From 007733967dcffd0845aeec869cf3ea55e31b497d Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Mon, 1 Feb 2016 00:28:59 -0800 Subject: [PATCH 01/46] Implementing Random Driver Bidding --- Frames/MobTimerController.py | 4 + Frames/ScreenBlockerFrame.py | 14 ++-- Infrastructure/DojoManager.py | 123 ++++++++++++++++++++++++++++++ Infrastructure/MobberManager.py | 4 +- Infrastructure/SettingsManager.py | 22 +++++- MobTimer.cfg | 11 ++- MobTimer.py | 6 ++ 7 files changed, 175 insertions(+), 9 deletions(-) create mode 100644 Infrastructure/DojoManager.py diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index 9c434bf..eff1cd8 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -8,6 +8,7 @@ from Frames.ScreenBlockerFrame import ScreenBlockerFrame from Frames.TransparentCountdownFrame import TransparentCountdownFrame from Infrastructure.CountdownManager import CountdownManager +from Infrastructure.DojoManager import DojoManager from Infrastructure.MobberManager import MobberManager from Infrastructure.PlatformUtility import PlatformUtility from Infrastructure.ScreenUtility import ScreenUtility @@ -79,6 +80,9 @@ def __init__(self, *args, **kwargs): self.bind_all("", self.launch_transparent_countdown_if_blocking) self.time_options_manager.set_countdown_time(self.settings_manager.get_timer_minutes(), self.settings_manager.get_timer_seconds()) + self.dojo_manager = DojoManager(self) + + def launch_transparent_countdown_if_blocking(self, event): if self.frame_is_screen_blocking(): self.show_transparent_countdown_frame() diff --git a/Frames/ScreenBlockerFrame.py b/Frames/ScreenBlockerFrame.py index 96abd12..2c9d447 100644 --- a/Frames/ScreenBlockerFrame.py +++ b/Frames/ScreenBlockerFrame.py @@ -35,11 +35,15 @@ def mobber_list_change_callback(self, mobber_list, driver_index, navigator_index for index in range(0, mobber_list.__len__()): tags = () name = mobber_list[index] - if index == driver_index: - tags = (TAGNAME_CURRENT_MOBBER) - name += " <= Current" - if index == navigator_index: - name += " <= Next" + if self.controller.settings_manager.get_dojo_enabled: + if self.controller.dojo_manager.station_drivers.__contains__(name): + name += " <= {}".format(self.controller.dojo_manager.station_drivers[name]) + else: + if index == driver_index: + tags = (TAGNAME_CURRENT_MOBBER) + name += " <= Current" + if index == navigator_index: + name += " <= Next" self.names_list.insert('', END, text=name, tags=tags) diff --git a/Infrastructure/DojoManager.py b/Infrastructure/DojoManager.py new file mode 100644 index 0000000..7de3f39 --- /dev/null +++ b/Infrastructure/DojoManager.py @@ -0,0 +1,123 @@ +import _thread +import random + +import paho.mqtt.publish as mqtt_pub +import paho.mqtt.client as mqtt +import json + +RANDOM_TOPIC_BID = "RandomTopicBid" + +START_RANDOM_DRIVER_BID = "StartRandomDriverBid" + +MOBBER_LIST = "MobberList" + +TIME_CHANGE = "TimeChange" + + +class DojoManager(object): + def __init__(self, controller): + if not controller.settings_manager.get_dojo_enabled(): + return + self.switch_dictionary = { + MOBBER_LIST: self.sub_mobber_list, + TIME_CHANGE: self.sub_time_change, + START_RANDOM_DRIVER_BID: self.sub_start_random_driver_bid, + RANDOM_TOPIC_BID: self.sub_random_topic_bid + } + self.station_drivers = {} + self.controller = controller + self.dojo_broker = self.controller.settings_manager.get_dojo_broker() + self.dojo_port = self.controller.settings_manager.get_dojo_port() + self.dojo_mob_station_name = self.controller.settings_manager.get_dojo_mob_station_name() + self.dojo_session_id = self.controller.settings_manager.get_dojo_session_id() + self.dojo_topic_root = self.controller.settings_manager.get_dojo_topic_root() + self.controller.mobber_manager.subscribe_to_mobber_list_change(self.publish_mobber_list_changes) + self.controller.time_options_manager.subscribe_to_timechange(self.publish_time_change) + self.subscribe_to_time_change() + + def publish_time_change(self, time_string, minutes, seconds): + topic = self.generate_topic(TIME_CHANGE) + payload_dictionary = { + "minutes": minutes, + "seconds": seconds + } + payload = json.dumps(payload_dictionary) + self.publish(topic, payload) + + def publish_mobber_list_changes(self, mobber_list, driver_index, next_driver_index): + topic = self.generate_topic(MOBBER_LIST) + payload_object = { + "driver_index": driver_index, + "next_driver_index": next_driver_index, + "mobber_list": mobber_list + } + payload = json.dumps(payload_object) + self.publish(topic, payload) + + def publish(self, topic, payload): + _thread.start_new_thread(self.thread_publish, (topic, payload)) + + def thread_publish(self, topic, payload): + mqtt_pub.single(topic, hostname=self.dojo_broker, port=self.dojo_port, payload=payload) + + def subscribe_to_time_change(self): + _thread.start_new_thread(self.subscribe_to_dojo, ()) + + def on_connect(self, client, userdata, flags, rc): + topic = "{}/{}/#".format(self.dojo_topic_root, self.dojo_session_id) + client.subscribe(topic) + + def on_message(self, client, userdata, msg): + topic_parts = msg.topic.split('/') + topic_root = topic_parts[0] + session_id = topic_parts[1] + station_name = topic_parts[2] + message_type = topic_parts[3] + self.switch_statement_dictionary_trick(station_name, message_type, msg.payload) + + def switch_statement_dictionary_trick(self, station_name, message_type, payload): + self.switch_dictionary[message_type](station_name, message_type, payload) + + def sub_mobber_list(self, station_name, message_type, payload): + if not station_name == self.dojo_mob_station_name: + payload_dictionary = json.loads(payload.decode("utf-8")) + for mobber in payload_dictionary["mobber_list"]: + self.controller.mobber_manager.add_mobber(mobber) + topic = self.generate_topic(START_RANDOM_DRIVER_BID) + self.publish(topic, "") + + def generate_topic(self, message_type): + topic = "{}/{}/{}/{}".format(self.dojo_topic_root, self.dojo_session_id, self.dojo_mob_station_name, + message_type) + return topic + + def sub_time_change(self, station_name, message_type, payload): + if not station_name == self.dojo_mob_station_name: + payload_dictionary = json.loads(payload.decode("utf-8")) + minutes = payload_dictionary["minutes"] + seconds = payload_dictionary["seconds"] + if not ( + self.controller.time_options_manager.minutes == minutes and self.controller.time_options_manager.seconds == seconds): + self.controller.time_options_manager.set_countdown_time(minutes, seconds) + + def sub_start_random_driver_bid(self, station_name, message_type, payload): + print(message_type) + # topic = self.generate_topic(RANDOM_TOPIC_BID) + # if self.controller.mobber_manager.mobber_list.__len__() > 1: + # payload_dictionary = {"bid": random.randint(0, 100), + # "mobber": random.choice(self.controller.mobber_manager.mobber_list)} + # self.publish(topic, json.dumps(payload_dictionary)) + + def sub_random_topic_bid(self, station_name, message_type, payload): + print(payload) + # payload_dictionary = json.loads(payload.decode("utf-8")) + # self.station_drivers[payload_dictionary["mobber"]] = station_name + # print(self.station_drivers) + # self.controller.mobber_manager.fire_time_change_callbacks() + + def subscribe_to_dojo(self): + client = mqtt.Client() + client.on_connect = self.on_connect + client.on_message = self.on_message + client.connect(self.dojo_broker, self.dojo_port, 60) + client.loop_forever() diff --git a/Infrastructure/MobberManager.py b/Infrastructure/MobberManager.py index 9d98dc5..0713139 100644 --- a/Infrastructure/MobberManager.py +++ b/Infrastructure/MobberManager.py @@ -13,7 +13,8 @@ def mobber_count(self): return self.mobber_list.__len__() def add_mobber(self, mobber_name): - if str(mobber_name).strip() != "": + clean_mobber_name = str(mobber_name).strip() + if clean_mobber_name != "" and not self.mobber_list.__contains__(clean_mobber_name): self.mobber_list.append(mobber_name) self.fire_time_change_callbacks() @@ -84,3 +85,4 @@ def rewind_driver(self): self.driver_index = mobber_count - 1 self.update_next_driver_index() self.fire_time_change_callbacks() + diff --git a/Infrastructure/SettingsManager.py b/Infrastructure/SettingsManager.py index 404d9b3..2584fb5 100644 --- a/Infrastructure/SettingsManager.py +++ b/Infrastructure/SettingsManager.py @@ -7,6 +7,7 @@ class SettingsManager(object): TIMER_SETTINGS = "TIMER SETTINGS" CONTINUE_SCREEN_BLOCKER_SETTINGS = "CONTINUE SCREEN BLOCKER SETTINGS" SCREEN_BLOCKER_SETTINGS = "SCREEN BLOCKER SETTINGS" + CODE_DOJO = "CODE DOJO" def __init__(self): self.config = configparser.ConfigParser() @@ -16,6 +17,7 @@ def __init__(self): self.screen_blocker_settings = self.config[SettingsManager.SCREEN_BLOCKER_SETTINGS] self.general_settings_ = self.config[SettingsManager.GENERAL_SETTINGS] self.timer_settings_ = self.config[SettingsManager.TIMER_SETTINGS] + self.code_dojo = self.config[SettingsManager.CODE_DOJO] def get_transparent_window_screen_size_percent(self): return self.window_settings_.getfloat("size percentage", 0.3) @@ -84,4 +86,22 @@ def get_timer_extension_count(self): return self.timer_settings_.getint("extension count", 2) def get_general_enable_tips(self): - return self.general_settings_.getboolean("enable tips", True) \ No newline at end of file + return self.general_settings_.getboolean("enable tips", True) + + def get_dojo_enabled(self): + return self.code_dojo.getboolean("enable dojo mode", False) + + def get_dojo_broker(self): + return self.code_dojo.get("broker", "iot.eclipse.org") + + def get_dojo_port(self): + return self.code_dojo.getint("port", 1883) + + def get_dojo_mob_station_name(self): + return self.code_dojo.get("mob station name", "NewName") + + def get_dojo_session_id(self): + return self.code_dojo.get("session id","1337") + + def get_dojo_topic_root(self): + return self.code_dojo.get("topic root", "MobTimer") diff --git a/MobTimer.cfg b/MobTimer.cfg index 1a6f4ee..9ec9707 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -23,11 +23,18 @@ use logo image = False logo image name = company-logo.png auto theme logo = False - [TIMER SETTINGS] minutes = 5 seconds = 0 extension enabled = False extension minutes = 0 extension seconds = 30 -extension count = 1 \ No newline at end of file +extension count = 1 + +[CODE DOJO] +enable dojo mode = True +broker = iot.eclipse.org +port = 1883 +mob station name = NewName +session id = 1337 +topic root = MobTimer \ No newline at end of file diff --git a/MobTimer.py b/MobTimer.py index cd9dda5..387c7fa 100644 --- a/MobTimer.py +++ b/MobTimer.py @@ -2,3 +2,9 @@ root = MobTimerController() root.mainloop() + + + + + + From ebc331ec9a1b6adfc16b08f15d5ad3f4fa758cd1 Mon Sep 17 00:00:00 2001 From: Lynn Langit Date: Thu, 11 Feb 2016 13:42:51 -0800 Subject: [PATCH 02/46] adding vscode hotkeys tip file --- Tips/vscodehotkeys | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Tips/vscodehotkeys diff --git a/Tips/vscodehotkeys b/Tips/vscodehotkeys new file mode 100644 index 0000000..0b0f0e5 --- /dev/null +++ b/Tips/vscodehotkeys @@ -0,0 +1,17 @@ +ctrl+p - open command pallette, search project files +alt+left - return to previous location +alt+shift+f - format code +alt+shift+right - widen selection scope +alt+shift+left - narrow selection scope +alt+up - move selected lines up +alt+down - move selected lines down +alt+shift+up - copy selected lines up +alt+shift+down - copy selected lines down +ctrl+shift+f - search all project files +ctrl+tab - move through recent file list +ctrl+shift+tab - move backwards through recent file list +f12 - rename variable +ctrl+enter - insert line below +ctrl+shift+enter - insert line above +ctrl+shift+l - select all instances of selected text +ctrl+shift+k - delete lines From e08022aab20c92ec05a5637aa661ec3f3688f12f Mon Sep 17 00:00:00 2001 From: Lynn Langit Date: Thu, 11 Feb 2016 13:47:16 -0800 Subject: [PATCH 03/46] vscoderefactoring tips --- Tips/vscoderefactoring | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Tips/vscoderefactoring diff --git a/Tips/vscoderefactoring b/Tips/vscoderefactoring new file mode 100644 index 0000000..fd1eb5b --- /dev/null +++ b/Tips/vscoderefactoring @@ -0,0 +1,7 @@ +Convert to Member Function - converts named function to object prototype function +Convert to Named Function - converts variable-assigned anonymous function to standard named function +Export Function - adds export declaration to module for selected function +Wrap in Condition - wraps selected code in an if block +Wrap in Executed Function - wraps selected code in a function which is invoked on the next line +Wrap in Function - wraps selected code in a function declaration +Wrap if IIFE - wraps selected code in an immediately invoked function expression From f34451ca17adb3e59c15ea7fcc6ac00dda3ed233 Mon Sep 17 00:00:00 2001 From: Lynn Langit Date: Thu, 11 Feb 2016 13:50:36 -0800 Subject: [PATCH 04/46] vscodejsrefactorsnippets --- vscodejsfactorsnippets | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 vscodejsfactorsnippets diff --git a/vscodejsfactorsnippets b/vscodejsfactorsnippets new file mode 100644 index 0000000..9af9073 --- /dev/null +++ b/vscodejsfactorsnippets @@ -0,0 +1,10 @@ +anon - anonymous function template +cond - if block template +export - single-line export template +exportObj - object literal export template +fn - function declaration template +iife - immediately invoked function expression template +mfn - object prototype member function template +proto - object template with prototype declaration +require - require statement template +strict - adds 'use strict'; at cursor location From c584f0b6fa91d2842e0d88070d9e23c69cf32857 Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Fri, 26 Feb 2016 08:06:58 -0800 Subject: [PATCH 05/46] Mob team synchronized via MQTT. --- Frames/MobTimerController.py | 8 ++- Frames/ScreenBlockerFrame.py | 6 +- Infrastructure/DojoManager.py | 71 ++++++++++++------- Infrastructure/MobberManager.py | 30 +++++--- Infrastructure/TimeSettingsManager.py | 8 +-- MobTimer.cfg | 2 +- .../MobberManager/TestsMobberManager.py | 3 +- ...to_mobber_list_changes_random.approved.txt | 25 +++---- .../TestsTimeOptionsManager.py | 4 +- 9 files changed, 93 insertions(+), 64 deletions(-) diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index eff1cd8..9e3d968 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -33,8 +33,8 @@ def __init__(self, *args, **kwargs): self.timer_extension_count = self.settings_manager.get_timer_extension_count() self.extensions_used = 0 atexit.register(self.session_manager.clear_sessions) - if self.session_manager.get_active_sessions().__len__() > 0: - self.quit_and_destroy_session() + # if self.session_manager.get_active_sessions().__len__() > 0: + # self.quit_and_destroy_session() self.session_manager.create_session() self.iconbitmap(default='time-bomb.ico') @@ -83,7 +83,7 @@ def __init__(self, *args, **kwargs): self.dojo_manager = DojoManager(self) - def launch_transparent_countdown_if_blocking(self, event): + def launch_transparent_countdown_if_blocking(self, event = None): if self.frame_is_screen_blocking(): self.show_transparent_countdown_frame() @@ -160,6 +160,7 @@ def remove_title_bar(self): container.master.overrideredirect(1) def set_always_on_top(self): + return for container in self.containers: container.master.wm_attributes("-topmost", True) if PlatformUtility.platform_is_mac(): @@ -169,6 +170,7 @@ def set_always_on_top(self): container.master.focus_force() def set_full_screen_always_on_top(self): + return self.set_always_on_top() self.remove_title_bar() self.disable_resizing() diff --git a/Frames/ScreenBlockerFrame.py b/Frames/ScreenBlockerFrame.py index 2c9d447..c93a3de 100644 --- a/Frames/ScreenBlockerFrame.py +++ b/Frames/ScreenBlockerFrame.py @@ -47,7 +47,7 @@ def mobber_list_change_callback(self, mobber_list, driver_index, navigator_index self.names_list.insert('', END, text=name, tags=tags) - def time_change_callback(self, time, minutes, seconds): + def time_change_callback(self, time, minutes, seconds, origin_station_name=None): self.label_minutes['text'] = "{0:0>2}".format(minutes) self.label_seconds['text'] = "{0:0>2}".format(seconds) @@ -203,11 +203,9 @@ def remove_mobber_if_screen_blocking(self, event): def add_default_team(self, event): team = self.settings_manager.get_general_team().split(',') randomize_team = self.settings_manager.get_randomize_team() - self.mobber_manager.clear() if randomize_team: random.shuffle(team) - for member in team: - self.mobber_manager.add_mobber(member) + self.mobber_manager.set_mobber_list(team) def focus_mobber_entry(self): self.add_mobber_entry.focus_set() diff --git a/Infrastructure/DojoManager.py b/Infrastructure/DojoManager.py index 7de3f39..7f6fd9d 100644 --- a/Infrastructure/DojoManager.py +++ b/Infrastructure/DojoManager.py @@ -1,45 +1,62 @@ import _thread import random +import uuid import paho.mqtt.publish as mqtt_pub import paho.mqtt.client as mqtt import json -RANDOM_TOPIC_BID = "RandomTopicBid" - -START_RANDOM_DRIVER_BID = "StartRandomDriverBid" - MOBBER_LIST = "MobberList" TIME_CHANGE = "TimeChange" +SAY_HELLO = "SayHello" + +START_TIMER = "StartTimer" + class DojoManager(object): def __init__(self, controller): if not controller.settings_manager.get_dojo_enabled(): return + + self.time_change_increment = 0 + self.mobber_change_increment = 0 + self.session_id = uuid.uuid4().__str__() + + self.switch_dictionary = { MOBBER_LIST: self.sub_mobber_list, TIME_CHANGE: self.sub_time_change, - START_RANDOM_DRIVER_BID: self.sub_start_random_driver_bid, - RANDOM_TOPIC_BID: self.sub_random_topic_bid + SAY_HELLO: self.sub_say_hello, + START_TIMER: self.sub_start_timer, } self.station_drivers = {} + self.other_stations = [] self.controller = controller self.dojo_broker = self.controller.settings_manager.get_dojo_broker() self.dojo_port = self.controller.settings_manager.get_dojo_port() - self.dojo_mob_station_name = self.controller.settings_manager.get_dojo_mob_station_name() + self.dojo_mob_station_name = self.controller.settings_manager.get_dojo_mob_station_name() + uuid.uuid4().__str__() self.dojo_session_id = self.controller.settings_manager.get_dojo_session_id() self.dojo_topic_root = self.controller.settings_manager.get_dojo_topic_root() self.controller.mobber_manager.subscribe_to_mobber_list_change(self.publish_mobber_list_changes) self.controller.time_options_manager.subscribe_to_timechange(self.publish_time_change) self.subscribe_to_time_change() + self.say_hello() + + def say_hello(self): + topic = self.generate_topic(SAY_HELLO) + self.publish(topic, "") - def publish_time_change(self, time_string, minutes, seconds): + def publish_time_change(self, time_string, minutes, seconds, origin_station_name=None): topic = self.generate_topic(TIME_CHANGE) + station_name = self.dojo_mob_station_name + if origin_station_name is not None: + return payload_dictionary = { "minutes": minutes, - "seconds": seconds + "seconds": seconds, + "station_name": station_name } payload = json.dumps(payload_dictionary) self.publish(topic, payload) @@ -73,6 +90,7 @@ def on_message(self, client, userdata, msg): session_id = topic_parts[1] station_name = topic_parts[2] message_type = topic_parts[3] + print("on_message",msg.topic) self.switch_statement_dictionary_trick(station_name, message_type, msg.payload) def switch_statement_dictionary_trick(self, station_name, message_type, payload): @@ -81,39 +99,37 @@ def switch_statement_dictionary_trick(self, station_name, message_type, payload) def sub_mobber_list(self, station_name, message_type, payload): if not station_name == self.dojo_mob_station_name: payload_dictionary = json.loads(payload.decode("utf-8")) - for mobber in payload_dictionary["mobber_list"]: - self.controller.mobber_manager.add_mobber(mobber) - topic = self.generate_topic(START_RANDOM_DRIVER_BID) - self.publish(topic, "") + mobber_list = payload_dictionary["mobber_list"] + print("sub_mobber_list",mobber_list) + self.controller.mobber_manager.set_mobber_list(mobber_list) def generate_topic(self, message_type): topic = "{}/{}/{}/{}".format(self.dojo_topic_root, self.dojo_session_id, self.dojo_mob_station_name, message_type) + print("generate_topic",topic) return topic def sub_time_change(self, station_name, message_type, payload): + print(payload) if not station_name == self.dojo_mob_station_name: payload_dictionary = json.loads(payload.decode("utf-8")) minutes = payload_dictionary["minutes"] seconds = payload_dictionary["seconds"] + origin_station_name = payload_dictionary["station_name"] if not ( self.controller.time_options_manager.minutes == minutes and self.controller.time_options_manager.seconds == seconds): - self.controller.time_options_manager.set_countdown_time(minutes, seconds) + self.controller.time_options_manager.set_countdown_time(minutes, seconds, origin_station_name) - def sub_start_random_driver_bid(self, station_name, message_type, payload): - print(message_type) - # topic = self.generate_topic(RANDOM_TOPIC_BID) - # if self.controller.mobber_manager.mobber_list.__len__() > 1: - # payload_dictionary = {"bid": random.randint(0, 100), - # "mobber": random.choice(self.controller.mobber_manager.mobber_list)} - # self.publish(topic, json.dumps(payload_dictionary)) + def sub_say_hello(self, station_name, message_type, payload): + if not station_name == self.dojo_mob_station_name: + if not self.other_stations.__contains__(station_name): + self.other_stations.append(station_name) + topic = self.generate_topic(SAY_HELLO) + self.publish(topic, "") - def sub_random_topic_bid(self, station_name, message_type, payload): - print(payload) - # payload_dictionary = json.loads(payload.decode("utf-8")) - # self.station_drivers[payload_dictionary["mobber"]] = station_name - # print(self.station_drivers) - # self.controller.mobber_manager.fire_time_change_callbacks() + def sub_start_timer(self, station_name, message_type, payload): + if not station_name == self.dojo_mob_station_name: + self.controller.launch_transparent_countdown_if_blocking() def subscribe_to_dojo(self): client = mqtt.Client() @@ -121,3 +137,4 @@ def subscribe_to_dojo(self): client.on_message = self.on_message client.connect(self.dojo_broker, self.dojo_port, 60) client.loop_forever() + diff --git a/Infrastructure/MobberManager.py b/Infrastructure/MobberManager.py index 0713139..a060bb6 100644 --- a/Infrastructure/MobberManager.py +++ b/Infrastructure/MobberManager.py @@ -16,35 +16,36 @@ def add_mobber(self, mobber_name): clean_mobber_name = str(mobber_name).strip() if clean_mobber_name != "" and not self.mobber_list.__contains__(clean_mobber_name): self.mobber_list.append(mobber_name) - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() def get_mobbers(self): return self.mobber_list def remove_mobber(self, remove_mobber_index): - if self.mobber_count() == 0: return + if self.mobber_count() == 0: + return del self.mobber_list[remove_mobber_index] - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() def move_mobber_up(self, swap_index): if self.mobber_count() == 0: return destination_index = swap_index - 1 self.mobber_list[swap_index], self.mobber_list[destination_index] = self.mobber_list[destination_index], \ self.mobber_list[swap_index] - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() def move_mobber_down(self, swap_index): if self.mobber_count() == 0: return destination_index = (swap_index + 1) % self.mobber_list.__len__() self.mobber_list[swap_index], self.mobber_list[destination_index] = self.mobber_list[destination_index], \ self.mobber_list[swap_index] - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() def subscribe_to_mobber_list_change(self, mobber_list_change_callback): self.mobber_list_change_callbacks.append(mobber_list_change_callback) - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() - def fire_time_change_callbacks(self): + def fire_mobber_list_change_callbacks(self): self.update_next_driver_index() for mobber_list_change_callback in self.mobber_list_change_callbacks: if mobber_list_change_callback: @@ -52,7 +53,7 @@ def fire_time_change_callbacks(self): def clear(self): self.mobber_list = [] - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() def switch_next_driver(self): mobber_count = self.mobber_list.__len__() @@ -61,7 +62,7 @@ def switch_next_driver(self): self.driver_index = self.next_driver_index else: self.driver_index = (self.driver_index + 1) % mobber_count - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() def update_next_driver_index(self): mobber_count = self.mobber_list.__len__() @@ -84,5 +85,14 @@ def rewind_driver(self): if self.driver_index < 0: self.driver_index = mobber_count - 1 self.update_next_driver_index() - self.fire_time_change_callbacks() + self.fire_mobber_list_change_callbacks() + + def set_mobber_list(self, mobber_list): + if self.mobber_list != mobber_list: + self.mobber_list = [] + for mobber_name in mobber_list: + clean_mobber_name = str(mobber_name).strip() + if clean_mobber_name != "" and not self.mobber_list.__contains__(clean_mobber_name): + self.mobber_list.append(mobber_name) + self.fire_mobber_list_change_callbacks() diff --git a/Infrastructure/TimeSettingsManager.py b/Infrastructure/TimeSettingsManager.py index 6e94b01..b2e498d 100644 --- a/Infrastructure/TimeSettingsManager.py +++ b/Infrastructure/TimeSettingsManager.py @@ -29,12 +29,12 @@ def subscribe_to_timechange(self, time_change_callback): self.time_change_callbacks.append(time_change_callback) self.fire_time_change_callbacks() - def fire_time_change_callbacks(self): + def fire_time_change_callbacks(self, origin_station_name=None): for time_change_callback in self.time_change_callbacks: if time_change_callback: - time_change_callback(self.get_time_string(), self.minutes, self.seconds) + time_change_callback(self.get_time_string(), self.minutes, self.seconds, origin_station_name) - def set_countdown_time(self, minutes, seconds): + def set_countdown_time(self, minutes, seconds, origin_station_name=None): self.minutes = minutes self.seconds = seconds - self.fire_time_change_callbacks() \ No newline at end of file + self.fire_time_change_callbacks(origin_station_name) \ No newline at end of file diff --git a/MobTimer.cfg b/MobTimer.cfg index 9ec9707..7e4c317 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -33,7 +33,7 @@ extension count = 1 [CODE DOJO] enable dojo mode = True -broker = iot.eclipse.org +broker = localhost port = 1883 mob station name = NewName session id = 1337 diff --git a/tests/Infrastructure/MobberManager/TestsMobberManager.py b/tests/Infrastructure/MobberManager/TestsMobberManager.py index 520556d..bbbcfd9 100644 --- a/tests/Infrastructure/MobberManager/TestsMobberManager.py +++ b/tests/Infrastructure/MobberManager/TestsMobberManager.py @@ -30,7 +30,7 @@ def test_add_mobber_joe_chris_joe__remove_joe_has_joe_chris(self): mobber_manager = MobberManager() mobber_manager.add_mobber("Joe") mobber_manager.add_mobber("Chris") - mobber_manager.add_mobber("Joe") + mobber_manager.add_mobber("John") mobber_manager.remove_mobber(2) result = ["Joe", "Chris"] self.assertEqual(mobber_manager.get_mobbers(), result) @@ -178,6 +178,7 @@ def time_change_callback(mobber_list, driver_index, navigator_index): mobber_manager.switch_next_driver() mobber_manager.switch_next_driver() mobber_manager.switch_next_driver() + mobber_manager.set_mobber_list(["Hello", "Eric", "Joe"]) mobber_manager.switch_next_driver() mobber_manager.switch_next_driver() mobber_manager.remove_mobber(2) diff --git a/tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt b/tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt index 57355ed..de4de02 100644 --- a/tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt +++ b/tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt @@ -9,15 +9,16 @@ Action 7:Joe, Chris (Next), Sam, John (Driver), Bill, Action 8:Joe, Chris (Driver), Sam (Next), John, Bill, Action 9:Joe, Chris, Sam (Driver), John (Next), Bill, Action 10:Joe, Chris (Next), Sam, John (Driver), Bill, -Action 11:Joe, Chris (Driver), Sam (Next), John, Bill, -Action 12:Joe, Chris, Sam (Driver), John, Bill (Next), -Action 13:Joe, Chris (Next), John (Driver), Bill, -Action 14:Chris, John (Next), Bill (Driver), -Action 15:Chris (Next), John (Driver), Bill, -Action 16:Chris, John (Driver), Bill, Seth (Next), -Action 17:John, Chris (Driver), Bill, Seth (Next), -Action 18:John, Chris (Driver), Bill, Seth, Fredrick (Next), -Action 19:John, Bill (Driver), Chris, Seth, Fredrick (Next), -Action 20:John, Chris (Driver), Seth (Next), Fredrick, -Action 21:Chris, Seth (Driver), Fredrick (Next), -Action 22:Seth (Next), Fredrick (Driver), +Action 11:Hello, Eric (Next), Joe, +Action 12:Hello, Eric (Driver), Joe (Next), +Action 13:Hello, Eric (Next), Joe (Driver), +Action 14:Hello (Driver), Eric (Next), +Action 15:Eric (Driver) (Next), +Action 16:Eric (Driver) (Next), +Action 17:Eric (Driver), Seth (Next), +Action 18:Seth (Driver), Eric (Next), +Action 19:Seth (Driver), Eric, Fredrick (Next), +Action 20:Seth (Driver), Fredrick (Next), Eric, +Action 21:Seth (Driver), Eric (Next), +Action 22:Eric (Driver) (Next), +Action 23: diff --git a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py index 75da203..3342fcf 100644 --- a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py +++ b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py @@ -58,7 +58,7 @@ def test_subscribe_to_time_changes(self): time_options_manager = TimeSettingsManager() result = {"result": "time"} - def time_change_callback(time, minutes, seconds): + def time_change_callback(time, minutes, seconds,origin_station_name): result["result"] += " " + time time_options_manager.subscribe_to_timechange(time_change_callback) @@ -71,7 +71,7 @@ def test_subscribe_to_time_changes_complex(self): time_options_manager = TimeSettingsManager() result = {"result": "Time Options after Change:", "increment" : 0} - def time_change_callback(time, minutes, seconds): + def time_change_callback(time, minutes, seconds,origin_station_name): result["increment"] += 1 result["result"] += "\n Change " + result["increment"].__str__() + "| " + time From 8782a9aa8ac14d011322bd178eb1f14cce104d87 Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Fri, 26 Feb 2016 08:23:20 -0800 Subject: [PATCH 06/46] UUID now in topic to allow for different instances on the same session with the same name --- Infrastructure/DojoManager.py | 38 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/Infrastructure/DojoManager.py b/Infrastructure/DojoManager.py index 7f6fd9d..36ab9b4 100644 --- a/Infrastructure/DojoManager.py +++ b/Infrastructure/DojoManager.py @@ -36,7 +36,8 @@ def __init__(self, controller): self.controller = controller self.dojo_broker = self.controller.settings_manager.get_dojo_broker() self.dojo_port = self.controller.settings_manager.get_dojo_port() - self.dojo_mob_station_name = self.controller.settings_manager.get_dojo_mob_station_name() + uuid.uuid4().__str__() + self.dojo_station_uuid = uuid.uuid4().__str__() + self.dojo_mob_station_name = self.controller.settings_manager.get_dojo_mob_station_name() self.dojo_session_id = self.controller.settings_manager.get_dojo_session_id() self.dojo_topic_root = self.controller.settings_manager.get_dojo_topic_root() self.controller.mobber_manager.subscribe_to_mobber_list_change(self.publish_mobber_list_changes) @@ -51,12 +52,14 @@ def say_hello(self): def publish_time_change(self, time_string, minutes, seconds, origin_station_name=None): topic = self.generate_topic(TIME_CHANGE) station_name = self.dojo_mob_station_name + station_uuid = self.dojo_station_uuid if origin_station_name is not None: return payload_dictionary = { "minutes": minutes, "seconds": seconds, - "station_name": station_name + "station_name": station_name, + "station_uuid": station_uuid } payload = json.dumps(payload_dictionary) self.publish(topic, payload) @@ -88,30 +91,31 @@ def on_message(self, client, userdata, msg): topic_parts = msg.topic.split('/') topic_root = topic_parts[0] session_id = topic_parts[1] - station_name = topic_parts[2] - message_type = topic_parts[3] - print("on_message",msg.topic) - self.switch_statement_dictionary_trick(station_name, message_type, msg.payload) + station_uuid = topic_parts[2] + station_name = topic_parts[3] + message_type = topic_parts[4] + print("on_message",msg.topic,"station_uuid",station_uuid) + self.switch_statement_dictionary_trick(station_uuid,station_name, message_type, msg.payload) - def switch_statement_dictionary_trick(self, station_name, message_type, payload): - self.switch_dictionary[message_type](station_name, message_type, payload) + def switch_statement_dictionary_trick(self, station_uuid,station_name, message_type, payload): + self.switch_dictionary[message_type](station_uuid,station_name, message_type, payload) - def sub_mobber_list(self, station_name, message_type, payload): - if not station_name == self.dojo_mob_station_name: + def sub_mobber_list(self, station_uuid,station_name, message_type, payload): + if not station_uuid == self.dojo_station_uuid: payload_dictionary = json.loads(payload.decode("utf-8")) mobber_list = payload_dictionary["mobber_list"] print("sub_mobber_list",mobber_list) self.controller.mobber_manager.set_mobber_list(mobber_list) def generate_topic(self, message_type): - topic = "{}/{}/{}/{}".format(self.dojo_topic_root, self.dojo_session_id, self.dojo_mob_station_name, + topic = "{}/{}/{}/{}/{}".format(self.dojo_topic_root, self.dojo_session_id,self.dojo_station_uuid, self.dojo_mob_station_name, message_type) print("generate_topic",topic) return topic - def sub_time_change(self, station_name, message_type, payload): + def sub_time_change(self, station_uuid, station_name, message_type, payload): print(payload) - if not station_name == self.dojo_mob_station_name: + if not station_uuid == self.dojo_station_uuid: payload_dictionary = json.loads(payload.decode("utf-8")) minutes = payload_dictionary["minutes"] seconds = payload_dictionary["seconds"] @@ -120,15 +124,15 @@ def sub_time_change(self, station_name, message_type, payload): self.controller.time_options_manager.minutes == minutes and self.controller.time_options_manager.seconds == seconds): self.controller.time_options_manager.set_countdown_time(minutes, seconds, origin_station_name) - def sub_say_hello(self, station_name, message_type, payload): - if not station_name == self.dojo_mob_station_name: + def sub_say_hello(self, station_uuid,station_name, message_type, payload): + if not station_uuid == self.dojo_station_uuid: if not self.other_stations.__contains__(station_name): self.other_stations.append(station_name) topic = self.generate_topic(SAY_HELLO) self.publish(topic, "") - def sub_start_timer(self, station_name, message_type, payload): - if not station_name == self.dojo_mob_station_name: + def sub_start_timer(self, station_uuid, station_name, message_type, payload): + if not station_uuid == self.dojo_station_uuid: self.controller.launch_transparent_countdown_if_blocking() def subscribe_to_dojo(self): From c654ca880e690717bed713bc5211ee47c5cc164b Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Sun, 6 Mar 2016 23:16:50 -0800 Subject: [PATCH 07/46] Mid Adding Dojo Mode Dojo Mode Disabled in Config File. --- Frames/MobTimerController.py | 4 +- Frames/ScreenBlockerFrame.py | 4 +- Infrastructure/CountdownManager.py | 2 +- Infrastructure/DojoManager.py | 55 ++++++++++--------- .../6d45f552-e434-11e5-b958-20c9d042e8c0 | 0 MobTimer.cfg | 2 +- README.md | 2 + 7 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 Infrastructure/Sessions/6d45f552-e434-11e5-b958-20c9d042e8c0 diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index 9e3d968..af854bf 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -160,7 +160,7 @@ def remove_title_bar(self): container.master.overrideredirect(1) def set_always_on_top(self): - return + for container in self.containers: container.master.wm_attributes("-topmost", True) if PlatformUtility.platform_is_mac(): @@ -170,7 +170,7 @@ def set_always_on_top(self): container.master.focus_force() def set_full_screen_always_on_top(self): - return + self.set_always_on_top() self.remove_title_bar() self.disable_resizing() diff --git a/Frames/ScreenBlockerFrame.py b/Frames/ScreenBlockerFrame.py index c93a3de..316ad4b 100644 --- a/Frames/ScreenBlockerFrame.py +++ b/Frames/ScreenBlockerFrame.py @@ -35,12 +35,12 @@ def mobber_list_change_callback(self, mobber_list, driver_index, navigator_index for index in range(0, mobber_list.__len__()): tags = () name = mobber_list[index] - if self.controller.settings_manager.get_dojo_enabled: + if self.controller.settings_manager.get_dojo_enabled(): if self.controller.dojo_manager.station_drivers.__contains__(name): name += " <= {}".format(self.controller.dojo_manager.station_drivers[name]) else: if index == driver_index: - tags = (TAGNAME_CURRENT_MOBBER) + tags = TAGNAME_CURRENT_MOBBER name += " <= Current" if index == navigator_index: name += " <= Next" diff --git a/Infrastructure/CountdownManager.py b/Infrastructure/CountdownManager.py index ec038e6..7fed3d5 100644 --- a/Infrastructure/CountdownManager.py +++ b/Infrastructure/CountdownManager.py @@ -8,7 +8,7 @@ def __init__(self, root_tk_app): self.minutes = 0 self.seconds = 0 self.time_change_callbacks = [] - self.count_down_total = datetime.timedelta(minutes=10, seconds=0) + self.count_down_total = datetime.timedelta(days=-1, minutes=0, seconds=0) self.root_tk_app = root_tk_app self.refresh_timer() diff --git a/Infrastructure/DojoManager.py b/Infrastructure/DojoManager.py index 36ab9b4..6741dc9 100644 --- a/Infrastructure/DojoManager.py +++ b/Infrastructure/DojoManager.py @@ -1,18 +1,17 @@ import _thread import random import uuid - import paho.mqtt.publish as mqtt_pub import paho.mqtt.client as mqtt import json -MOBBER_LIST = "MobberList" +TOPIC_MOBBER_LIST = "MobberList" -TIME_CHANGE = "TimeChange" +TOPIC_TIME_CHANGE = "TimeChange" -SAY_HELLO = "SayHello" +TOPIC_SAY_HELLO = "SayHello" -START_TIMER = "StartTimer" +TOPIC_START_TIMER = "StartTimer" class DojoManager(object): @@ -24,12 +23,11 @@ def __init__(self, controller): self.mobber_change_increment = 0 self.session_id = uuid.uuid4().__str__() - self.switch_dictionary = { - MOBBER_LIST: self.sub_mobber_list, - TIME_CHANGE: self.sub_time_change, - SAY_HELLO: self.sub_say_hello, - START_TIMER: self.sub_start_timer, + TOPIC_MOBBER_LIST: self.sub_mobber_list, + TOPIC_TIME_CHANGE: self.sub_time_change, + TOPIC_SAY_HELLO: self.sub_say_hello, + TOPIC_START_TIMER: self.sub_start_timer, } self.station_drivers = {} self.other_stations = [] @@ -42,15 +40,22 @@ def __init__(self, controller): self.dojo_topic_root = self.controller.settings_manager.get_dojo_topic_root() self.controller.mobber_manager.subscribe_to_mobber_list_change(self.publish_mobber_list_changes) self.controller.time_options_manager.subscribe_to_timechange(self.publish_time_change) + self.controller.countdown_manager.subscribe_to_time_changes(self.publish_countdown_change) self.subscribe_to_time_change() self.say_hello() def say_hello(self): - topic = self.generate_topic(SAY_HELLO) + topic = self.generate_topic(TOPIC_SAY_HELLO) + self.publish(topic, "") + + def publish_countdown_change(self, negative_if_time_expired, minutes, seconds, origin_station_name=None): + if negative_if_time_expired < 0: return + print("publish_countdown_change" , minutes, seconds) + topic = self.generate_topic(TOPIC_START_TIMER) self.publish(topic, "") def publish_time_change(self, time_string, minutes, seconds, origin_station_name=None): - topic = self.generate_topic(TIME_CHANGE) + topic = self.generate_topic(TOPIC_TIME_CHANGE) station_name = self.dojo_mob_station_name station_uuid = self.dojo_station_uuid if origin_station_name is not None: @@ -65,7 +70,7 @@ def publish_time_change(self, time_string, minutes, seconds, origin_station_name self.publish(topic, payload) def publish_mobber_list_changes(self, mobber_list, driver_index, next_driver_index): - topic = self.generate_topic(MOBBER_LIST) + topic = self.generate_topic(TOPIC_MOBBER_LIST) payload_object = { "driver_index": driver_index, "next_driver_index": next_driver_index, @@ -94,23 +99,24 @@ def on_message(self, client, userdata, msg): station_uuid = topic_parts[2] station_name = topic_parts[3] message_type = topic_parts[4] - print("on_message",msg.topic,"station_uuid",station_uuid) - self.switch_statement_dictionary_trick(station_uuid,station_name, message_type, msg.payload) + print("on_message", msg.topic, "station_uuid", station_uuid) + self.switch_statement_dictionary_trick(station_uuid, station_name, message_type, msg.payload) - def switch_statement_dictionary_trick(self, station_uuid,station_name, message_type, payload): - self.switch_dictionary[message_type](station_uuid,station_name, message_type, payload) + def switch_statement_dictionary_trick(self, station_uuid, station_name, message_type, payload): + self.switch_dictionary[message_type](station_uuid, station_name, message_type, payload) - def sub_mobber_list(self, station_uuid,station_name, message_type, payload): + def sub_mobber_list(self, station_uuid, station_name, message_type, payload): if not station_uuid == self.dojo_station_uuid: payload_dictionary = json.loads(payload.decode("utf-8")) mobber_list = payload_dictionary["mobber_list"] - print("sub_mobber_list",mobber_list) + print("sub_mobber_list", mobber_list) self.controller.mobber_manager.set_mobber_list(mobber_list) def generate_topic(self, message_type): - topic = "{}/{}/{}/{}/{}".format(self.dojo_topic_root, self.dojo_session_id,self.dojo_station_uuid, self.dojo_mob_station_name, - message_type) - print("generate_topic",topic) + topic = "{}/{}/{}/{}/{}".format(self.dojo_topic_root, self.dojo_session_id, self.dojo_station_uuid, + self.dojo_mob_station_name, + message_type) + print("generate_topic", topic) return topic def sub_time_change(self, station_uuid, station_name, message_type, payload): @@ -124,11 +130,11 @@ def sub_time_change(self, station_uuid, station_name, message_type, payload): self.controller.time_options_manager.minutes == minutes and self.controller.time_options_manager.seconds == seconds): self.controller.time_options_manager.set_countdown_time(minutes, seconds, origin_station_name) - def sub_say_hello(self, station_uuid,station_name, message_type, payload): + def sub_say_hello(self, station_uuid, station_name, message_type, payload): if not station_uuid == self.dojo_station_uuid: if not self.other_stations.__contains__(station_name): self.other_stations.append(station_name) - topic = self.generate_topic(SAY_HELLO) + topic = self.generate_topic(TOPIC_SAY_HELLO) self.publish(topic, "") def sub_start_timer(self, station_uuid, station_name, message_type, payload): @@ -141,4 +147,3 @@ def subscribe_to_dojo(self): client.on_message = self.on_message client.connect(self.dojo_broker, self.dojo_port, 60) client.loop_forever() - diff --git a/Infrastructure/Sessions/6d45f552-e434-11e5-b958-20c9d042e8c0 b/Infrastructure/Sessions/6d45f552-e434-11e5-b958-20c9d042e8c0 new file mode 100644 index 0000000..e69de29 diff --git a/MobTimer.cfg b/MobTimer.cfg index 7e4c317..3eee6d0 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -32,7 +32,7 @@ extension seconds = 30 extension count = 1 [CODE DOJO] -enable dojo mode = True +enable dojo mode = False broker = localhost port = 1883 mob station name = NewName diff --git a/README.md b/README.md index 953e6fe..cf1b239 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Mob Programming Timer – Python # [Download Now](https://github.com/MobProgramming/MobTimer.Python/releases) +## How to install and basic use video +[![MobTimer Install and Tutorial Video](http://img.youtube.com/vi/GxMP8SI6v0k/0.jpg)](http://www.youtube.com/watch?v=GxMP8SI6v0k) ## What is Mob Programming? All the brilliant people working on the same thing, at the same time, in the same space, and on the same computer. Find out more at the [Mob Programming site]( http://mobprogramming.org/). From 6ff6bf7e1a2f3fcb56842a538baf44812f83864a Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Wed, 9 Mar 2016 23:21:18 -0800 Subject: [PATCH 08/46] Unobtrusive mode added --- Frames/MobTimerController.py | 30 +++++++++++++------ Frames/TransparentCountdownFrame.py | 24 +++++++++++++-- ...0 => 00010203-0405-0607-0809-0a0b0c0d0e0f} | 0 Infrastructure/SettingsManager.py | 3 ++ Infrastructure/ThemeManager.py | 18 +++++++++++ MobTimer.cfg | 3 +- 6 files changed, 65 insertions(+), 13 deletions(-) rename Infrastructure/Sessions/{6d45f552-e434-11e5-b958-20c9d042e8c0 => 00010203-0405-0607-0809-0a0b0c0d0e0f} (100%) diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index af854bf..242ed63 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -22,6 +22,7 @@ class MobTimerController(Tk): def __init__(self, *args, **kwargs): Tk.__init__(self, *args, **kwargs) + self.toggle_transparent_frame_position_function = self.toggle_transparent_frame_position_enabled self.transparent_frame_monitor_index = 0 self.transparent_frame_position_index = 0 self.settings_manager = SettingsManager() @@ -33,8 +34,8 @@ def __init__(self, *args, **kwargs): self.timer_extension_count = self.settings_manager.get_timer_extension_count() self.extensions_used = 0 atexit.register(self.session_manager.clear_sessions) - # if self.session_manager.get_active_sessions().__len__() > 0: - # self.quit_and_destroy_session() + if self.session_manager.get_active_sessions().__len__() > 0: + self.quit_and_destroy_session() self.session_manager.create_session() self.iconbitmap(default='time-bomb.ico') @@ -91,6 +92,8 @@ def frame_is_screen_blocking(self): return self.last_frame == ScreenBlockerFrame or self.last_frame == MinimalScreenBlockerFrame def show_minimal_screen_blocker_frame(self): + self.toggle_transparent_frame_position_function = self.toggle_transparent_frame_position_enabled + self.theme_manager.reset_flashing_background_colors_to_normal() if self.last_frame != MinimalScreenBlockerFrame: self.launch_blocking_Frame(MinimalScreenBlockerFrame) self.mobber_manager.switch_next_driver() @@ -122,7 +125,8 @@ def show_frame(self, frame_class): container.deiconify() else: container.withdraw() - + container.focus_force() + container.focus_set() return switched_frames def show_screen_blocker_frame(self): @@ -207,22 +211,30 @@ def unfade_app(self): for controller in self.containers: controller.master.attributes("-alpha", 1) + def flash_unobtrusive_transparent_countdown_frame(self): + self.toggle_transparent_frame_position_function = self.toggle_transparent_frame_position_disabled + for container in self.containers: + container.master.attributes("-alpha", 1) + container.focus_force() + container.focus_set() + + def toggle_transparent_frame_position_disabled(self): + pass + def toggle_transparent_frame_position(self, e=None): if self.state() == "withdrawn": return + self.toggle_transparent_frame_position_function() + def toggle_transparent_frame_position_enabled(self): monitors = ScreenUtility.get_monitors_or_default(self) monitor = monitors[self.transparent_frame_monitor_index] - screenwidth = monitor.width screenheight = monitor.height - self.set_always_on_top() self.remove_title_bar() self.disable_resizing() - size_percentage = self.settings_manager.get_transparent_window_screen_size_percent() - window_width = int(screenwidth * size_percentage) window_height = int(screenheight * size_percentage) if self.transparent_frame_position_index == 0: @@ -231,8 +243,8 @@ def toggle_transparent_frame_position(self, e=None): else: self.transparent_frame_position = monitor.x + 0 self.transparent_frame_position_index = (self.transparent_frame_position_index + 1) % 2 - - bottom_left_screen = "{}x{}+{}+{}".format(window_width, window_height, self.transparent_frame_position, monitor.y + + bottom_left_screen = "{}x{}+{}+{}".format(window_width, window_height, self.transparent_frame_position, + monitor.y + screenheight - window_height) self.geometry(bottom_left_screen) diff --git a/Frames/TransparentCountdownFrame.py b/Frames/TransparentCountdownFrame.py index 08583a6..5f4807b 100644 --- a/Frames/TransparentCountdownFrame.py +++ b/Frames/TransparentCountdownFrame.py @@ -6,7 +6,7 @@ class TransparentCountdownFrame(ttk.Frame): def __init__(self, master, controller, time_options_manager, mobber_manager, countdown_manager, settings_manager, - tips_manager,theme_manager, + tips_manager, theme_manager, **kwargs): super().__init__(master, **kwargs) self.master = master @@ -18,11 +18,23 @@ def __init__(self, master, controller, time_options_manager, mobber_manager, cou self.mobber_manager.subscribe_to_mobber_list_change(self.mobber_list_change_callback) self.countdown_manager = countdown_manager self.countdown_manager.subscribe_to_time_changes(self.update_time_change_callback) + self.unobtrusive_mode_enabled = self.settings_manager.get_general_enable_unobtrusive_mode() + + + def reset_theme_and_continue_mobbing(self): + self.controller.show_minimal_screen_blocker_frame() + self.controller.theme_manager.reset_flashing_background_colors_to_normal() def update_time_change_callback(self, days, minutes, seconds): - if (days < 0 or minutes < 0 or seconds < 0) and not self.controller.frame_is_screen_blocking(): - self.controller.show_minimal_screen_blocker_frame() self.label_time['text'] = "{0:0>2}:{1:0>2}".format(minutes, seconds) + if (days < 0 or minutes < 0 or seconds < 0) and not self.controller.frame_is_screen_blocking(): + if self.unobtrusive_mode_enabled: + self.controller.flash_unobtrusive_transparent_countdown_frame() + self.controller.theme_manager.toggle_flashing_background_style() + self.label_time['text'] = "Click&Rotate!" + else: + self.controller.show_minimal_screen_blocker_frame() + def mobber_list_change_callback(self, mobber_list, driver_index, navigator_index): mobber_count = mobber_list.__len__() @@ -59,6 +71,12 @@ def create_frame_content(self): self.label_driver.pack() row_index += 1 + + self.bind("", lambda event: self.reset_theme_and_continue_mobbing()) + self.label_time.bind("", lambda event: self.reset_theme_and_continue_mobbing()) + self.label_navigator.bind("", lambda event: self.reset_theme_and_continue_mobbing()) + self.label_driver.bind("", lambda event: self.reset_theme_and_continue_mobbing()) + def get_navigator_text(self, name): return "Next: " + name diff --git a/Infrastructure/Sessions/6d45f552-e434-11e5-b958-20c9d042e8c0 b/Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f similarity index 100% rename from Infrastructure/Sessions/6d45f552-e434-11e5-b958-20c9d042e8c0 rename to Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f diff --git a/Infrastructure/SettingsManager.py b/Infrastructure/SettingsManager.py index 2584fb5..3af1cc2 100644 --- a/Infrastructure/SettingsManager.py +++ b/Infrastructure/SettingsManager.py @@ -88,6 +88,9 @@ def get_timer_extension_count(self): def get_general_enable_tips(self): return self.general_settings_.getboolean("enable tips", True) + def get_general_enable_unobtrusive_mode(self): + return self.general_settings_.getboolean("enable unobtrusive mode", False) + def get_dojo_enabled(self): return self.code_dojo.getboolean("enable dojo mode", False) diff --git a/Infrastructure/ThemeManager.py b/Infrastructure/ThemeManager.py index fb46af2..4c5cd1d 100644 --- a/Infrastructure/ThemeManager.py +++ b/Infrastructure/ThemeManager.py @@ -28,6 +28,24 @@ def __init__(self): self.button_color = "#FFFFFF" self.text_color = "#000000" self.highlight_color = "#aaaaaa" + self.normal_background_flash_color = True + + def toggle_flashing_background_style(self): + style = ttk.Style() + style.theme_use('default') + self.normal_background_flash_color = not self.normal_background_flash_color + if self.normal_background_flash_color: + style.configure('TFrame', background= self.background_color) + style.configure('TLabel', background=self.background_color, foreground=self.text_color) + else: + style.configure('TFrame', background= self.highlight_color) + style.configure('TLabel', background=self.highlight_color, foreground=self.background_color) + + def reset_flashing_background_colors_to_normal(self): + style = ttk.Style() + style.theme_use('default') + style.configure('TFrame', background= self.background_color) + style.configure('TLabel', background=self.background_color, foreground=self.text_color) def set_theme(self, theme_name): cfg_file = "Themes/{}.cfg".format(theme_name) diff --git a/MobTimer.cfg b/MobTimer.cfg index 3eee6d0..3bab691 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -3,7 +3,7 @@ mouse wheel seconds delta = 1 click seconds delta = 5 [TRANSPARENT WINDOW SETTINGS] -size percentage = 0.12 +size percentage = 0.14 alpha percentage = 0.4 count down timer font size = 30 driver font size = 15 @@ -22,6 +22,7 @@ randomize next driver = False use logo image = False logo image name = company-logo.png auto theme logo = False +enable unobtrusive mode = True [TIMER SETTINGS] minutes = 5 From d101c5afd3da484d92f4df6a711d0d2210643a09 Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Sun, 20 Mar 2016 18:22:56 -0700 Subject: [PATCH 09/46] Updated setup to delete existing files and removed TCL import. --- Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f | 0 setup.py | 5 ++--- 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f diff --git a/Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f b/Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f deleted file mode 100644 index e69de29..0000000 diff --git a/setup.py b/setup.py index 38a337b..82af84d 100644 --- a/setup.py +++ b/setup.py @@ -10,10 +10,10 @@ def get_file_paths(folder_name): file_paths = [f for f in listdir(folder_name) if isfile(join(folder_name, f))] return ['{}/{}'.format(folder_name, i) for i in file_paths] + [os.remove(x) for x in get_file_paths('dist')] theme_file_paths = get_file_paths("Themes") tips_file_paths = get_file_paths("Tips") image_file_paths = get_file_paths("Images") - tcl__path = '{}\\tcl\\tcl8.6\\init.tcl'.format(os.path.dirname(sys.executable)) setup(windows=[{ "script": 'MobTimer.py', "icon_resources": [(1, "time-bomb.ico")] @@ -22,8 +22,7 @@ def get_file_paths(folder_name): ('', ["MobTimer.cfg", "company-logo.png", "time-bomb.ico"]), ('Themes', theme_file_paths), ('Tips', tips_file_paths), - ('Images', image_file_paths), - tcl__path] + ('Images', image_file_paths)] , requires=['screeninfo']) def create_mac_app(): From 443b8422b2e5c70fb75d347cad8a02834cbb924b Mon Sep 17 00:00:00 2001 From: Chris Lucian Date: Tue, 22 Mar 2016 14:13:45 -0700 Subject: [PATCH 10/46] Stab at mac compatability --- Frames/MobTimerController.py | 4 +++- Frames/TransparentCountdownFrame.py | 5 +++-- MobTimer.cfg | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index 242ed63..3fde2a7 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -38,7 +38,9 @@ def __init__(self, *args, **kwargs): self.quit_and_destroy_session() self.session_manager.create_session() - self.iconbitmap(default='time-bomb.ico') + if sys.platform != 'darwin': + self.iconbitmap(default='time-bomb.ico') + self.countdown_manager.subscribe_to_time_changes(self.show_screen_blocker_when_session_interupted) self.theme_manager = ThemeManager() diff --git a/Frames/TransparentCountdownFrame.py b/Frames/TransparentCountdownFrame.py index 5f4807b..7b1ee8e 100644 --- a/Frames/TransparentCountdownFrame.py +++ b/Frames/TransparentCountdownFrame.py @@ -22,8 +22,9 @@ def __init__(self, master, controller, time_options_manager, mobber_manager, cou def reset_theme_and_continue_mobbing(self): - self.controller.show_minimal_screen_blocker_frame() - self.controller.theme_manager.reset_flashing_background_colors_to_normal() + if self.unobtrusive_mode_enabled: + self.controller.show_minimal_screen_blocker_frame() + self.controller.theme_manager.reset_flashing_background_colors_to_normal() def update_time_change_callback(self, days, minutes, seconds): self.label_time['text'] = "{0:0>2}:{1:0>2}".format(minutes, seconds) diff --git a/MobTimer.cfg b/MobTimer.cfg index 3bab691..1b70237 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -22,7 +22,7 @@ randomize next driver = False use logo image = False logo image name = company-logo.png auto theme logo = False -enable unobtrusive mode = True +enable unobtrusive mode = False [TIMER SETTINGS] minutes = 5 From 830f2f49cced52c4aca068a381d2f6cf0253c508 Mon Sep 17 00:00:00 2001 From: David Alpert Date: Sat, 6 Aug 2016 19:26:59 +0800 Subject: [PATCH 11/46] adds requirements.txt to document dependencies - these were partially pieced together by hand and partially filled in by pycharm's quick fix process. this set is confimed working on my machine in the pycharm IDE and also by command line via build.bat generating an exe which runs successfully. This is despite generating the following warnings: Error: Namespace packages not yet supported: Skipping package 'win32com.gen_py' 14 missing Modules ------------------ ? PIL._imagingagg imported from PIL.ImageDraw ? PyQt4 imported from PIL.ImageQt ? PyQt5 imported from PIL.ImageQt ? _grabscreen imported from PIL.ImageGrab ? _imaging_gif imported from PIL.GifImagePlugin ? backports imported from setuptools.ssl_support ? packaging imported from pkg_resources ? setuptools_svn imported from setuptools.command.egg_info ? sha imported from dns.entropy ? testing imported from cffi.recompiler ? urllib.pathname2url imported from setuptools.compat ? urllib.splittag imported from setuptools.compat ? urllib.url2pathname imported from setuptools.compat ? wincertstore imported from setuptools.ssl_support --- requirements.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..927cdca --- /dev/null +++ b/requirements.txt @@ -0,0 +1,13 @@ +approvaltests==0.1.12 +py2exe==0.9.2.2 +pysmb==1.1.15 +paho-mqtt==1.1 +pyreadline==2.1 +screeninfo==0.2.1 +pypiwin32==219 +dnspython==1.14.0 +Pillow==2.4.0 +pyasn1==0.1.9 +cffi==1.7.0 +pycparser==2.14 +pysha3==0.3 From f6677687551c7294a161b3d7b6450e2cef370e6f Mon Sep 17 00:00:00 2001 From: David Alpert Date: Sun, 7 Aug 2016 00:30:06 +0800 Subject: [PATCH 12/46] removing user-specific files from source control - as per https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 --- .gitignore | 3 + .idea/workspace.xml | 1466 ------------------------------------------- 2 files changed, 3 insertions(+), 1466 deletions(-) delete mode 100644 .idea/workspace.xml diff --git a/.gitignore b/.gitignore index ba74660..8241498 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ var/ pip-log.txt pip-delete-this-directory.txt +# idea user-specific files +.idea/workspace.xml + # Unit test / coverage reports htmlcov/ .tox/ diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index af12eab..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,1466 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Python - - - - - PyTypeCheckerInspection - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1448960251969 - - - 1448960352426 - - - 1449128502810 - - - 1449208527550 - - - 1449217011568 - - - 1449560317680 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From fd0147514b5328a5b2ebdf6168df1e92c9568fe7 Mon Sep 17 00:00:00 2001 From: David Alpert Date: Sun, 7 Aug 2016 00:35:08 +0800 Subject: [PATCH 13/46] fixes a crash in build.bat when the 'dist' folder did not exist - The error was: Traceback (most recent call last): File setup.py, line 61, in create_windows_exe() File setup.py, line 13, in create_windows_exe [os.remove(x) for x in get_file_paths('dist')] File setup.py, line 10, in get_file_paths file_paths = [f for f in listdir(folder_name) if isfile(join(folder_name, f))] FileNotFoundError: [WinError 3] The system cannot find the path specified: 'dist' - The error occured only on first checkout; once the dist folder was built this error did not occur. --- setup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 82af84d..a9a7e3e 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,11 @@ def create_windows_exe(): # Get theme files and store them in a list def get_file_paths(folder_name): - file_paths = [f for f in listdir(folder_name) if isfile(join(folder_name, f))] - return ['{}/{}'.format(folder_name, i) for i in file_paths] + if os.path.isdir(folder_name): + file_paths = [f for f in listdir(folder_name) if isfile(join(folder_name, f))] + return ['{}/{}'.format(folder_name, i) for i in file_paths] + else: + return [] [os.remove(x) for x in get_file_paths('dist')] theme_file_paths = get_file_paths("Themes") From d7a7e909aadc79e973d3e27404c67970983e4eb3 Mon Sep 17 00:00:00 2001 From: Argon Date: Fri, 2 Sep 2016 08:48:07 -0700 Subject: [PATCH 14/46] ignoring pycharm ide files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ba74660..51d567b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ docs/_build/ # PyBuilder target/ + +#PyCharm +.idea/ \ No newline at end of file From 81c1e18dad59d48659887ecb185f293a3621bc72 Mon Sep 17 00:00:00 2001 From: Argon Date: Fri, 2 Sep 2016 08:54:41 -0700 Subject: [PATCH 15/46] Removing JetBrains files. --- .gitignore | 3 +- .idea/MobTimer.iml | 12 - .idea/dictionaries/Chris.xml | 8 - .idea/encodings.xml | 6 - .idea/inspectionProfiles/Project_Default.xml | 15 - .../inspectionProfiles/profiles_settings.xml | 7 - .idea/misc.xml | 14 - .idea/modules.xml | 8 - .idea/vcs.xml | 6 - .idea/workspace.xml | 1466 ----------------- 10 files changed, 2 insertions(+), 1543 deletions(-) delete mode 100644 .idea/MobTimer.iml delete mode 100644 .idea/dictionaries/Chris.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.gitignore b/.gitignore index 51d567b..6275668 100644 --- a/.gitignore +++ b/.gitignore @@ -57,4 +57,5 @@ docs/_build/ target/ #PyCharm -.idea/ \ No newline at end of file +.idea/ +.idea/MobTimer.iml \ No newline at end of file diff --git a/.idea/MobTimer.iml b/.idea/MobTimer.iml deleted file mode 100644 index 2d874a9..0000000 --- a/.idea/MobTimer.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/dictionaries/Chris.xml b/.idea/dictionaries/Chris.xml deleted file mode 100644 index 2b33936..0000000 --- a/.idea/dictionaries/Chris.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - mobber - mobbers - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index fc41869..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b31283..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 97db8bc..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 627b78f..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index af12eab..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,1466 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Python - - - - - PyTypeCheckerInspection - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1448960251969 - - - 1448960352426 - - - 1449128502810 - - - 1449208527550 - - - 1449217011568 - - - 1449560317680 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From a3cb9a1dd32522176c3553724ecee6dab1845b5d Mon Sep 17 00:00:00 2001 From: Argon Date: Fri, 2 Sep 2016 09:00:08 -0700 Subject: [PATCH 16/46] more pycharm ide updates --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6275668..b8098fd 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,3 @@ target/ #PyCharm .idea/ -.idea/MobTimer.iml \ No newline at end of file From cf87293a323a24fa5941df08a9ac1d6c8d01bb09 Mon Sep 17 00:00:00 2001 From: Argon Date: Fri, 2 Sep 2016 16:53:52 -0700 Subject: [PATCH 17/46] Updated Requirements for latest versions of libraries. --- requirements.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 927cdca..358f627 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,13 @@ approvaltests==0.1.12 py2exe==0.9.2.2 -pysmb==1.1.15 -paho-mqtt==1.1 +pysmb==1.1.18 +paho-mqtt==1.2 pyreadline==2.1 screeninfo==0.2.1 pypiwin32==219 dnspython==1.14.0 -Pillow==2.4.0 +Pillow==3.3.1 +Pillow-PIL==0.1.dev0 pyasn1==0.1.9 cffi==1.7.0 pycparser==2.14 From bdcc2a0710c4759c31c9fdda3890da18f3cbe4a1 Mon Sep 17 00:00:00 2001 From: Argon Date: Fri, 2 Sep 2016 16:54:54 -0700 Subject: [PATCH 18/46] Removed redundant git ignore element --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 327fb4e..b8098fd 100644 --- a/.gitignore +++ b/.gitignore @@ -33,9 +33,6 @@ var/ pip-log.txt pip-delete-this-directory.txt -# idea user-specific files -.idea/workspace.xml - # Unit test / coverage reports htmlcov/ .tox/ From 0cdec4e485f7968b1ca92681c97fa28effd73840 Mon Sep 17 00:00:00 2001 From: Argon Date: Wed, 7 Sep 2016 08:45:26 -0700 Subject: [PATCH 19/46] Added Mob Timer tips and cleaned up other tips from pull request. --- Tips/MobTimer | 19 +++++++++++++++++++ .../VsCodeJsRefactorSnippets | 0 2 files changed, 19 insertions(+) create mode 100644 Tips/MobTimer rename vscodejsfactorsnippets => Tips/VsCodeJsRefactorSnippets (100%) diff --git a/Tips/MobTimer b/Tips/MobTimer new file mode 100644 index 0000000..b1e0267 --- /dev/null +++ b/Tips/MobTimer @@ -0,0 +1,19 @@ +You can set the mouse wheel seconds delta in the MobTimer.cfg file. +You can set the mouse click seconds delta delta in the MobTimer.cfg file. +You can set the transparent window size percentage in the MobTimer.cfg file. +You can set the transparent window alpha percentage in the MobTimer.cfg file. +You can set the transparent window count down timer font size in the MobTimer.cfg file. +You can set the transparent window driver text font size in the MobTimer.cfg file. +You can set the transparent window next driver text font size in the MobTimer.cfg file. +You can set the continue screen alpha percentage in the MobTimer.cfg file. +You can set the continue screen to show current time in the MobTimer.cfg file. +You can set the theme to Candy, Dark, Foo, Forest, Lava, Pastel, and Sky in the MobTimer.cfg file. +You can create your own color themes in the Themes folder. +You can disable these tips in the MobTimer.cfg file. +You can set your default team with comma delimited names in the MobTimer.cfg file. +You can enable randomize team in the MobTimer.cfg file. +You can enable randomize next driver in MobTimer.cfg file. +You can able your own logo image in the MobTimer.cfg file. +You can enable unobtrusive mode MobTimer.cfg file. (Instead of blocking the screen, show a small notification that the driver needs to switch) +You can set the default time in the MobTimer.cfg file. +You can enable time extensions in the MobTimer.cfg file. \ No newline at end of file diff --git a/vscodejsfactorsnippets b/Tips/VsCodeJsRefactorSnippets similarity index 100% rename from vscodejsfactorsnippets rename to Tips/VsCodeJsRefactorSnippets From dcbbf32d849cf48f72106082e9427eedc84154cd Mon Sep 17 00:00:00 2001 From: Argon Date: Tue, 13 Sep 2016 09:04:12 -0700 Subject: [PATCH 20/46] Approvals Fixed --- .../Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f | 0 Infrastructure/SettingsManager.py | 3 +++ MobTimer.cfg | 1 + .../CountdownManager/TestsCountdownManager.py | 6 ++++-- ...nager.test_subscribe_to_time_changes.approved.txt} | 0 .../MobberManager/TestsMobberManager.py | 11 ++++++----- ...est_subscribe_to_mobber_list_changes.approved.txt} | 0 ...scribe_to_mobber_list_changes_random.approved.txt} | 0 .../TimeOptionsManager/TestsTimeOptionsManager.py | 7 +++++-- ...st_subscribe_to_time_changes_complex.approved.txt} | 0 tests/Infrastructure/TipsManager/TestTipsManager.py | 5 +++-- 11 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f rename tests/Infrastructure/CountdownManager/{tests.Infrastructure.CountdownManager.TestsCountdownManager.test_subscribe_to_time_changes.approved.txt => TestsCountdownManager.test_subscribe_to_time_changes.approved.txt} (100%) rename tests/Infrastructure/MobberManager/{tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt => TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt} (100%) rename tests/Infrastructure/MobberManager/{tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt => TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt} (100%) rename tests/Infrastructure/TimeOptionsManager/{tests.Infrastructure.TimeOptionsManager.TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt => TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt} (100%) diff --git a/Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f b/Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f new file mode 100644 index 0000000..e69de29 diff --git a/Infrastructure/SettingsManager.py b/Infrastructure/SettingsManager.py index 3af1cc2..4a9950f 100644 --- a/Infrastructure/SettingsManager.py +++ b/Infrastructure/SettingsManager.py @@ -108,3 +108,6 @@ def get_dojo_session_id(self): def get_dojo_topic_root(self): return self.code_dojo.get("topic root", "MobTimer") + + def get_general_enable_unobtrusive_mode_bouncing_screen(self): + return self.general_settings_.getboolean("enable unobtrusive mode bouncing screen", False) diff --git a/MobTimer.cfg b/MobTimer.cfg index 1b70237..298f23d 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -23,6 +23,7 @@ use logo image = False logo image name = company-logo.png auto theme logo = False enable unobtrusive mode = False +enable unobtrusive mode bouncing screen = True [TIMER SETTINGS] minutes = 5 diff --git a/tests/Infrastructure/CountdownManager/TestsCountdownManager.py b/tests/Infrastructure/CountdownManager/TestsCountdownManager.py index 8b7dbb3..cc0422b 100644 --- a/tests/Infrastructure/CountdownManager/TestsCountdownManager.py +++ b/tests/Infrastructure/CountdownManager/TestsCountdownManager.py @@ -3,12 +3,14 @@ import unittest from approvaltests import Approvals -from approvaltests.TextDiffReporter import TextDiffReporter +from approvaltests.GenericDiffReporterFactory import GenericDiffReporterFactory from Infrastructure.CountdownManager import CountdownManager class TestsCountdownManager(unittest.TestCase): + def setUp(self): + self.reporter = GenericDiffReporterFactory().get_first_working() def test_set_countdown_timer(self): countdown_manager = CountdownManager(None) @@ -37,7 +39,7 @@ def time_change_callback(days, minutes, seconds): countdown_manager.set_countdown_duration(853, 32) countdown_manager.set_countdown_duration(3, 62) - Approvals.verify(result["result"], TextDiffReporter()) + Approvals.verify(result["result"], self.reporter) if __name__ == '__main__': diff --git a/tests/Infrastructure/CountdownManager/tests.Infrastructure.CountdownManager.TestsCountdownManager.test_subscribe_to_time_changes.approved.txt b/tests/Infrastructure/CountdownManager/TestsCountdownManager.test_subscribe_to_time_changes.approved.txt similarity index 100% rename from tests/Infrastructure/CountdownManager/tests.Infrastructure.CountdownManager.TestsCountdownManager.test_subscribe_to_time_changes.approved.txt rename to tests/Infrastructure/CountdownManager/TestsCountdownManager.test_subscribe_to_time_changes.approved.txt diff --git a/tests/Infrastructure/MobberManager/TestsMobberManager.py b/tests/Infrastructure/MobberManager/TestsMobberManager.py index bbbcfd9..ad7034b 100644 --- a/tests/Infrastructure/MobberManager/TestsMobberManager.py +++ b/tests/Infrastructure/MobberManager/TestsMobberManager.py @@ -2,13 +2,14 @@ import random import unittest from approvaltests import Approvals -from approvaltests.TextDiffReporter import TextDiffReporter +from approvaltests.GenericDiffReporterFactory import GenericDiffReporterFactory from Infrastructure.MobberManager import MobberManager -os.environ["APPROVALS_TEXT_DIFF_TOOL"] = "C:\\Program Files\\TortoiseSVN\\bin\\TortoiseMerge.exe" - class TestsMobberManager(unittest.TestCase): + def setUp(self): + self.reporter = GenericDiffReporterFactory().get_first_working() + def test_empty_mobber_manager_has_no_items(self): mobber_manager = MobberManager() self.assertEqual(mobber_manager.mobber_count(), 0) @@ -147,7 +148,7 @@ def time_change_callback(mobber_list, driver_index, navigator_index): mobber_manager.remove_mobber(0) mobber_manager.remove_mobber(0) - Approvals.verify(result["result"], TextDiffReporter()) + Approvals.verify(result["result"], self.reporter) def test_subscribe_to_mobber_list_changes_random(self): random.seed(0) @@ -192,7 +193,7 @@ def time_change_callback(mobber_list, driver_index, navigator_index): mobber_manager.remove_mobber(0) mobber_manager.remove_mobber(0) - Approvals.verify(result["result"], TextDiffReporter()) + Approvals.verify(result["result"], self.reporter) def test_navigator1_driver0_index(self): mobber_manager = MobberManager() diff --git a/tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt b/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt similarity index 100% rename from tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt rename to tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt diff --git a/tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt b/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt similarity index 100% rename from tests/Infrastructure/MobberManager/tests.Infrastructure.MobberManager.TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt rename to tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt diff --git a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py index 3342fcf..699d0de 100644 --- a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py +++ b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py @@ -2,12 +2,15 @@ import unittest from approvaltests import Approvals -from approvaltests.TextDiffReporter import TextDiffReporter +from approvaltests.GenericDiffReporterFactory import GenericDiffReporterFactory from Infrastructure.TimeSettingsManager import TimeSettingsManager class TestsTimeOptionsManager(unittest.TestCase): + def setUp(self): + self.reporter = GenericDiffReporterFactory().get_first_working() + def test_default_time_10_minutes(self): time_options_manager = TimeSettingsManager() result = time_options_manager.get_time_string() @@ -93,7 +96,7 @@ def time_change_callback(time, minutes, seconds,origin_station_name): time_options_manager.increment_minutes() time_options_manager.set_countdown_time(3, 14) - Approvals.verify(result["result"], TextDiffReporter()) + Approvals.verify(result["result"], self.reporter) if __name__ == '__main__': os.environ["APPROVALS_TEXT_DIFF_TOOL"] = "meld" diff --git a/tests/Infrastructure/TimeOptionsManager/tests.Infrastructure.TimeOptionsManager.TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt similarity index 100% rename from tests/Infrastructure/TimeOptionsManager/tests.Infrastructure.TimeOptionsManager.TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt rename to tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt diff --git a/tests/Infrastructure/TipsManager/TestTipsManager.py b/tests/Infrastructure/TipsManager/TestTipsManager.py index 43230c5..5d95c90 100644 --- a/tests/Infrastructure/TipsManager/TestTipsManager.py +++ b/tests/Infrastructure/TipsManager/TestTipsManager.py @@ -8,13 +8,14 @@ class TestsTipsManage(unittest.TestCase): def test_random_tip_from_file(self): seed = 0 - tips_manager = TipsManager(seed,sys.argv[1]) + print("!!!" , sys.path[1]) + tips_manager = TipsManager(seed,sys.path[1]) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips2.txt: Words\n') def test_random_tip_from_file_second(self): seed = 1 - tips_manager = TipsManager(seed,sys.argv[1]) + tips_manager = TipsManager(seed,sys.path[1]) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips.txt: Customer collaboration over contract negotiation\n') From 9152d51b1d6abff48d7bb48daa776d17cc51bac6 Mon Sep 17 00:00:00 2001 From: Argon Date: Wed, 14 Sep 2016 08:11:52 -0700 Subject: [PATCH 21/46] Updated random file path for new version of python. --- Infrastructure/TipsManager.py | 5 +++-- tests/Infrastructure/TipsManager/TestTipsManager.py | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Infrastructure/TipsManager.py b/Infrastructure/TipsManager.py index 50e8093..a99d622 100644 --- a/Infrastructure/TipsManager.py +++ b/Infrastructure/TipsManager.py @@ -12,9 +12,10 @@ def __init__(self, seed = None, root_directory=sys.argv[0]): random.seed(seed) def get_random_tip(self): - tips_folder = "Tips" + tips_folder = self.root_directory+ "/Tips" random_file = random.choice(os.listdir("%s" % tips_folder)) - return "{}: {}" .format(random_file, TipsManager.random_line(PathUtility.normalize_path(tips_folder + "\\" + random_file,self.root_directory))) + random_file_path = tips_folder + "\\" + random_file + return "{}: {}" .format(random_file, TipsManager.random_line(random_file_path)) @staticmethod def random_line(file_name): diff --git a/tests/Infrastructure/TipsManager/TestTipsManager.py b/tests/Infrastructure/TipsManager/TestTipsManager.py index 5d95c90..1d65039 100644 --- a/tests/Infrastructure/TipsManager/TestTipsManager.py +++ b/tests/Infrastructure/TipsManager/TestTipsManager.py @@ -8,7 +8,6 @@ class TestsTipsManage(unittest.TestCase): def test_random_tip_from_file(self): seed = 0 - print("!!!" , sys.path[1]) tips_manager = TipsManager(seed,sys.path[1]) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips2.txt: Words\n') From 39965f15f7d15b5f20de32342d6925f085eadc12 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 20 Oct 2021 07:50:49 -0700 Subject: [PATCH 22/46] WIP --- .gitignore | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b8098fd..8be5b0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ +# Created by .ignore support plugin (hsz.mobi) +### Python template # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] +*$py.class # C extensions *.so @@ -42,6 +45,7 @@ htmlcov/ nosetests.xml coverage.xml *,cover +.hypothesis/ # Translations *.mo @@ -49,6 +53,14 @@ coverage.xml # Django stuff: *.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy # Sphinx documentation docs/_build/ @@ -56,5 +68,84 @@ docs/_build/ # PyBuilder target/ -#PyCharm +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject +### VirtualEnv template +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml + +# Sensitive or high-churn files: +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml + .idea/ + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties From 67d229bb41a3eeee538e912b31cf38bde72e90f9 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 20 Oct 2021 07:54:08 -0700 Subject: [PATCH 23/46] WIP updating to python 2 to python 3 --- .vscode/settings.json | 16 +++++++++++ Frames/MobTimerController.py | 1 + Infrastructure/TipsManager.py | 6 ++-- README.md | 4 +++ requirements.txt | 28 +++++++++---------- ...ownManager.py => test_CountdownManager.py} | 9 ++---- ...est_subscribe_to_time_changes.approved.txt | 0 7 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 .vscode/settings.json rename tests/Infrastructure/CountdownManager/{TestsCountdownManager.py => test_CountdownManager.py} (81%) rename Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f => tests/Infrastructure/CountdownManager/test_CountdownManager.test_subscribe_to_time_changes.approved.txt (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e4a0637 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "workbench.colorCustomizations": { + "activityBar.background": "#263205", + "titleBar.activeBackground": "#354507", + "titleBar.activeForeground": "#F6FCE5" + }, + "python.testing.unittestArgs": [ + "-v", + "-s", + "./tests", + "-p", + "*test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} \ No newline at end of file diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index 3fde2a7..3de01c5 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -2,6 +2,7 @@ import os import uuid from tkinter import * +import sys from Frames.MinimalScreenBlockerFrame import MinimalScreenBlockerFrame from Frames.OuterFrame import OuterFrame diff --git a/Infrastructure/TipsManager.py b/Infrastructure/TipsManager.py index a99d622..3f84283 100644 --- a/Infrastructure/TipsManager.py +++ b/Infrastructure/TipsManager.py @@ -6,13 +6,13 @@ class TipsManager(object): - def __init__(self, seed = None, root_directory=sys.argv[0]): - self.root_directory = root_directory + def __init__(self, seed=None, root_directory=sys.argv[0]): + self.root_directory = "/".join(root_directory.split('/')[:-1]) if seed is not None: random.seed(seed) def get_random_tip(self): - tips_folder = self.root_directory+ "/Tips" + tips_folder = self.root_directory + "/Tips" random_file = random.choice(os.listdir("%s" % tips_folder)) random_file_path = tips_folder + "\\" + random_file return "{}: {}" .format(random_file, TipsManager.random_line(random_file_path)) diff --git a/README.md b/README.md index cf1b239..0c101fa 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,7 @@ To add a theme simply copy and existing theme. To use that theme, put the file n ## Project Links [Trello Kanban Board]( https://trello.com/b/THISIB9Q/mob-programming-timer-python) +# Todo +* Update to latest version of python +* Convert to single file distributable +* Create plugin infrastructure diff --git a/requirements.txt b/requirements.txt index 358f627..6be243d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,14 @@ -approvaltests==0.1.12 -py2exe==0.9.2.2 -pysmb==1.1.18 -paho-mqtt==1.2 -pyreadline==2.1 -screeninfo==0.2.1 -pypiwin32==219 -dnspython==1.14.0 -Pillow==3.3.1 -Pillow-PIL==0.1.dev0 -pyasn1==0.1.9 -cffi==1.7.0 -pycparser==2.14 -pysha3==0.3 +approvaltests +py2exe +pysmb +paho-mqtt +pyreadline +screeninfo +pypiwin32 +dnspython +Pillow +Pillow-PIL +pyasn1 +cffi +pycparser +pysha3 diff --git a/tests/Infrastructure/CountdownManager/TestsCountdownManager.py b/tests/Infrastructure/CountdownManager/test_CountdownManager.py similarity index 81% rename from tests/Infrastructure/CountdownManager/TestsCountdownManager.py rename to tests/Infrastructure/CountdownManager/test_CountdownManager.py index cc0422b..4f9c137 100644 --- a/tests/Infrastructure/CountdownManager/TestsCountdownManager.py +++ b/tests/Infrastructure/CountdownManager/test_CountdownManager.py @@ -2,15 +2,12 @@ import time import unittest -from approvaltests import Approvals -from approvaltests.GenericDiffReporterFactory import GenericDiffReporterFactory +from approvaltests.approvals import verify from Infrastructure.CountdownManager import CountdownManager -class TestsCountdownManager(unittest.TestCase): - def setUp(self): - self.reporter = GenericDiffReporterFactory().get_first_working() +class test_CountdownManager(unittest.TestCase): def test_set_countdown_timer(self): countdown_manager = CountdownManager(None) @@ -39,7 +36,7 @@ def time_change_callback(days, minutes, seconds): countdown_manager.set_countdown_duration(853, 32) countdown_manager.set_countdown_duration(3, 62) - Approvals.verify(result["result"], self.reporter) + verify(result["result"]) if __name__ == '__main__': diff --git a/Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f b/tests/Infrastructure/CountdownManager/test_CountdownManager.test_subscribe_to_time_changes.approved.txt similarity index 100% rename from Infrastructure/Sessions/00010203-0405-0607-0809-0a0b0c0d0e0f rename to tests/Infrastructure/CountdownManager/test_CountdownManager.test_subscribe_to_time_changes.approved.txt From efbd0021667a867e33163a9c11528f51bf7cfab0 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 20 Oct 2021 07:56:52 -0700 Subject: [PATCH 24/46] e updated gitignore for approval tests --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8be5b0f..8cbd216 100644 --- a/.gitignore +++ b/.gitignore @@ -149,3 +149,6 @@ com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties + +# For approvals +*.received.txt From b3fef2aef6efa3252ff9d7b9209911e45558e96e Mon Sep 17 00:00:00 2001 From: Pipeline Date: Fri, 22 Oct 2021 07:15:47 -0700 Subject: [PATCH 25/46] R upgrade from python 2 to python 3, which caused file path modifications --- Infrastructure/TipsManager.py | 5 ++++- .../CountdownManager/test_CountdownManager.py | 4 +--- ...ager.test_subscribe_to_time_changes.approved.txt | 0 ...{TestsMobberManager.py => test_MobberManager.py} | 11 +++-------- ...estsSessionManager.py => test_SessionManager.py} | 0 ...t_subscribe_to_time_changes_complex.approved.txt | 2 +- ...OptionsManager.py => test_TimeOptionsManager.py} | 7 ++----- .../{TestTipsManager.py => test_TipsManager.py} | 13 +++++++++++-- 8 files changed, 22 insertions(+), 20 deletions(-) delete mode 100644 tests/Infrastructure/CountdownManager/test_CountdownManager.test_subscribe_to_time_changes.approved.txt rename tests/Infrastructure/MobberManager/{TestsMobberManager.py => test_MobberManager.py} (96%) rename tests/Infrastructure/SessionManager/{TestsSessionManager.py => test_SessionManager.py} (100%) rename tests/Infrastructure/TimeOptionsManager/{TestsTimeOptionsManager.py => test_TimeOptionsManager.py} (93%) rename tests/Infrastructure/TipsManager/{TestTipsManager.py => test_TipsManager.py} (58%) diff --git a/Infrastructure/TipsManager.py b/Infrastructure/TipsManager.py index 3f84283..c78d64e 100644 --- a/Infrastructure/TipsManager.py +++ b/Infrastructure/TipsManager.py @@ -7,10 +7,13 @@ class TipsManager(object): def __init__(self, seed=None, root_directory=sys.argv[0]): - self.root_directory = "/".join(root_directory.split('/')[:-1]) + self.root_directory = self.go_up_dir(root_directory) if seed is not None: random.seed(seed) + def go_up_dir(self, root_directory): + return "/".join(root_directory.split('/')[:-1]) + def get_random_tip(self): tips_folder = self.root_directory + "/Tips" random_file = random.choice(os.listdir("%s" % tips_folder)) diff --git a/tests/Infrastructure/CountdownManager/test_CountdownManager.py b/tests/Infrastructure/CountdownManager/test_CountdownManager.py index 4f9c137..bf7c7df 100644 --- a/tests/Infrastructure/CountdownManager/test_CountdownManager.py +++ b/tests/Infrastructure/CountdownManager/test_CountdownManager.py @@ -1,5 +1,3 @@ -import datetime -import time import unittest from approvaltests.approvals import verify @@ -7,7 +5,7 @@ from Infrastructure.CountdownManager import CountdownManager -class test_CountdownManager(unittest.TestCase): +class TestsCountdownManager(unittest.TestCase): def test_set_countdown_timer(self): countdown_manager = CountdownManager(None) diff --git a/tests/Infrastructure/CountdownManager/test_CountdownManager.test_subscribe_to_time_changes.approved.txt b/tests/Infrastructure/CountdownManager/test_CountdownManager.test_subscribe_to_time_changes.approved.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/Infrastructure/MobberManager/TestsMobberManager.py b/tests/Infrastructure/MobberManager/test_MobberManager.py similarity index 96% rename from tests/Infrastructure/MobberManager/TestsMobberManager.py rename to tests/Infrastructure/MobberManager/test_MobberManager.py index ad7034b..d60493f 100644 --- a/tests/Infrastructure/MobberManager/TestsMobberManager.py +++ b/tests/Infrastructure/MobberManager/test_MobberManager.py @@ -1,15 +1,10 @@ -import os import random import unittest -from approvaltests import Approvals -from approvaltests.GenericDiffReporterFactory import GenericDiffReporterFactory +from approvaltests.approvals import verify from Infrastructure.MobberManager import MobberManager class TestsMobberManager(unittest.TestCase): - def setUp(self): - self.reporter = GenericDiffReporterFactory().get_first_working() - def test_empty_mobber_manager_has_no_items(self): mobber_manager = MobberManager() self.assertEqual(mobber_manager.mobber_count(), 0) @@ -148,7 +143,7 @@ def time_change_callback(mobber_list, driver_index, navigator_index): mobber_manager.remove_mobber(0) mobber_manager.remove_mobber(0) - Approvals.verify(result["result"], self.reporter) + verify(result["result"]) def test_subscribe_to_mobber_list_changes_random(self): random.seed(0) @@ -193,7 +188,7 @@ def time_change_callback(mobber_list, driver_index, navigator_index): mobber_manager.remove_mobber(0) mobber_manager.remove_mobber(0) - Approvals.verify(result["result"], self.reporter) + verify(result["result"]) def test_navigator1_driver0_index(self): mobber_manager = MobberManager() diff --git a/tests/Infrastructure/SessionManager/TestsSessionManager.py b/tests/Infrastructure/SessionManager/test_SessionManager.py similarity index 100% rename from tests/Infrastructure/SessionManager/TestsSessionManager.py rename to tests/Infrastructure/SessionManager/test_SessionManager.py diff --git a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt index c30ed55..86293ef 100644 --- a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt +++ b/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.test_subscribe_to_time_changes_complex.approved.txt @@ -14,4 +14,4 @@ Time Options after Change: Change 13| 11:45 Change 14| 12:45 Change 15| 13:45 - Change 16| 03:14 \ No newline at end of file + Change 16| 03:14 diff --git a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py b/tests/Infrastructure/TimeOptionsManager/test_TimeOptionsManager.py similarity index 93% rename from tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py rename to tests/Infrastructure/TimeOptionsManager/test_TimeOptionsManager.py index 699d0de..fec0310 100644 --- a/tests/Infrastructure/TimeOptionsManager/TestsTimeOptionsManager.py +++ b/tests/Infrastructure/TimeOptionsManager/test_TimeOptionsManager.py @@ -1,15 +1,12 @@ import os import unittest -from approvaltests import Approvals -from approvaltests.GenericDiffReporterFactory import GenericDiffReporterFactory +from approvaltests.approvals import verify from Infrastructure.TimeSettingsManager import TimeSettingsManager class TestsTimeOptionsManager(unittest.TestCase): - def setUp(self): - self.reporter = GenericDiffReporterFactory().get_first_working() def test_default_time_10_minutes(self): time_options_manager = TimeSettingsManager() @@ -96,7 +93,7 @@ def time_change_callback(time, minutes, seconds,origin_station_name): time_options_manager.increment_minutes() time_options_manager.set_countdown_time(3, 14) - Approvals.verify(result["result"], self.reporter) + verify(result["result"]) if __name__ == '__main__': os.environ["APPROVALS_TEXT_DIFF_TOOL"] = "meld" diff --git a/tests/Infrastructure/TipsManager/TestTipsManager.py b/tests/Infrastructure/TipsManager/test_TipsManager.py similarity index 58% rename from tests/Infrastructure/TipsManager/TestTipsManager.py rename to tests/Infrastructure/TipsManager/test_TipsManager.py index 1d65039..fbaec78 100644 --- a/tests/Infrastructure/TipsManager/TestTipsManager.py +++ b/tests/Infrastructure/TipsManager/test_TipsManager.py @@ -2,19 +2,28 @@ import sys +import os from Infrastructure.TipsManager import TipsManager class TestsTipsManage(unittest.TestCase): def test_random_tip_from_file(self): seed = 0 - tips_manager = TipsManager(seed,sys.path[1]) + + dirname = os.path.dirname(__file__) + path = self.go_two_dirs_up(dirname) + "/Tips" + tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips2.txt: Words\n') + def go_two_dirs_up(self, dirname): + return "/".join(dirname.split('\\')[:-2]) + def test_random_tip_from_file_second(self): seed = 1 - tips_manager = TipsManager(seed,sys.path[1]) + dirname = os.path.dirname(__file__) + path = self.go_two_dirs_up(dirname) + "/Tips" + tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips.txt: Customer collaboration over contract negotiation\n') From 3c68bbc8d96e4004a4cbd9521e706e32739533d0 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Fri, 22 Oct 2021 07:25:46 -0700 Subject: [PATCH 26/46] d Updated todo for learning sessions --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0c101fa..a1f2a51 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,7 @@ To add a theme simply copy and existing theme. To use that theme, put the file n * Update to latest version of python * Convert to single file distributable * Create plugin infrastructure +* Type into the minutes and seconds +* Clicking Add mobber should redirect cursor to typing next name +* Flipping the order of next and driver +* Replace next with navigator From de2cfb2b6dc2e5a4ce25f0cf94121708c9ec1c37 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Fri, 22 Oct 2021 16:05:29 -0700 Subject: [PATCH 27/46] d -Updated todo list --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a1f2a51..99c803a 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,17 @@ To add a theme simply copy and existing theme. To use that theme, put the file n ## Project Links [Trello Kanban Board]( https://trello.com/b/THISIB9Q/mob-programming-timer-python) +## Build Windows Distributable +Run BuildMobTimer.py + # Todo -* Update to latest version of python -* Convert to single file distributable -* Create plugin infrastructure +* Make a distributable version for Windows +* Choose if to use the trello link or use this list +* Create plugin infrastructure (to interface with Clockify, etc.) * Type into the minutes and seconds -* Clicking Add mobber should redirect cursor to typing next name +* Clicking [Add mobber] should redirect cursor to typing next name * Flipping the order of next and driver * Replace next with navigator +* Make a new setup for Mac +* Skipping someone on the timer screen should be a button not clicking the name +* Consolidate files into a dir for moving to the './dist' folder \ No newline at end of file From 7942b0b20418837ac8ea3e2cc1201775e1f1d8b4 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Fri, 22 Oct 2021 16:06:00 -0700 Subject: [PATCH 28/46] e - updated packages for deployments --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6be243d..1f0e97c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ approvaltests -py2exe +pyinstaller pysmb paho-mqtt pyreadline From bd38a9dab5be0454dc9503ea48c5d2d1a24e3282 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Fri, 22 Oct 2021 16:09:12 -0700 Subject: [PATCH 29/46] F - Update app to deploy application to windows --- BuildMobTimer.py | 17 +++++++++++++++++ Infrastructure/TipsManager.py | 2 +- .../TipsManager/test_TipsManager.py | 6 +++--- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 BuildMobTimer.py diff --git a/BuildMobTimer.py b/BuildMobTimer.py new file mode 100644 index 0000000..5e5a162 --- /dev/null +++ b/BuildMobTimer.py @@ -0,0 +1,17 @@ +import subprocess +from shutil import copy, copytree, rmtree + +rmtree('./dist') +py_installer_command = 'pyinstaller --clean --onefile --windowed MobTimer.spec'.split(" ") + +# Run py installer +subprocess.run(py_installer_command) + +# Copy files MobTimer.spec and TimeBomb icon into dist/ directory + + +copy('./MobTimer.cfg', './dist/MobTimer.cfg') +copy('./time-bomb.ico', './dist/time-bomb.ico') +copytree('./Themes', './dist/Themes') +copytree('./Tips', './dist/Tips') +copytree('./Images', './dist/Images') diff --git a/Infrastructure/TipsManager.py b/Infrastructure/TipsManager.py index c78d64e..7710056 100644 --- a/Infrastructure/TipsManager.py +++ b/Infrastructure/TipsManager.py @@ -12,7 +12,7 @@ def __init__(self, seed=None, root_directory=sys.argv[0]): random.seed(seed) def go_up_dir(self, root_directory): - return "/".join(root_directory.split('/')[:-1]) + return "/".join(root_directory.split('\\')[:-1]) def get_random_tip(self): tips_folder = self.root_directory + "/Tips" diff --git a/tests/Infrastructure/TipsManager/test_TipsManager.py b/tests/Infrastructure/TipsManager/test_TipsManager.py index fbaec78..7beeaf7 100644 --- a/tests/Infrastructure/TipsManager/test_TipsManager.py +++ b/tests/Infrastructure/TipsManager/test_TipsManager.py @@ -11,18 +11,18 @@ def test_random_tip_from_file(self): seed = 0 dirname = os.path.dirname(__file__) - path = self.go_two_dirs_up(dirname) + "/Tips" + path = self.go_two_dirs_up(dirname) + "\\Tips" tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips2.txt: Words\n') def go_two_dirs_up(self, dirname): - return "/".join(dirname.split('\\')[:-2]) + return "\\".join(dirname.split('\\')[:-2]) def test_random_tip_from_file_second(self): seed = 1 dirname = os.path.dirname(__file__) - path = self.go_two_dirs_up(dirname) + "/Tips" + path = self.go_two_dirs_up(dirname) + "\\Tips" tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips.txt: Customer collaboration over contract negotiation\n') From f329b59ef1005de4098e70b2c5bc80758f41375b Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 25 Oct 2021 07:42:51 -0700 Subject: [PATCH 30/46] e Updated git ignore for build system --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8cbd216..61843ed 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ env/ build/ develop-eggs/ dist/ +builds/ downloads/ eggs/ .eggs/ From 8de30a53af1f40117da2e630a7a22e369e471af1 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 25 Oct 2021 07:43:27 -0700 Subject: [PATCH 31/46] e Updated DevOps Script --- BuildMobTimer.py | 21 +++++++++++++++------ README.md | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/BuildMobTimer.py b/BuildMobTimer.py index 5e5a162..996e71b 100644 --- a/BuildMobTimer.py +++ b/BuildMobTimer.py @@ -1,17 +1,26 @@ +import os + import subprocess -from shutil import copy, copytree, rmtree +from shutil import copy, copytree, make_archive, rmtree +import time -rmtree('./dist') +dist_path = './dist' +rmtree(dist_path) py_installer_command = 'pyinstaller --clean --onefile --windowed MobTimer.spec'.split(" ") -# Run py installer subprocess.run(py_installer_command) -# Copy files MobTimer.spec and TimeBomb icon into dist/ directory - - copy('./MobTimer.cfg', './dist/MobTimer.cfg') copy('./time-bomb.ico', './dist/time-bomb.ico') copytree('./Themes', './dist/Themes') copytree('./Tips', './dist/Tips') copytree('./Images', './dist/Images') + +time_for_filename = time.strftime("%Y%m%d-%H%M%S") +output_filename = 'MobTimer' + time_for_filename + +builds_path = './builds/' +if not os.path.exists(builds_path): + os.makedirs(builds_path) + +make_archive(builds_path + output_filename, 'zip', dist_path) diff --git a/README.md b/README.md index 99c803a..7121e9c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ When we started mob programming we originally used a phone timer to time the rot - Screen will be blocked when timer runs out - Switch the person at the keyboard to the new driver - Repeat -- To stop timer mid session open the exe again +- To stop timer mid-session, open the exe again ## Random Tips Tips are maintained in the Tips folder. A random file is selected and a random line from the random file is displayed. To add or remove tips simply add or remove files and lines from files. From a2068e5c815a899b57dbfd29085bdaa903080d48 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 25 Oct 2021 07:46:30 -0700 Subject: [PATCH 32/46] e removed timer sessions from git tracking --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 61843ed..9b04030 100644 --- a/.gitignore +++ b/.gitignore @@ -153,3 +153,6 @@ fabric.properties # For approvals *.received.txt + +#for mob timer sessions +/Infrastructure/Sessions/ \ No newline at end of file From c2c1abbdf4b351e70ce96db4ebb9aaf84d72b30a Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 25 Oct 2021 07:49:43 -0700 Subject: [PATCH 33/46] d Updated Kanban and removed trello link --- README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index 7121e9c..4104e62 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,10 @@ The Mob timer can be customized by modifying MobTimer.cfg. ## Themes To add a theme simply copy and existing theme. To use that theme, put the file name of the new theme in the theme attribute in the MobTimer.cfg -## Project Links -[Trello Kanban Board]( https://trello.com/b/THISIB9Q/mob-programming-timer-python) - ## Build Windows Distributable Run BuildMobTimer.py -# Todo -* Make a distributable version for Windows -* Choose if to use the trello link or use this list +# Kanban * Create plugin infrastructure (to interface with Clockify, etc.) * Type into the minutes and seconds * Clicking [Add mobber] should redirect cursor to typing next name From 8540addf5006195bf459ed4046a5e922b71dd436 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Tue, 26 Oct 2021 07:07:22 -0700 Subject: [PATCH 34/46] d Updated Kanban with more details about time tracking. --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4104e62..20ef7dd 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,16 @@ To add a theme simply copy and existing theme. To use that theme, put the file n Run BuildMobTimer.py # Kanban -* Create plugin infrastructure (to interface with Clockify, etc.) -* Type into the minutes and seconds +* Make it easy to track time actually working + * enable/disable time tracking via a config file + * define time types in the conf file + * log when mobber added and removed + * replace continue button with tracking type + * Create plugin infrastructure (to interface with Clockify, etc.) +* Allow typing into the minutes and seconds * Clicking [Add mobber] should redirect cursor to typing next name -* Flipping the order of next and driver -* Replace next with navigator +* Flip the order of Next and Driver +* Replace Next with navigator * Make a new setup for Mac * Skipping someone on the timer screen should be a button not clicking the name * Consolidate files into a dir for moving to the './dist' folder \ No newline at end of file From 9ee3ca00564136233c3e30f54297739f66ad9e15 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 1 Nov 2021 07:33:21 -0700 Subject: [PATCH 35/46] F - implemented new FileUtilities methods d - improved README.md --- Infrastructure/FileUtilities.py | 16 ++++++++- Infrastructure/SettingsManager.py | 2 +- MobTimer.cfg | 6 +++- README.md | 4 +-- .../EventLoggingManager/__init__.py | 0 .../test_EventLoggingManager.py | 35 +++++++++++++++++++ 6 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 tests/Infrastructure/EventLoggingManager/__init__.py create mode 100644 tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index 3ae8bb5..0f8dfaf 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -1,6 +1,7 @@ import imp import os import sys +from os.path import exists class FileUtilities(object): @@ -14,4 +15,17 @@ def main_is_frozen(): def get_root_path(): if FileUtilities.main_is_frozen(): return os.path.dirname(sys.executable) - return os.path.dirname(os.path.realpath(__file__)) \ No newline at end of file + return os.path.dirname(os.path.realpath(__file__)) + + def file_exists(self, path): + return exists(path) + + def create_file(self, filePath): + f = open(filePath, "w") + # f.write("Woops! I have deleted the content!") + f.close() + + # def __init__(self, file_utility): + # + # if not file_utility.file_exists(): + # file_utility.create_file("path to file") \ No newline at end of file diff --git a/Infrastructure/SettingsManager.py b/Infrastructure/SettingsManager.py index 4a9950f..cae732a 100644 --- a/Infrastructure/SettingsManager.py +++ b/Infrastructure/SettingsManager.py @@ -104,7 +104,7 @@ def get_dojo_mob_station_name(self): return self.code_dojo.get("mob station name", "NewName") def get_dojo_session_id(self): - return self.code_dojo.get("session id","1337") + return self.code_dojo.get("session id", "1337") def get_dojo_topic_root(self): return self.code_dojo.get("topic root", "MobTimer") diff --git a/MobTimer.cfg b/MobTimer.cfg index 298f23d..ebc5598 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -39,4 +39,8 @@ broker = localhost port = 1883 mob station name = NewName session id = 1337 -topic root = MobTimer \ No newline at end of file +topic root = MobTimer + +[EVENT LOGGING] +enabled = True +log file name = MobTimer.log \ No newline at end of file diff --git a/README.md b/README.md index 20ef7dd..eb08566 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Run BuildMobTimer.py # Kanban * Make it easy to track time actually working - * enable/disable time tracking via a config file - * define time types in the conf file + * enable/disable time tracking via the config file + * define time types in the config file * log when mobber added and removed * replace continue button with tracking type * Create plugin infrastructure (to interface with Clockify, etc.) diff --git a/tests/Infrastructure/EventLoggingManager/__init__.py b/tests/Infrastructure/EventLoggingManager/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py new file mode 100644 index 0000000..3b312a0 --- /dev/null +++ b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py @@ -0,0 +1,35 @@ +import unittest +from unittest.mock import MagicMock +from approvaltests.approvals import verify + +from Infrastructure.FileUtilities import FileUtilities +from Infrastructure.SettingsManager import SettingsManager + + +class EventLoggingManager: + + def __init__(self, file_utility): + file_path = FileUtilities.get_root_path() + "\\filename.txt" + if not file_utility.file_exists(file_path): + # file_utility. + file_utility.create_file(file_path) + + +class TestsEventLoggingManager(unittest.TestCase): + + def test_log_file_should_be_created_if_doesnt_exist(self): + # Options: Mocks, Fake Files + + # Arrange: Make sure the file does not exist + file_utility = FileUtilities() + file_utility.file_exists = MagicMock(return_value=False) + file_utility.create_file = MagicMock(return_value=True) + # Act: Instantiate EventLoggingManager + event_logging_manager = EventLoggingManager(file_utility) + + # Assert: Verify the file exists + file_utility.create_file.assert_called_with(FileUtilities.get_root_path() + "\\filename.txt") + + +if __name__ == '__main__': + unittest.main() From 5df00c2e8b52f15d638f8a5a45696bf482a93134 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 1 Nov 2021 07:46:48 -0700 Subject: [PATCH 36/46] R - Replaced static method with instance method on FileUtilities and mocked it in the test --- Infrastructure/EventLoggingManager.py | 9 +++++++++ Infrastructure/FileUtilities.py | 3 +-- Infrastructure/SessionManager.py | 3 ++- .../test_EventLoggingManager.py | 16 +++++----------- 4 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 Infrastructure/EventLoggingManager.py diff --git a/Infrastructure/EventLoggingManager.py b/Infrastructure/EventLoggingManager.py new file mode 100644 index 0000000..ae4ab40 --- /dev/null +++ b/Infrastructure/EventLoggingManager.py @@ -0,0 +1,9 @@ +from Infrastructure.FileUtilities import FileUtilities + + +class EventLoggingManager: + + def __init__(self, file_utility): + file_path = file_utility.get_root_path() + "\\filename.txt" + if not file_utility.file_exists(file_path): + file_utility.create_file(file_path) \ No newline at end of file diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index 0f8dfaf..b38d0f2 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -11,8 +11,7 @@ def main_is_frozen(): hasattr(sys, "importers") # old py2exe or imp.is_frozen("__main__")) # tools/freeze - @staticmethod - def get_root_path(): + def get_root_path(self): if FileUtilities.main_is_frozen(): return os.path.dirname(sys.executable) return os.path.dirname(os.path.realpath(__file__)) diff --git a/Infrastructure/SessionManager.py b/Infrastructure/SessionManager.py index 12cf7db..fedddce 100644 --- a/Infrastructure/SessionManager.py +++ b/Infrastructure/SessionManager.py @@ -7,6 +7,7 @@ class SessionManager(object): def __init__(self, uuid_generator): self.uuid_generator = uuid_generator + self.file_utilities = FileUtilities() def create_session(self): session_id = self.uuid_generator.uuid1() @@ -16,7 +17,7 @@ def create_session(self): file = open(directory + session_id.__str__(), 'w+') def get_sessions_path(self): - directory = (FileUtilities.get_root_path() + "/Sessions/") + directory = (self.file_utilities.get_root_path() + "/Sessions/") if not os.path.exists(directory): os.makedirs(directory) return directory diff --git a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py index 3b312a0..86230e5 100644 --- a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py +++ b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py @@ -1,19 +1,12 @@ import unittest from unittest.mock import MagicMock -from approvaltests.approvals import verify +from Infrastructure.EventLoggingManager import EventLoggingManager from Infrastructure.FileUtilities import FileUtilities -from Infrastructure.SettingsManager import SettingsManager -class EventLoggingManager: - - def __init__(self, file_utility): - file_path = FileUtilities.get_root_path() + "\\filename.txt" - if not file_utility.file_exists(file_path): - # file_utility. - file_utility.create_file(file_path) - +# 1. Mock remaining File Utilities function calls +# 2. Choose a real name for the log file class TestsEventLoggingManager(unittest.TestCase): @@ -22,13 +15,14 @@ def test_log_file_should_be_created_if_doesnt_exist(self): # Arrange: Make sure the file does not exist file_utility = FileUtilities() + file_utility.get_root_path = MagicMock(return_value='beginning of file path') file_utility.file_exists = MagicMock(return_value=False) file_utility.create_file = MagicMock(return_value=True) # Act: Instantiate EventLoggingManager event_logging_manager = EventLoggingManager(file_utility) # Assert: Verify the file exists - file_utility.create_file.assert_called_with(FileUtilities.get_root_path() + "\\filename.txt") + file_utility.create_file.assert_called_with(file_utility.get_root_path() + "\\filename.txt") if __name__ == '__main__': From 3e40cfc879a84faac545feb47688b9b585ae48af Mon Sep 17 00:00:00 2001 From: Pipeline Date: Mon, 1 Nov 2021 07:52:55 -0700 Subject: [PATCH 37/46] r - Removed comments, refactored names --- Infrastructure/EventLoggingManager.py | 2 +- Infrastructure/FileUtilities.py | 20 +++++++------------ .../test_EventLoggingManager.py | 13 +++--------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Infrastructure/EventLoggingManager.py b/Infrastructure/EventLoggingManager.py index ae4ab40..409ad41 100644 --- a/Infrastructure/EventLoggingManager.py +++ b/Infrastructure/EventLoggingManager.py @@ -4,6 +4,6 @@ class EventLoggingManager: def __init__(self, file_utility): - file_path = file_utility.get_root_path() + "\\filename.txt" + file_path = file_utility.get_root_path() + "\\MobTimerEvents.log" if not file_utility.file_exists(file_path): file_utility.create_file(file_path) \ No newline at end of file diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index b38d0f2..a5b02e9 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -7,24 +7,18 @@ class FileUtilities(object): @staticmethod def main_is_frozen(): - return (hasattr(sys, "frozen") or # new py2exe - hasattr(sys, "importers") # old py2exe - or imp.is_frozen("__main__")) # tools/freeze + return (hasattr(sys, "frozen") or # new py2exe + hasattr(sys, "importers") # old py2exe + or imp.is_frozen("__main__")) # tools/freeze def get_root_path(self): if FileUtilities.main_is_frozen(): return os.path.dirname(sys.executable) return os.path.dirname(os.path.realpath(__file__)) - def file_exists(self, path): - return exists(path) + def file_exists(self, file_path): + return exists(file_path) - def create_file(self, filePath): - f = open(filePath, "w") - # f.write("Woops! I have deleted the content!") + def create_file(self, file_path): + f = open(file_path, "w") f.close() - - # def __init__(self, file_utility): - # - # if not file_utility.file_exists(): - # file_utility.create_file("path to file") \ No newline at end of file diff --git a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py index 86230e5..9a5de6a 100644 --- a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py +++ b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py @@ -5,24 +5,17 @@ from Infrastructure.FileUtilities import FileUtilities -# 1. Mock remaining File Utilities function calls -# 2. Choose a real name for the log file - class TestsEventLoggingManager(unittest.TestCase): def test_log_file_should_be_created_if_doesnt_exist(self): - # Options: Mocks, Fake Files - - # Arrange: Make sure the file does not exist file_utility = FileUtilities() file_utility.get_root_path = MagicMock(return_value='beginning of file path') file_utility.file_exists = MagicMock(return_value=False) file_utility.create_file = MagicMock(return_value=True) - # Act: Instantiate EventLoggingManager - event_logging_manager = EventLoggingManager(file_utility) - # Assert: Verify the file exists - file_utility.create_file.assert_called_with(file_utility.get_root_path() + "\\filename.txt") + EventLoggingManager(file_utility) + + file_utility.create_file.assert_called_with(file_utility.get_root_path() + '\\MobTimerEvents.log') if __name__ == '__main__': From af6117900895418c47be28e41a1376b392744f53 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Tue, 2 Nov 2021 08:00:23 -0700 Subject: [PATCH 38/46] t - Added tests for EventLoggingManager and updated tests for TipsManager --- Infrastructure/EventLoggingManager.py | 10 ++++-- Infrastructure/FileUtilities.py | 5 +++ Infrastructure/TipsManager.py | 6 +++- .../test_EventLoggingManager.py | 31 ++++++++++++++++++- .../TipsManager/test_TipsManager.py | 9 ++++++ 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Infrastructure/EventLoggingManager.py b/Infrastructure/EventLoggingManager.py index 409ad41..90d85de 100644 --- a/Infrastructure/EventLoggingManager.py +++ b/Infrastructure/EventLoggingManager.py @@ -4,6 +4,10 @@ class EventLoggingManager: def __init__(self, file_utility): - file_path = file_utility.get_root_path() + "\\MobTimerEvents.log" - if not file_utility.file_exists(file_path): - file_utility.create_file(file_path) \ No newline at end of file + self.file_path = file_utility.get_root_path() + "\\MobTimerEvents.log" + self.file_utility = file_utility + if not self.file_utility.file_exists(self.file_path): + self.file_utility.create_file(self.file_path) + + def log(self, data): + self.file_utility.append(self.file_path, '\n' + data) diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index a5b02e9..9041760 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -22,3 +22,8 @@ def file_exists(self, file_path): def create_file(self, file_path): f = open(file_path, "w") f.close() + + def append(self, file_path, data): + f = open(file_path, "w+") + f.write(data) + f.close() diff --git a/Infrastructure/TipsManager.py b/Infrastructure/TipsManager.py index 7710056..23743c1 100644 --- a/Infrastructure/TipsManager.py +++ b/Infrastructure/TipsManager.py @@ -12,7 +12,11 @@ def __init__(self, seed=None, root_directory=sys.argv[0]): random.seed(seed) def go_up_dir(self, root_directory): - return "/".join(root_directory.split('\\')[:-1]) + if '\\' in root_directory: + return "/".join(root_directory.split('\\')[:-1]) + else: + return "/".join(root_directory.split('/')[:-1]) + def get_random_tip(self): tips_folder = self.root_directory + "/Tips" diff --git a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py index 9a5de6a..a6bd0e9 100644 --- a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py +++ b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py @@ -1,5 +1,5 @@ import unittest -from unittest.mock import MagicMock +from unittest.mock import call, MagicMock from Infrastructure.EventLoggingManager import EventLoggingManager from Infrastructure.FileUtilities import FileUtilities @@ -17,6 +17,35 @@ def test_log_file_should_be_created_if_doesnt_exist(self): file_utility.create_file.assert_called_with(file_utility.get_root_path() + '\\MobTimerEvents.log') + def test_log_file_should_not_create_if_file_exists(self): + file_utility = FileUtilities() + file_utility.get_root_path = MagicMock(return_value='beginning of file path') + file_utility.file_exists = MagicMock(return_value=True) + file_utility.create_file = MagicMock(return_value=True) + + EventLoggingManager(file_utility) + + file_utility.create_file.assert_not_called() + + def test_log_file_should_append_to_log(self): + file_utility = FileUtilities() + file_utility.get_root_path = MagicMock(return_value='beginning of file path') + file_utility.file_exists = MagicMock(return_value=True) + file_utility.create_file = MagicMock(return_value=True) + file_utility.append = MagicMock() + logger = EventLoggingManager(file_utility) + + test_data = ["Hello world 1", "Hello world 2"] + + for entry in test_data: + logger.log(entry) + calls = [] + + for entry in test_data: + calls.append(call('beginning of file path\\MobTimerEvents.log', '\n'+entry)) + + file_utility.append.assert_has_calls(calls) + if __name__ == '__main__': unittest.main() diff --git a/tests/Infrastructure/TipsManager/test_TipsManager.py b/tests/Infrastructure/TipsManager/test_TipsManager.py index 7beeaf7..a2fc05c 100644 --- a/tests/Infrastructure/TipsManager/test_TipsManager.py +++ b/tests/Infrastructure/TipsManager/test_TipsManager.py @@ -27,6 +27,15 @@ def test_random_tip_from_file_second(self): result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips.txt: Customer collaboration over contract negotiation\n') + def test_random_tip_from_file_second_alternate_slashes(self): + seed = 1 + dirname = os.path.dirname(__file__) + path = self.go_two_dirs_up(dirname) + "\\Tips" + path = path.replace("\\", "/") + tips_manager = TipsManager(seed, path) + result = tips_manager.get_random_tip() + self.assertEqual(result, 'TestTips.txt: Customer collaboration over contract negotiation\n') + if __name__ == '__main__': unittest.main() From 165b28fa295b76892dcf35a1a4db1e9ea90fef9a Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 3 Nov 2021 07:29:49 -0700 Subject: [PATCH 39/46] t - Added tests around navigating directories for creating files. --- .../EventLoggingManager/test_EventLoggingManager.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py index a6bd0e9..8f19f4b 100644 --- a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py +++ b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py @@ -9,17 +9,18 @@ class TestsEventLoggingManager(unittest.TestCase): def test_log_file_should_be_created_if_doesnt_exist(self): file_utility = FileUtilities() - file_utility.get_root_path = MagicMock(return_value='beginning of file path') + beginning_of_file_path = 'beginning of file path' + file_utility.get_root_path = MagicMock(return_value=beginning_of_file_path + "\\Infrastructure") file_utility.file_exists = MagicMock(return_value=False) file_utility.create_file = MagicMock(return_value=True) EventLoggingManager(file_utility) - file_utility.create_file.assert_called_with(file_utility.get_root_path() + '\\MobTimerEvents.log') + file_utility.create_file.assert_called_with(beginning_of_file_path + '\\MobTimerEvents.log') def test_log_file_should_not_create_if_file_exists(self): file_utility = FileUtilities() - file_utility.get_root_path = MagicMock(return_value='beginning of file path') + file_utility.get_root_path = MagicMock(return_value='beginning of file path' + '\\Infrastructure') file_utility.file_exists = MagicMock(return_value=True) file_utility.create_file = MagicMock(return_value=True) @@ -29,7 +30,8 @@ def test_log_file_should_not_create_if_file_exists(self): def test_log_file_should_append_to_log(self): file_utility = FileUtilities() - file_utility.get_root_path = MagicMock(return_value='beginning of file path') + beginning_of_file_path = 'beginning of file path' + file_utility.get_root_path = MagicMock(return_value=beginning_of_file_path + '\\Infrastructure') file_utility.file_exists = MagicMock(return_value=True) file_utility.create_file = MagicMock(return_value=True) file_utility.append = MagicMock() @@ -42,7 +44,7 @@ def test_log_file_should_append_to_log(self): calls = [] for entry in test_data: - calls.append(call('beginning of file path\\MobTimerEvents.log', '\n'+entry)) + calls.append(call(beginning_of_file_path +'\\MobTimerEvents.log', '\n'+entry)) file_utility.append.assert_has_calls(calls) From 7cdec2af2faa78484837fe2cf2cbc0e78387bf8b Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 3 Nov 2021 07:31:13 -0700 Subject: [PATCH 40/46] F - Implemented feature for navigating directories for file creation. --- Frames/MobTimerController.py | 4 ++++ Infrastructure/EventLoggingManager.py | 3 ++- Infrastructure/FileUtilities.py | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index 3de01c5..f2f0735 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -18,6 +18,8 @@ from Infrastructure.ThemeManager import ThemeManager from Infrastructure.TimeSettingsManager import TimeSettingsManager from Infrastructure.TipsManager import TipsManager +from Infrastructure.EventLoggingManager import EventLoggingManager +from Infrastructure.FileUtilities import FileUtilities class MobTimerController(Tk): @@ -32,6 +34,8 @@ def __init__(self, *args, **kwargs): self.mobber_manager = MobberManager(self.settings_manager.get_randomize_randomize_next_driver()) self.countdown_manager = CountdownManager(self) self.session_manager = SessionManager(uuid) + self.file_utilities = FileUtilities() + self.event_logging_manager = EventLoggingManager(self.file_utilities) self.timer_extension_count = self.settings_manager.get_timer_extension_count() self.extensions_used = 0 atexit.register(self.session_manager.clear_sessions) diff --git a/Infrastructure/EventLoggingManager.py b/Infrastructure/EventLoggingManager.py index 90d85de..0a5b25a 100644 --- a/Infrastructure/EventLoggingManager.py +++ b/Infrastructure/EventLoggingManager.py @@ -4,8 +4,9 @@ class EventLoggingManager: def __init__(self, file_utility): - self.file_path = file_utility.get_root_path() + "\\MobTimerEvents.log" self.file_utility = file_utility + self.file_path = self.file_utility.go_up_dir(self.file_utility.get_root_path()) + "\\MobTimerEvents.log" + if not self.file_utility.file_exists(self.file_path): self.file_utility.create_file(self.file_path) diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index 9041760..340e0ec 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -27,3 +27,9 @@ def append(self, file_path, data): f = open(file_path, "w+") f.write(data) f.close() + + def go_up_dir(self, root_directory): + if '\\' in root_directory: + return "/".join(root_directory.split('\\')[:-1]) + else: + return "/".join(root_directory.split('/')[:-1]) \ No newline at end of file From 546a1e3a58be1f7b6e4ae38b7edc49b001184f29 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 3 Nov 2021 07:56:59 -0700 Subject: [PATCH 41/46] d Updated Kanban --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eb08566..33ee232 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ To add a theme simply copy and existing theme. To use that theme, put the file n Run BuildMobTimer.py # Kanban -* Make it easy to track time actually working - * enable/disable time tracking via the config file - * define time types in the config file +* Make it easy to track time actually working * log when mobber added and removed + * enable/disable time tracking via the config file + * define time types in the config file (Learning Time / Development Time etc...) * replace continue button with tracking type * Create plugin infrastructure (to interface with Clockify, etc.) * Allow typing into the minutes and seconds From c01a8576e131bb34b433f9dd9febf5dc342082e8 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Wed, 3 Nov 2021 07:59:20 -0700 Subject: [PATCH 42/46] r refactored navigating directories to allow levels of directories to navigate to be specified and removed duplicate code --- Infrastructure/EventLoggingManager.py | 2 +- Infrastructure/FileUtilities.py | 6 +++--- Infrastructure/TipsManager.py | 11 +++-------- .../TipsManager/test_TipsManager.py | 15 ++++++++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Infrastructure/EventLoggingManager.py b/Infrastructure/EventLoggingManager.py index 0a5b25a..df68f92 100644 --- a/Infrastructure/EventLoggingManager.py +++ b/Infrastructure/EventLoggingManager.py @@ -5,7 +5,7 @@ class EventLoggingManager: def __init__(self, file_utility): self.file_utility = file_utility - self.file_path = self.file_utility.go_up_dir(self.file_utility.get_root_path()) + "\\MobTimerEvents.log" + self.file_path = self.file_utility.go_up_dirs(self.file_utility.get_root_path(), 1) + "\\MobTimerEvents.log" if not self.file_utility.file_exists(self.file_path): self.file_utility.create_file(self.file_path) diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index 340e0ec..5662374 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -28,8 +28,8 @@ def append(self, file_path, data): f.write(data) f.close() - def go_up_dir(self, root_directory): + def go_up_dirs(self, root_directory, levels): if '\\' in root_directory: - return "/".join(root_directory.split('\\')[:-1]) + return "/".join(root_directory.split('\\')[:-levels]) else: - return "/".join(root_directory.split('/')[:-1]) \ No newline at end of file + return "/".join(root_directory.split('/')[:-levels]) \ No newline at end of file diff --git a/Infrastructure/TipsManager.py b/Infrastructure/TipsManager.py index 23743c1..9908f8f 100644 --- a/Infrastructure/TipsManager.py +++ b/Infrastructure/TipsManager.py @@ -2,22 +2,17 @@ import sys +from Infrastructure.FileUtilities import FileUtilities from Infrastructure.PathUtility import PathUtility class TipsManager(object): def __init__(self, seed=None, root_directory=sys.argv[0]): - self.root_directory = self.go_up_dir(root_directory) + self.file_utility = FileUtilities() + self.root_directory = self.file_utility.go_up_dirs(root_directory, 1) if seed is not None: random.seed(seed) - def go_up_dir(self, root_directory): - if '\\' in root_directory: - return "/".join(root_directory.split('\\')[:-1]) - else: - return "/".join(root_directory.split('/')[:-1]) - - def get_random_tip(self): tips_folder = self.root_directory + "/Tips" random_file = random.choice(os.listdir("%s" % tips_folder)) diff --git a/tests/Infrastructure/TipsManager/test_TipsManager.py b/tests/Infrastructure/TipsManager/test_TipsManager.py index a2fc05c..1fdebf5 100644 --- a/tests/Infrastructure/TipsManager/test_TipsManager.py +++ b/tests/Infrastructure/TipsManager/test_TipsManager.py @@ -3,26 +3,31 @@ import sys import os + +from Infrastructure.FileUtilities import FileUtilities from Infrastructure.TipsManager import TipsManager class TestsTipsManage(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.fileUtilities = FileUtilities() + def test_random_tip_from_file(self): seed = 0 dirname = os.path.dirname(__file__) - path = self.go_two_dirs_up(dirname) + "\\Tips" + path = self.fileUtilities.go_up_dirs(dirname, 2) + "\\Tips" tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips2.txt: Words\n') - def go_two_dirs_up(self, dirname): - return "\\".join(dirname.split('\\')[:-2]) def test_random_tip_from_file_second(self): seed = 1 dirname = os.path.dirname(__file__) - path = self.go_two_dirs_up(dirname) + "\\Tips" + path = self.fileUtilities.go_up_dirs(dirname, 2) + "\\Tips" tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() self.assertEqual(result, 'TestTips.txt: Customer collaboration over contract negotiation\n') @@ -30,7 +35,7 @@ def test_random_tip_from_file_second(self): def test_random_tip_from_file_second_alternate_slashes(self): seed = 1 dirname = os.path.dirname(__file__) - path = self.go_two_dirs_up(dirname) + "\\Tips" + path = self.fileUtilities.go_up_dirs(dirname, 2) + "\\Tips" path = path.replace("\\", "/") tips_manager = TipsManager(seed, path) result = tips_manager.get_random_tip() From eab45e1c48df7c295e9a9884590988ba6372eaac Mon Sep 17 00:00:00 2001 From: Pipeline Date: Thu, 4 Nov 2021 07:42:59 -0700 Subject: [PATCH 43/46] F Added events to mobbing manager for adding and removing mobbers. File Utilities now appends properly --- Infrastructure/FileUtilities.py | 2 +- Infrastructure/MobberManager.py | 20 +++++++ ...scribe_to_mobber_list_changes.approved.txt | 60 +++++++++++-------- .../MobberManager/test_MobberManager.py | 13 ++++ 4 files changed, 70 insertions(+), 25 deletions(-) diff --git a/Infrastructure/FileUtilities.py b/Infrastructure/FileUtilities.py index 5662374..382980a 100644 --- a/Infrastructure/FileUtilities.py +++ b/Infrastructure/FileUtilities.py @@ -24,7 +24,7 @@ def create_file(self, file_path): f.close() def append(self, file_path, data): - f = open(file_path, "w+") + f = open(file_path, "a") f.write(data) f.close() diff --git a/Infrastructure/MobberManager.py b/Infrastructure/MobberManager.py index a060bb6..a45ac4e 100644 --- a/Infrastructure/MobberManager.py +++ b/Infrastructure/MobberManager.py @@ -7,6 +7,8 @@ def __init__(self, randomize=False): self.next_driver_index = 1 self.mobber_list = [] self.mobber_list_change_callbacks = [] + self.mobber_add_callbacks = [] + self.mobber_remove_callbacks = [] self.randomize = randomize def mobber_count(self): @@ -16,17 +18,35 @@ def add_mobber(self, mobber_name): clean_mobber_name = str(mobber_name).strip() if clean_mobber_name != "" and not self.mobber_list.__contains__(clean_mobber_name): self.mobber_list.append(mobber_name) + self.fire_mobber_add_callbacks(mobber_name) self.fire_mobber_list_change_callbacks() + def subscribe_to_mobber_add(self, mobber_add_callback): + self.mobber_add_callbacks.append(mobber_add_callback) + + def fire_mobber_add_callbacks(self, mobber_name): + for mobber_add_callback in self.mobber_add_callbacks: + if mobber_add_callback: + mobber_add_callback(mobber_name) + def get_mobbers(self): return self.mobber_list def remove_mobber(self, remove_mobber_index): if self.mobber_count() == 0: return + self.fire_mobber_remove_callbacks(self.mobber_list[remove_mobber_index]) del self.mobber_list[remove_mobber_index] self.fire_mobber_list_change_callbacks() + def subscribe_to_mobber_remove(self, mobber_remove_callback): + self.mobber_remove_callbacks.append(mobber_remove_callback) + + def fire_mobber_remove_callbacks(self, mobber_name): + for mobber_remove_callback in self.mobber_remove_callbacks: + if mobber_remove_callback: + mobber_remove_callback(mobber_name) + def move_mobber_up(self, swap_index): if self.mobber_count() == 0: return destination_index = swap_index - 1 diff --git a/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt b/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt index d000eb0..e123f40 100644 --- a/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt +++ b/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes.approved.txt @@ -1,27 +1,39 @@ Mobbers in List for Each Change Action 1: -Action 2:Joe (Driver) (Navigator), -Action 3:Joe (Driver), Chris (Navigator), -Action 4:Joe (Driver), Chris (Navigator), Sam, -Action 5:Joe (Driver), Chris (Navigator), Sam, John, -Action 6:Joe, Chris (Driver), Sam (Navigator), John, -Action 7:Joe, Chris (Driver), Sam (Navigator), John, Bill, -Action 8:Joe, Chris, Sam (Driver), John (Navigator), Bill, -Action 9:Joe, Chris, Sam, John (Driver), Bill (Navigator), -Action 10:Joe (Navigator), Chris, Sam, John, Bill (Driver), -Action 11:Joe (Driver), Chris (Navigator), Sam, John, Bill, +Action 2:Joe added +Action 3:Joe (Driver) (Navigator), +Action 4:Chris added +Action 5:Joe (Driver), Chris (Navigator), +Action 6:Sam added +Action 7:Joe (Driver), Chris (Navigator), Sam, +Action 8:John added +Action 9:Joe (Driver), Chris (Navigator), Sam, John, +Action 10:Joe, Chris (Driver), Sam (Navigator), John, +Action 11:Bill added Action 12:Joe, Chris (Driver), Sam (Navigator), John, Bill, -Action 13:Joe, Chris (Driver), John (Navigator), Bill, -Action 14:Chris, John (Driver), Bill (Navigator), -Action 15:Chris (Navigator), John, Bill (Driver), -Action 16:Chris, John (Driver), Bill (Navigator), -Action 17:Chris, John (Driver), Bill (Navigator), Seth, -Action 18:Chris (Driver), John (Navigator), Bill, Seth, -Action 19:Chris (Navigator), John, Bill, Seth (Driver), -Action 20:Chris, John, Bill (Driver), Seth (Navigator), -Action 21:John, Chris, Bill (Driver), Seth (Navigator), -Action 22:John, Chris, Bill (Driver), Seth (Navigator), Fredrick, -Action 23:John, Bill, Chris (Driver), Seth (Navigator), Fredrick, -Action 24:John, Chris, Seth (Driver), Fredrick (Navigator), -Action 25:Chris (Navigator), Seth, Fredrick (Driver), -Action 26:Seth (Driver), Fredrick (Navigator), +Action 13:Joe, Chris, Sam (Driver), John (Navigator), Bill, +Action 14:Joe, Chris, Sam, John (Driver), Bill (Navigator), +Action 15:Joe (Navigator), Chris, Sam, John, Bill (Driver), +Action 16:Joe (Driver), Chris (Navigator), Sam, John, Bill, +Action 17:Joe, Chris (Driver), Sam (Navigator), John, Bill, +Action 18:Sam removed +Action 19:Joe, Chris (Driver), John (Navigator), Bill, +Action 20:Joe removed +Action 21:Chris, John (Driver), Bill (Navigator), +Action 22:Chris (Navigator), John, Bill (Driver), +Action 23:Chris, John (Driver), Bill (Navigator), +Action 24:Seth added +Action 25:Chris, John (Driver), Bill (Navigator), Seth, +Action 26:Chris (Driver), John (Navigator), Bill, Seth, +Action 27:Chris (Navigator), John, Bill, Seth (Driver), +Action 28:Chris, John, Bill (Driver), Seth (Navigator), +Action 29:John, Chris, Bill (Driver), Seth (Navigator), +Action 30:Fredrick added +Action 31:John, Chris, Bill (Driver), Seth (Navigator), Fredrick, +Action 32:John, Bill, Chris (Driver), Seth (Navigator), Fredrick, +Action 33:Bill removed +Action 34:John, Chris, Seth (Driver), Fredrick (Navigator), +Action 35:John removed +Action 36:Chris (Navigator), Seth, Fredrick (Driver), +Action 37:Chris removed +Action 38:Seth (Driver), Fredrick (Navigator), diff --git a/tests/Infrastructure/MobberManager/test_MobberManager.py b/tests/Infrastructure/MobberManager/test_MobberManager.py index d60493f..20c8412 100644 --- a/tests/Infrastructure/MobberManager/test_MobberManager.py +++ b/tests/Infrastructure/MobberManager/test_MobberManager.py @@ -117,6 +117,19 @@ def time_change_callback(mobber_list, driver_index, navigator_index): mobber_manager.subscribe_to_mobber_list_change(time_change_callback) + def on_mobber_add(mobber_name): + result["increment"] += 1 + result["result"] += "Action " + result["increment"].__str__() + ":" + mobber_name + " added\n" + + mobber_manager.subscribe_to_mobber_add(on_mobber_add) + + + def on_mobber_remove(mobber_name): + result["increment"] += 1 + result["result"] += "Action " + result["increment"].__str__() + ":" + mobber_name + " removed\n" + + mobber_manager.subscribe_to_mobber_remove(on_mobber_remove) + mobber_manager.add_mobber("Joe") mobber_manager.add_mobber("Chris") mobber_manager.add_mobber("Sam") From 75b9ff6cb642ec85cbc47af0229d0e23907a1c5b Mon Sep 17 00:00:00 2001 From: Pipeline Date: Thu, 4 Nov 2021 08:03:35 -0700 Subject: [PATCH 44/46] F Event logging manager now records time stamps --- Infrastructure/EventLoggingManager.py | 6 +++-- README.md | 1 + .../test_EventLoggingManager.py | 22 +++++++++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Infrastructure/EventLoggingManager.py b/Infrastructure/EventLoggingManager.py index df68f92..a6bf60f 100644 --- a/Infrastructure/EventLoggingManager.py +++ b/Infrastructure/EventLoggingManager.py @@ -3,12 +3,14 @@ class EventLoggingManager: - def __init__(self, file_utility): + def __init__(self, file_utility, date_time_utility): self.file_utility = file_utility self.file_path = self.file_utility.go_up_dirs(self.file_utility.get_root_path(), 1) + "\\MobTimerEvents.log" + self.date_time_utility = date_time_utility + if not self.file_utility.file_exists(self.file_path): self.file_utility.create_file(self.file_path) def log(self, data): - self.file_utility.append(self.file_path, '\n' + data) + self.file_utility.append(self.file_path, f'\n{self.date_time_utility.get_timestamp()} {data}') diff --git a/README.md b/README.md index 33ee232..80f8bac 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Run BuildMobTimer.py # Kanban * Make it easy to track time actually working + * Logs should have timestamps * log when mobber added and removed * enable/disable time tracking via the config file * define time types in the config file (Learning Time / Development Time etc...) diff --git a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py index 8f19f4b..9038552 100644 --- a/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py +++ b/tests/Infrastructure/EventLoggingManager/test_EventLoggingManager.py @@ -1,6 +1,7 @@ import unittest -from unittest.mock import call, MagicMock +from unittest.mock import call, MagicMock, Mock +from Infrastructure.DateTimeUtility import DateTimeUtility from Infrastructure.EventLoggingManager import EventLoggingManager from Infrastructure.FileUtilities import FileUtilities @@ -13,8 +14,8 @@ def test_log_file_should_be_created_if_doesnt_exist(self): file_utility.get_root_path = MagicMock(return_value=beginning_of_file_path + "\\Infrastructure") file_utility.file_exists = MagicMock(return_value=False) file_utility.create_file = MagicMock(return_value=True) - - EventLoggingManager(file_utility) + date_time_utility = DateTimeUtility() + EventLoggingManager(file_utility,date_time_utility) file_utility.create_file.assert_called_with(beginning_of_file_path + '\\MobTimerEvents.log') @@ -24,7 +25,8 @@ def test_log_file_should_not_create_if_file_exists(self): file_utility.file_exists = MagicMock(return_value=True) file_utility.create_file = MagicMock(return_value=True) - EventLoggingManager(file_utility) + date_time_utility = DateTimeUtility() + EventLoggingManager(file_utility, date_time_utility) file_utility.create_file.assert_not_called() @@ -35,16 +37,22 @@ def test_log_file_should_append_to_log(self): file_utility.file_exists = MagicMock(return_value=True) file_utility.create_file = MagicMock(return_value=True) file_utility.append = MagicMock() - logger = EventLoggingManager(file_utility) + date_time_utility = DateTimeUtility() + + timestamps = [1594823426.159446, 1594123426.159447, 1594654426.159448] + date_time_utility.get_timestamp = Mock() + date_time_utility.get_timestamp.side_effect = timestamps + logger = EventLoggingManager(file_utility, date_time_utility) test_data = ["Hello world 1", "Hello world 2"] for entry in test_data: logger.log(entry) calls = [] - + index = 0 for entry in test_data: - calls.append(call(beginning_of_file_path +'\\MobTimerEvents.log', '\n'+entry)) + calls.append(call(f'{beginning_of_file_path}\\MobTimerEvents.log', f'\n{timestamps[index]} {entry}')) + index += 1 file_utility.append.assert_has_calls(calls) From 62e45f75773f88b2635e42179f445c6596ef0975 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Thu, 4 Nov 2021 08:03:54 -0700 Subject: [PATCH 45/46] F Event logging manager now records time stamps --- Infrastructure/DateTimeUtility.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Infrastructure/DateTimeUtility.py diff --git a/Infrastructure/DateTimeUtility.py b/Infrastructure/DateTimeUtility.py new file mode 100644 index 0000000..8202849 --- /dev/null +++ b/Infrastructure/DateTimeUtility.py @@ -0,0 +1,6 @@ +import datetime + + +class DateTimeUtility: + def get_timestamp(self): + return datetime.datetime.now().timestamp() From 25bcf95d1c1970515ccbdb1ce59b7cf7e908b697 Mon Sep 17 00:00:00 2001 From: Pipeline Date: Fri, 5 Nov 2021 07:48:36 -0700 Subject: [PATCH 46/46] F Added logging of different types of events and setting of event logging to be toggleable --- Frames/MobTimerController.py | 34 +++++++--- Infrastructure/MobberManager.py | 32 +++++---- Infrastructure/SettingsManager.py | 5 ++ MobTimer.cfg | 3 +- ...to_mobber_list_changes_random.approved.txt | 67 +++++++++++++------ .../MobberManager/test_MobberManager.py | 14 ++++ 6 files changed, 107 insertions(+), 48 deletions(-) diff --git a/Frames/MobTimerController.py b/Frames/MobTimerController.py index f2f0735..79bc4d1 100644 --- a/Frames/MobTimerController.py +++ b/Frames/MobTimerController.py @@ -9,6 +9,7 @@ from Frames.ScreenBlockerFrame import ScreenBlockerFrame from Frames.TransparentCountdownFrame import TransparentCountdownFrame from Infrastructure.CountdownManager import CountdownManager +from Infrastructure.DateTimeUtility import DateTimeUtility from Infrastructure.DojoManager import DojoManager from Infrastructure.MobberManager import MobberManager from Infrastructure.PlatformUtility import PlatformUtility @@ -31,11 +32,12 @@ def __init__(self, *args, **kwargs): self.settings_manager = SettingsManager() self.tips_manager = TipsManager() self.time_options_manager = TimeSettingsManager() + self.date_time_utility = DateTimeUtility() + self.file_utilities = FileUtilities() + self.event_logging_manager = EventLoggingManager(self.file_utilities, self.date_time_utility) self.mobber_manager = MobberManager(self.settings_manager.get_randomize_randomize_next_driver()) self.countdown_manager = CountdownManager(self) self.session_manager = SessionManager(uuid) - self.file_utilities = FileUtilities() - self.event_logging_manager = EventLoggingManager(self.file_utilities) self.timer_extension_count = self.settings_manager.get_timer_extension_count() self.extensions_used = 0 atexit.register(self.session_manager.clear_sessions) @@ -74,7 +76,8 @@ def __init__(self, *args, **kwargs): container.grid_columnconfigure(0, weight=1) for frame_type in self.frame_types: frame_instance = frame_type(container, self, self.time_options_manager, self.mobber_manager, - self.countdown_manager, self.settings_manager, self.tips_manager, self.theme_manager) + self.countdown_manager, self.settings_manager, self.tips_manager, + self.theme_manager) self.frames[frame_type].append(frame_instance) frame_instance.grid(row=0, column=0, sticky=(N, S, E, W)) frame_instance.grid_rowconfigure(0, weight=1) @@ -86,12 +89,22 @@ def __init__(self, *args, **kwargs): self.transparent_frame_position = 0 self.title("Mob Timer") self.bind_all("", self.launch_transparent_countdown_if_blocking) - self.time_options_manager.set_countdown_time(self.settings_manager.get_timer_minutes(), self.settings_manager.get_timer_seconds()) + self.time_options_manager.set_countdown_time(self.settings_manager.get_timer_minutes(), + self.settings_manager.get_timer_seconds()) self.dojo_manager = DojoManager(self) + if self.settings_manager.get_event_logging_enabled(): + self.mobber_manager.subscribe_to_mobber_add(self.add_mobber_callback) + self.mobber_manager.subscribe_to_mobber_remove(self.remove_mobber_callback) + + def remove_mobber_callback(self, mobber_name): + self.event_logging_manager.log(f'Removed: {mobber_name}') - def launch_transparent_countdown_if_blocking(self, event = None): + def add_mobber_callback(self, mobber_name): + self.event_logging_manager.log(f'Added: {mobber_name}') + + def launch_transparent_countdown_if_blocking(self, event=None): if self.frame_is_screen_blocking(): self.show_transparent_countdown_frame() @@ -158,7 +171,7 @@ def show_transparent_countdown_frame(self, extend_minutes=None, extend_seconds=N def get_current_window_geometry(self): return "{0}x{1}+0+0".format( - self.winfo_screenwidth(), self.winfo_screenheight()) + self.winfo_screenwidth(), self.winfo_screenheight()) def disable_resizing(self): for container in self.containers: @@ -190,7 +203,8 @@ def set_full_screen_always_on_top(self): monitor_string = "{}x{}+{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y) container.master.geometry(monitor_string) if not PlatformUtility.platform_is_mac(): - container.master.wait_visibility(container.master) # Mac removing this prevented the issue with the continue screen visibility + container.master.wait_visibility( + container.master) # Mac removing this prevented the issue with the continue screen visibility container.master.attributes("-alpha", 1) def set_partial_screen_transparent(self): @@ -212,7 +226,8 @@ def set_partial_screen_transparent(self): def fade_app(self): for controller in self.containers: - controller.master.attributes("-alpha", self.settings_manager.get_continue_screen_blocker_window_alpha_percent()) + controller.master.attributes("-alpha", + self.settings_manager.get_continue_screen_blocker_window_alpha_percent()) def unfade_app(self): for controller in self.containers: @@ -255,11 +270,10 @@ def toggle_transparent_frame_position_enabled(self): screenheight - window_height) self.geometry(bottom_left_screen) - def rewind_and_extend(self,minutes, seconds): + def rewind_and_extend(self, minutes, seconds): self.extensions_used += 1 self.mobber_manager.rewind_driver() result = self.show_transparent_countdown_frame(minutes, seconds) for minimal_frame in self.frames[MinimalScreenBlockerFrame]: minimal_frame.show_extend_time_button() return result - diff --git a/Infrastructure/MobberManager.py b/Infrastructure/MobberManager.py index a45ac4e..c8eb20e 100644 --- a/Infrastructure/MobberManager.py +++ b/Infrastructure/MobberManager.py @@ -21,6 +21,22 @@ def add_mobber(self, mobber_name): self.fire_mobber_add_callbacks(mobber_name) self.fire_mobber_list_change_callbacks() + def remove_mobber(self, remove_mobber_index): + if self.mobber_count() == 0: + return + self.fire_mobber_remove_callbacks(self.mobber_list[remove_mobber_index]) + del self.mobber_list[remove_mobber_index] + self.fire_mobber_list_change_callbacks() + + def set_mobber_list(self, mobber_list): + if self.mobber_list != mobber_list: + for index in range(0, mobber_list.__len__()): + self.remove_mobber(0) + for mobber_name in mobber_list: + clean_mobber_name = str(mobber_name).strip() + if clean_mobber_name != "" and not self.mobber_list.__contains__(clean_mobber_name): + self.add_mobber(clean_mobber_name) + def subscribe_to_mobber_add(self, mobber_add_callback): self.mobber_add_callbacks.append(mobber_add_callback) @@ -32,12 +48,7 @@ def fire_mobber_add_callbacks(self, mobber_name): def get_mobbers(self): return self.mobber_list - def remove_mobber(self, remove_mobber_index): - if self.mobber_count() == 0: - return - self.fire_mobber_remove_callbacks(self.mobber_list[remove_mobber_index]) - del self.mobber_list[remove_mobber_index] - self.fire_mobber_list_change_callbacks() + def subscribe_to_mobber_remove(self, mobber_remove_callback): self.mobber_remove_callbacks.append(mobber_remove_callback) @@ -107,12 +118,5 @@ def rewind_driver(self): self.update_next_driver_index() self.fire_mobber_list_change_callbacks() - def set_mobber_list(self, mobber_list): - if self.mobber_list != mobber_list: - self.mobber_list = [] - for mobber_name in mobber_list: - clean_mobber_name = str(mobber_name).strip() - if clean_mobber_name != "" and not self.mobber_list.__contains__(clean_mobber_name): - self.mobber_list.append(mobber_name) - self.fire_mobber_list_change_callbacks() + diff --git a/Infrastructure/SettingsManager.py b/Infrastructure/SettingsManager.py index cae732a..9186801 100644 --- a/Infrastructure/SettingsManager.py +++ b/Infrastructure/SettingsManager.py @@ -8,6 +8,7 @@ class SettingsManager(object): CONTINUE_SCREEN_BLOCKER_SETTINGS = "CONTINUE SCREEN BLOCKER SETTINGS" SCREEN_BLOCKER_SETTINGS = "SCREEN BLOCKER SETTINGS" CODE_DOJO = "CODE DOJO" + EVENT_LOGGING = "EVENT LOGGING" def __init__(self): self.config = configparser.ConfigParser() @@ -18,6 +19,7 @@ def __init__(self): self.general_settings_ = self.config[SettingsManager.GENERAL_SETTINGS] self.timer_settings_ = self.config[SettingsManager.TIMER_SETTINGS] self.code_dojo = self.config[SettingsManager.CODE_DOJO] + self.event_logging = self.config[SettingsManager.EVENT_LOGGING] def get_transparent_window_screen_size_percent(self): return self.window_settings_.getfloat("size percentage", 0.3) @@ -109,5 +111,8 @@ def get_dojo_session_id(self): def get_dojo_topic_root(self): return self.code_dojo.get("topic root", "MobTimer") + def get_event_logging_enabled(self): + return self.event_logging.getboolean("enabled", True) + def get_general_enable_unobtrusive_mode_bouncing_screen(self): return self.general_settings_.getboolean("enable unobtrusive mode bouncing screen", False) diff --git a/MobTimer.cfg b/MobTimer.cfg index ebc5598..1ba34fe 100644 --- a/MobTimer.cfg +++ b/MobTimer.cfg @@ -42,5 +42,4 @@ session id = 1337 topic root = MobTimer [EVENT LOGGING] -enabled = True -log file name = MobTimer.log \ No newline at end of file +enabled = False \ No newline at end of file diff --git a/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt b/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt index de4de02..e0e2ce0 100644 --- a/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt +++ b/tests/Infrastructure/MobberManager/TestsMobberManager.test_subscribe_to_mobber_list_changes_random.approved.txt @@ -1,24 +1,47 @@ Mobbers in List for Each Change Action 1: -Action 2:Joe (Driver) (Next), -Action 3:Joe (Driver), Chris (Next), -Action 4:Joe (Driver), Chris, Sam (Next), -Action 5:Joe (Driver), Chris, Sam, John (Next), -Action 6:Joe, Chris (Next), Sam, John (Driver), -Action 7:Joe, Chris (Next), Sam, John (Driver), Bill, -Action 8:Joe, Chris (Driver), Sam (Next), John, Bill, -Action 9:Joe, Chris, Sam (Driver), John (Next), Bill, -Action 10:Joe, Chris (Next), Sam, John (Driver), Bill, -Action 11:Hello, Eric (Next), Joe, -Action 12:Hello, Eric (Driver), Joe (Next), -Action 13:Hello, Eric (Next), Joe (Driver), -Action 14:Hello (Driver), Eric (Next), -Action 15:Eric (Driver) (Next), -Action 16:Eric (Driver) (Next), -Action 17:Eric (Driver), Seth (Next), -Action 18:Seth (Driver), Eric (Next), -Action 19:Seth (Driver), Eric, Fredrick (Next), -Action 20:Seth (Driver), Fredrick (Next), Eric, -Action 21:Seth (Driver), Eric (Next), -Action 22:Eric (Driver) (Next), -Action 23: +Action 2:Joe added +Action 3:Joe (Driver) (Next), +Action 4:Chris added +Action 5:Joe (Driver), Chris (Next), +Action 6:Sam added +Action 7:Joe (Driver), Chris, Sam (Next), +Action 8:John added +Action 9:Joe (Driver), Chris, Sam, John (Next), +Action 10:Joe, Chris (Next), Sam, John (Driver), +Action 11:Bill added +Action 12:Joe, Chris (Next), Sam, John (Driver), Bill, +Action 13:Joe, Chris (Driver), Sam (Next), John, Bill, +Action 14:Joe, Chris, Sam (Driver), John (Next), Bill, +Action 15:Joe, Chris (Next), Sam, John (Driver), Bill, +Action 16:Joe removed +Action 17:Chris, Sam (Next), John, Bill (Driver), +Action 18:Chris removed +Action 19:Sam, John (Next), Bill, +Action 20:Sam removed +Action 21:John (Next), Bill (Driver), +Action 22:Hello added +Action 23:John, Bill (Driver), Hello (Next), +Action 24:Eric added +Action 25:John, Bill (Driver), Hello (Next), Eric, +Action 26:Joe added +Action 27:John, Bill (Driver), Hello, Eric (Next), Joe, +Action 28:John, Bill (Next), Hello, Eric (Driver), Joe, +Action 29:John, Bill (Driver), Hello, Eric, Joe (Next), +Action 30:Hello removed +Action 31:John, Bill (Driver), Eric, Joe (Next), +Action 32:John removed +Action 33:Bill, Eric (Driver), Joe (Next), +Action 34:Bill (Next), Eric, Joe (Driver), +Action 35:Seth added +Action 36:Bill, Eric, Joe (Driver), Seth (Next), +Action 37:Eric, Bill (Next), Joe (Driver), Seth, +Action 38:Fredrick added +Action 39:Eric (Next), Bill, Joe (Driver), Seth, Fredrick, +Action 40:Eric, Joe, Bill (Driver), Seth (Next), Fredrick, +Action 41:Joe removed +Action 42:Eric, Bill, Seth (Driver), Fredrick (Next), +Action 43:Eric removed +Action 44:Bill, Seth (Next), Fredrick (Driver), +Action 45:Bill removed +Action 46:Seth (Driver), Fredrick (Next), diff --git a/tests/Infrastructure/MobberManager/test_MobberManager.py b/tests/Infrastructure/MobberManager/test_MobberManager.py index 20c8412..359b08d 100644 --- a/tests/Infrastructure/MobberManager/test_MobberManager.py +++ b/tests/Infrastructure/MobberManager/test_MobberManager.py @@ -176,6 +176,20 @@ def time_change_callback(mobber_list, driver_index, navigator_index): result["result"] += "\n" + def on_mobber_add(mobber_name): + result["increment"] += 1 + result["result"] += "Action " + result["increment"].__str__() + ":" + mobber_name + " added\n" + + mobber_manager.subscribe_to_mobber_add(on_mobber_add) + + + def on_mobber_remove(mobber_name): + result["increment"] += 1 + result["result"] += "Action " + result["increment"].__str__() + ":" + mobber_name + " removed\n" + + mobber_manager.subscribe_to_mobber_remove(on_mobber_remove) + + mobber_manager.subscribe_to_mobber_list_change(time_change_callback) mobber_manager.add_mobber("Joe")