First pass on rewriting everything as a single package

This commit is contained in:
CMDR-Kiel42 2019-08-04 11:10:56 +02:00
parent 62d808b08a
commit e1752f7794
2 changed files with 302 additions and 307 deletions

View File

@ -2,13 +2,19 @@
import os
import sys
import traceback
import csv
import subprocess
import webbrowser
import json
import requests
import Tkinter as tk
import tkFileDialog as filedialog
import tkMessageBox as confirmDialog
from time import sleep
from . import AutoCompleter
from . import PlaceHolderEntry
from .updater import SpanshUpdater
class SpanshRouter():
def __init__(self, plugin_dir):
@ -22,6 +28,7 @@ class SpanshRouter():
self.next_wp_label = "Next waypoint: "
self.jumpcountlbl_txt = "Estimated jumps left: "
self.parent = None
self.plugin_dir = plugin_dir
self.save_route_path = os.path.join(plugin_dir, 'route.csv')
self.offset_file_path = os.path.join(plugin_dir, 'offset')
self.offset = 0
@ -29,7 +36,7 @@ class SpanshRouter():
self.error_txt = tk.StringVar()
self.plot_error = "Error while trying to plot a route, please try again."
# -- GUI part --
def init_gui(self, parent):
self.parent = parent
parentwidth = parent.winfo_width()
@ -50,11 +57,11 @@ class SpanshRouter():
self.efficiency_slider = tk.Scale(self.frame, from_=1, to=100, orient=tk.HORIZONTAL, label="Efficiency (%)")
self.efficiency_slider.set(60)
self.plot_gui_btn = tk.Button(self.frame, text="Plot route", command=self.show_plot_gui)
self.plot_route_btn = tk.Button(self.frame, text="Calculate", command=plot_route)
self.plot_route_btn = tk.Button(self.frame, text="Calculate", command=self.plot_route)
self.cancel_plot = tk.Button(self.frame, text="Cancel", command=lambda: self.show_plot_gui(False))
self.csv_route_btn = tk.Button(self.frame, text="Import CSV", command=plot_csv)
self.clear_route_btn = tk.Button(self.frame, text="Clear route", command=clear_route)
self.csv_route_btn = tk.Button(self.frame, text="Import CSV", command=self.plot_csv)
self.clear_route_btn = tk.Button(self.frame, text="Clear route", command=self.clear_route)
row = 0
self.waypoint_prev_btn.grid(row=row, columnspan=2)
@ -84,7 +91,7 @@ class SpanshRouter():
self.error_lbl.grid_remove()
row += 1
show_plot_gui(False)
self.show_plot_gui(False)
if not self.route.__len__() > 0:
self.waypoint_prev_btn.grid_remove()
@ -98,14 +105,125 @@ class SpanshRouter():
"It will be installed next time you start EDMC.\n"
"Click to dismiss this message, right click to see what's new.")
self.update_btn = tk.Button(self.frame, text=update_txt, command=lambda: self.update_btn.grid_forget())
self.update_btn.bind("<Button-3>", goto_changelog_page)
self.update_btn.bind("<Button-3>", self.goto_changelog_page)
self.update_btn.grid(row=row, pady=5, columnspan=2)
row += 1
update_gui()
self.update_gui()
return self.frame
def show_plot_gui(self, show=True):
if show:
self.waypoint_prev_btn.grid_remove()
self.waypoint_btn.grid_remove()
self.waypoint_next_btn.grid_remove()
self.jumpcounttxt_lbl.grid_remove()
self.clear_route_btn.grid_remove()
self.plot_gui_btn.grid_remove()
self.csv_route_btn.grid_remove()
self.source_ac.grid()
self.dest_ac.grid()
self.range_entry.grid()
self.efficiency_slider.grid()
self.plot_route_btn.grid()
self.cancel_plot.grid()
# Workaround because EDMC keeps switching the placeholder to bright white
if self.source_ac.get() == self.source_ac.placeholder:
self.source_ac.force_placeholder_color()
if self.dest_ac.get() == self.dest_ac.placeholder:
self.dest_ac.force_placeholder_color()
if self.range_entry.get() == self.range_entry.placeholder:
self.range_entry.force_placeholder_color()
self.show_route_gui(False)
else:
self.source_ac.put_placeholder()
self.dest_ac.put_placeholder()
self.source_ac.grid_remove()
self.dest_ac.grid_remove()
self.range_entry.grid_remove()
self.efficiency_slider.grid_remove()
self.plot_gui_btn.grid_remove()
self.plot_route_btn.grid_remove()
self.cancel_plot.grid_remove()
self.plot_gui_btn.grid()
self.csv_route_btn.grid()
self.show_route_gui(True)
def set_source_ac(self, text):
self.source_ac.delete(0, tk.END)
self.source_ac.insert(0, text)
self.source_ac["fg"] = self.source_ac.default_fg_color
def show_route_gui(self, show):
hide_error()
if not show or not self.route.__len__() > 0:
self.waypoint_prev_btn.grid_remove()
self.waypoint_btn.grid_remove()
self.waypoint_next_btn.grid_remove()
self.jumpcounttxt_lbl.grid_remove()
self.clear_route_btn.grid_remove()
else:
self.waypoint_btn["text"] = self.next_wp_label + self.next_stop
self.jumpcounttxt_lbl["text"] = self.jumpcountlbl_txt + str(self.jumps_left)
self.jumpcounttxt_lbl.grid()
self.waypoint_prev_btn.grid()
self.waypoint_btn.grid()
self.waypoint_next_btn.grid()
if self.offset == 0:
self.waypoint_prev_btn.config(state=tk.DISABLED)
else:
self.waypoint_prev_btn.config(state=tk.NORMAL)
if self.offset == self.route.__len__()-1:
self.waypoint_next_btn.config(state=tk.DISABLED)
else:
self.waypoint_next_btn.config(state=tk.NORMAL)
self.clear_route_btn.grid()
def update_gui(self):
self.show_route_gui(True)
def show_error(self, error):
self.error_txt.set(error)
self.error_lbl.grid()
def hide_error(self):
self.error_lbl.grid_remove()
def enable_plot_gui(self, enable):
if enable:
self.source_ac.config(state=tk.NORMAL)
self.source_ac.update_idletasks()
self.dest_ac.config(state=tk.NORMAL)
self.dest_ac.update_idletasks()
self.efficiency_slider.config(state=tk.NORMAL)
self.efficiency_slider.update_idletasks()
self.range_entry.config(state=tk.NORMAL)
self.range_entry.update_idletasks()
self.plot_route_btn.config(state=tk.NORMAL, text="Calculate")
self.plot_route_btn.update_idletasks()
self.cancel_plot.config(state=tk.NORMAL)
self.cancel_plot.update_idletasks()
else:
self.source_ac.config(state=tk.DISABLED)
self.source_ac.update_idletasks()
self.dest_ac.config(state=tk.DISABLED)
self.dest_ac.update_idletasks()
self.efficiency_slider.config(state=tk.DISABLED)
self.efficiency_slider.update_idletasks()
self.range_entry.config(state=tk.DISABLED)
self.range_entry.update_idletasks()
self.plot_route_btn.config(state=tk.DISABLED, text="Computing...")
self.plot_route_btn.update_idletasks()
self.cancel_plot.config(state=tk.DISABLED)
self.cancel_plot.update_idletasks()
def open_last_route(self):
try:
@ -142,52 +260,173 @@ class SpanshRouter():
def goto_next_waypoint(self):
if self.offset < self.route.__len__()-1:
update_route(1)
self.update_route(1)
def goto_prev_waypoint(self):
if self.offset > 0:
update_route(-1)
def show_plot_gui(self, show=True):
if show:
self.waypoint_prev_btn.grid_remove()
self.waypoint_btn.grid_remove()
self.waypoint_next_btn.grid_remove()
self.jumpcounttxt_lbl.grid_remove()
self.clear_route_btn.grid_remove()
self.plot_gui_btn.grid_remove()
self.csv_route_btn.grid_remove()
self.source_ac.grid()
self.dest_ac.grid()
self.range_entry.grid()
self.efficiency_slider.grid()
self.plot_route_btn.grid()
self.cancel_plot.grid()
# Workaround because EDMC keeps switching the placeholder to bright white
if self.source_ac.get() == self.source_ac.placeholder:
self.source_ac.force_placeholder_color()
if self.dest_ac.get() == self.dest_ac.placeholder:
self.dest_ac.force_placeholder_color()
if self.range_entry.get() == self.range_entry.placeholder:
self.range_entry.force_placeholder_color()
show_route_gui(False)
self.update_route(-1)
def update_route(self, direction=1):
if direction > 0:
self.jumps_left -= int(self.route[self.offset][1])
self.offset += 1
else:
self.source_ac.put_placeholder()
self.dest_ac.put_placeholder()
self.source_ac.grid_remove()
self.dest_ac.grid_remove()
self.range_entry.grid_remove()
self.efficiency_slider.grid_remove()
self.plot_gui_btn.grid_remove()
self.plot_route_btn.grid_remove()
self.cancel_plot.grid_remove()
self.plot_gui_btn.grid()
self.csv_route_btn.grid()
show_route_gui(True)
self.offset -= 1
self.jumps_left += int(self.route[self.offset][1])
if self.offset >= self.route.__len__():
self.next_stop = "End of the road!"
self.update_gui()
else:
self.next_stop = self.route[self.offset][0]
self.update_gui()
self.copy_waypoint(self.parent)
if __name__ == "__main__":
pass
def goto_changelog_page(self):
changelog_url = 'https://github.com/CMDR-Kiel42/EDMC_SpanshRouter/blob/master/CHANGELOG.md#'
changelog_url += self.spansh_updater.version.replace('.', '')
webbrowser.open(changelog_url)
def plot_csv(self):
filename = filedialog.askopenfilename(filetypes = (("csv files", "*.csv"),)) # show an "Open" dialog box and return the path to the selected file
if filename.__len__() > 0:
with open(filename, 'r') as csvfile:
route_reader = csv.reader(csvfile)
# Skip the header
route_reader.next()
self.jumps_left = 0
for row in route_reader:
if row not in (None, "", []):
self.route.append([row[0], row[4]])
self.jumps_left += int(row[4])
self.offset = 0
self.next_stop = self.route[0][0]
self.copy_waypoint()
self.update_gui()
def plot_route(self):
self.hide_error()
try:
source = self.source_ac.get()
dest = self.dest_ac.get()
efficiency = self.efficiency_slider.get()
if ( source and source != self.source_ac.placeholder and
dest and dest != self.dest_ac.placeholder ):
range_ly = float(self.range_entry.get())
job_url="https://spansh.co.uk/api/route?"
results = requests.post(job_url, params={
"efficiency": efficiency,
"range": range_ly,
"from": source,
"to": dest
}, headers={'User-Agent': "EDMC_SpanshRouter 1.0"})
if results.status_code == 202:
self.enable_plot_gui(False)
tries = 0
while(tries < 20):
response = json.loads(results.content)
job = response["job"]
results_url = "https://spansh.co.uk/api/results/" + job
route_response = requests.get(results_url, timeout=5)
if route_response.status_code != 202:
break
tries += 1
sleep(1)
if route_response:
if route_response.status_code == 200:
route = json.loads(route_response.content)["result"]["system_jumps"]
self.clear_route(show_dialog=False)
for waypoint in route:
self.route.append([waypoint["system"], str(waypoint["jumps"])])
self.jumps_left += waypoint["jumps"]
self.enable_plot_gui(True)
self.show_plot_gui(False)
self.offset = 0
self.next_stop = self.route[0][0]
self.copy_waypoint()
self.update_gui()
else:
sys.stderr.write("Failed to query plotted route from Spansh: code " + str(route_response.status_code) + route_response.text)
self.enable_plot_gui(True)
self.show_error(self.plot_error)
else:
sys.stderr.write("Query to Spansh timed out")
self.enable_plot_gui(True)
self.show_error(self.plot_error)
else:
sys.stderr.write("Failed to query route from Spansh: code " + str(results.status_code) + results.text)
self.enable_plot_gui(True)
self.show_error(self.plot_error)
except NameError:
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
sys.stderr.write(''.join('!! ' + line for line in lines))
self.enable_plot_gui(True)
self.show_error(self.plot_error)
def clear_route(self, show_dialog=True):
clear = confirmDialog.askyesno("SpanshRouter","Are you sure you want to clear the current route?") if show_dialog else True
if clear:
self.offset = 0
self.route = []
self.next_waypoint = ""
self.jumps_left = 0
try:
os.remove(self.save_route_path)
except:
print("No route to delete")
try:
os.remove(self.offset_file_path)
except:
print("No offset file to delete")
self.update_gui()
def save_route(self):
if self.route.__len__() != 0:
with open(self.save_route_path, 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(self.route)
with open(self.offset_file_path, 'w') as offset_fh:
offset_fh.write(str(self.offset))
else:
try:
os.remove(self.save_route_path)
os.remove(self.offset_file_path)
except:
print("No route to delete")
def check_for_update(self):
url = "https://raw.githubusercontent.com/CMDR-Kiel42/EDMC_SpanshRouter/master/version.json"
try:
response = requests.get(url, timeout=2)
if response.status_code == 200:
if self.plugin_version != response.content:
self.update_available = True
self.spansh_updater = SpanshUpdater(response.content, self.plugin_dir)
if not self.spansh_updater.download_zip():
sys.stderr.write("Error when downloading the latest SpanshRouter update")
else:
sys.stderr.write("Could not query latest SpanshRouter version: " + str(response.status_code) + response.text)
except NameError:
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
sys.stderr.write(''.join('!! ' + line for line in lines))
def install_update(self):
self.install()

266
load.py
View File

@ -1,273 +1,29 @@
import Tkinter as tk
import tkFileDialog as filedialog
import tkMessageBox as confirmDialog
import sys
import csv
import os
import json
import webbrowser
import requests
import traceback
import subprocess
from time import sleep
from SpanshRouter import updater as SpanshUpdater
from SpanshRouter import AutoCompleter
from SpanshRouter import PlaceHolderEntry
from SpanshRouter import SpanshRouter
this = sys.modules[__name__]
spansh_router = None
# Done
def plugin_start(plugin_dir):
# Check for newer versions
url = "https://raw.githubusercontent.com/CMDR-Kiel42/EDMC_SpanshRouter/master/version.json"
try:
response = requests.get(url, timeout=2)
if response.status_code == 200:
if this.plugin_version != response.content:
this.update_available = True
this.spansh_updater = SpanshUpdater(response.content, plugin_dir)
if not this.spansh_updater.download_zip():
sys.stderr.write("Error when downloading the latest SpanshRouter update")
else:
sys.stderr.write("Could not query latest SpanshRouter version: " + str(response.status_code) + response.text)
except NameError:
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
sys.stderr.write(''.join('!! ' + line for line in lines))
finally:
global spansh_router
spansh_router = SpanshRouter(plugin_dir)
spansh_router.check_for_update()
spansh_router.open_last_route()
def plugin_stop():
if this.route.__len__() != 0:
# Save route for next time
with open(this.save_route_path, 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(this.route)
global spansh_router
spansh_router.save_route()
with open(this.offset_file_path, 'w') as offset_fh:
offset_fh.write(str(this.offset))
else:
try:
os.remove(this.save_route_path)
os.remove(this.offset_file_path)
except:
print("No route to delete")
if this.update_available:
this.spansh_updater.install()
def show_error(error):
this.error_txt.set(error)
this.error_lbl.grid()
def hide_error():
this.error_lbl.grid_remove()
def show_route_gui(show):
hide_error()
if not show or not this.route.__len__() > 0:
this.waypoint_prev_btn.grid_remove()
this.waypoint_btn.grid_remove()
this.waypoint_next_btn.grid_remove()
this.jumpcounttxt_lbl.grid_remove()
this.clear_route_btn.grid_remove()
else:
this.waypoint_btn["text"] = this.next_wp_label + this.next_stop
this.jumpcounttxt_lbl["text"] = this.jumpcountlbl_txt + str(this.jumps_left)
this.jumpcounttxt_lbl.grid()
this.waypoint_prev_btn.grid()
this.waypoint_btn.grid()
this.waypoint_next_btn.grid()
if this.offset == 0:
this.waypoint_prev_btn.config(state=tk.DISABLED)
else:
this.waypoint_prev_btn.config(state=tk.NORMAL)
if this.offset == this.route.__len__()-1:
this.waypoint_next_btn.config(state=tk.DISABLED)
else:
this.waypoint_next_btn.config(state=tk.NORMAL)
this.clear_route_btn.grid()
def update_gui():
show_route_gui(True)
def plot_csv(self=None):
filename = filedialog.askopenfilename(filetypes = (("csv files", "*.csv"),)) # show an "Open" dialog box and return the path to the selected file
if filename.__len__() > 0:
with open(filename, 'r') as csvfile:
route_reader = csv.reader(csvfile)
# Skip the header
route_reader.next()
this.jumps_left = 0
for row in route_reader:
if row not in (None, "", []):
this.route.append([row[0], row[4]])
this.jumps_left += int(row[4])
this.offset = 0
this.next_stop = this.route[0][0]
copy_waypoint()
update_gui()
def enable_plot_gui(enable):
if enable:
this.source_ac.config(state=tk.NORMAL)
this.source_ac.update_idletasks()
this.dest_ac.config(state=tk.NORMAL)
this.dest_ac.update_idletasks()
this.efficiency_slider.config(state=tk.NORMAL)
this.efficiency_slider.update_idletasks()
this.range_entry.config(state=tk.NORMAL)
this.range_entry.update_idletasks()
this.plot_route_btn.config(state=tk.NORMAL, text="Calculate")
this.plot_route_btn.update_idletasks()
this.cancel_plot.config(state=tk.NORMAL)
this.cancel_plot.update_idletasks()
else:
this.source_ac.config(state=tk.DISABLED)
this.source_ac.update_idletasks()
this.dest_ac.config(state=tk.DISABLED)
this.dest_ac.update_idletasks()
this.efficiency_slider.config(state=tk.DISABLED)
this.efficiency_slider.update_idletasks()
this.range_entry.config(state=tk.DISABLED)
this.range_entry.update_idletasks()
this.plot_route_btn.config(state=tk.DISABLED, text="Computing...")
this.plot_route_btn.update_idletasks()
this.cancel_plot.config(state=tk.DISABLED)
this.cancel_plot.update_idletasks()
def plot_route(self=None):
hide_error()
try:
source = this.source_ac.get()
dest = this.dest_ac.get()
efficiency = this.efficiency_slider.get()
if ( source and source != this.source_ac.placeholder and
dest and dest != this.dest_ac.placeholder ):
range_ly = float(this.range_entry.get())
job_url="https://spansh.co.uk/api/route?"
results = requests.post(job_url, params={
"efficiency": efficiency,
"range": range_ly,
"from": source,
"to": dest
}, headers={'User-Agent': "EDMC_SpanshRouter 1.0"})
if results.status_code == 202:
enable_plot_gui(False)
tries = 0
while(tries < 20):
response = json.loads(results.content)
job = response["job"]
results_url = "https://spansh.co.uk/api/results/" + job
route_response = requests.get(results_url, timeout=5)
if route_response.status_code != 202:
break
tries += 1
sleep(1)
if route_response:
if route_response.status_code == 200:
route = json.loads(route_response.content)["result"]["system_jumps"]
clear_route(show_dialog=False)
for waypoint in route:
this.route.append([waypoint["system"], str(waypoint["jumps"])])
this.jumps_left += waypoint["jumps"]
enable_plot_gui(True)
show_plot_gui(False)
this.offset = 0
this.next_stop = this.route[0][0]
copy_waypoint()
update_gui()
else:
sys.stderr.write("Failed to query plotted route from Spansh: code " + str(route_response.status_code) + route_response.text)
enable_plot_gui(True)
show_error(this.plot_error)
else:
sys.stderr.write("Query to Spansh timed out")
enable_plot_gui(True)
show_error(this.plot_error)
else:
sys.stderr.write("Failed to query route from Spansh: code " + str(results.status_code) + results.text)
enable_plot_gui(True)
show_error(this.plot_error)
except NameError:
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
sys.stderr.write(''.join('!! ' + line for line in lines))
enable_plot_gui(True)
show_error(this.plot_error)
def clear_route(self=None, show_dialog=True):
clear = confirmDialog.askyesno("SpanshRouter","Are you sure you want to clear the current route?") if show_dialog else True
if clear:
this.offset = 0
this.route = []
this.next_waypoint = ""
this.jumps_left = 0
try:
os.remove(this.save_route_path)
except:
print("No route to delete")
try:
os.remove(this.offset_file_path)
except:
print("No offset file to delete")
update_gui()
def update_route(direction=1):
if direction > 0:
this.jumps_left -= int(this.route[this.offset][1])
this.offset += 1
else:
this.offset -= 1
this.jumps_left += int(this.route[this.offset][1])
if this.offset >= this.route.__len__():
this.next_stop = "End of the road!"
update_gui()
else:
this.next_stop = this.route[this.offset][0]
update_gui()
copy_waypoint(this.parent)
if spansh_router.update_available:
spansh_router.install_update()
def journal_entry(cmdr, is_beta, system, station, entry, state):
global spansh_router
if (entry['event'] in ['FSDJump', 'Location', 'SupercruiseEntry', 'SupercruiseExit']) and entry["StarSystem"] == this.next_stop:
update_route()
this.source_ac.delete(0, tk.END)
this.source_ac.insert(0, entry["StarSystem"])
this.source_ac["fg"] = this.source_ac.default_fg_color
spansh_router.update_route()
spansh_router.set_source_ac(entry["StarSystem"])
elif entry['event'] == 'FSSDiscoveryScan' and entry['SystemName'] == this.next_stop:
update_route()
def goto_changelog_page(self=None):
changelog_url = 'https://github.com/CMDR-Kiel42/EDMC_SpanshRouter/blob/master/CHANGELOG.md#'
changelog_url += this.spansh_updater.version.replace('.', '')
webbrowser.open(changelog_url)
spansh_router.update_route()
def plugin_app(parent):
global spansh_router
spansh_router.init_gui(parent)