Mode to find nearby unscanned stars. master
authorCMDR furrycat <elite@furrycat.net>
Mon, 6 Nov 2017 22:14:18 +0000 (22:14 +0000)
committerCMDR furrycat <elite@furrycat.net>
Mon, 6 Nov 2017 22:14:18 +0000 (22:14 +0000)
If a search radius is configured - it defaults to 0 - we now search for
up to 50 systems which have missing arrival star information within that
radius of the current system.

load.py

diff --git a/load.py b/load.py
index 2e04f36..b6bf3a4 100644 (file)
--- a/load.py
+++ b/load.py
@@ -7,28 +7,47 @@ import Tkinter as tk
 from ttkHyperlinkLabel import HyperlinkLabel
 import myNotebook as nb
 
+from l10n import Locale
 from config import config
 
 this = sys.modules[__name__]
 this.frame = None
 this.edsm_session = None
 this.edsm_data = None
+this.edsm_sphere_data = None
 this.cache = {}
 this.config_prefix = 'plugin.MissingArrivalStar'
 
 def plugin_start():
   return 'MissingArrivalStar'
 
+def update_ui():
+  if this.nearby.get() > 0:
+    this.nearby_widget_label.grid(row = 1, column = 0, sticky = tk.W)
+    this.nearby_widget.grid(row = 1, column = 1, sticky = tk.W)
+  else:
+    try:
+      this.nearby_widget_label.grid_remove()
+      this.nearby_widget.grid_remove()
+    except:
+      pass
+
 def plugin_app(parent):
   this.frame = tk.Frame(parent)
   this.frame.columnconfigure(2, weight = 1)
   this.frame.bind('<<MissingArrivalStar>>', edsm_callback)
+  this.frame.bind('<<MissingArrivalStarSphere>>', edsm_sphere_callback)
   this.widget_label = tk.Label(this.frame, text = 'Arrival star:')
   this.widget_label.grid(row = 0, column = 0, sticky = tk.W)
   this.widget = tk.Label(this.frame, text = '')
   this.widget.grid(row = 0, column = 1, sticky = tk.W)
+  this.nearby_widget_label = tk.Label(this.frame, text = 'Nearby:')
+  this.nearby_widget = HyperlinkLabel(this.frame)
+  this.nearby_entry = None
   this.last_system = None
   this.event = tk.StringVar(value = get_pref('event', 'FSDJump'))
+  this.nearby = tk.IntVar(value = get_int_pref('nearby', 0))
+  update_ui()
   return this.frame
 
 def plugin_prefs(parent, cmdr, is_beta):
@@ -36,17 +55,29 @@ def plugin_prefs(parent, cmdr, is_beta):
   nb.Label(frame, text = 'Query EDSM for arrival star:').grid(row = 0, padx = 10, pady = (10, 0), sticky = tk.W)
   nb.Radiobutton(frame, variable = this.event, value = 'StartJump', text = "When jump is initiated").grid(row = 1, column = 0, padx = 10, sticky = tk.W)
   nb.Radiobutton(frame, variable = this.event, value = 'FSDJump', text = "On arrival in system").grid(row = 2, column = 0, padx = 10, sticky = tk.W)
+  nb.Label(frame, text = 'Search radius (lightyears) for systems with incomplete EDSM data:').grid(row = 3, column = 0, padx = 10, pady = (10, 0), sticky = tk.W)
+  this.nearby_entry = nb.Entry(frame)
+  this.nearby_entry.grid(row = 4, column = 0, padx = 10, sticky = tk.W)
+  this.nearby_entry.config(width = 4)
+  this.nearby_entry.insert(0, Locale.stringFromNumber(this.nearby.get()))
   return frame
 
 def get_pref(key, default = None):
   value = config.get('{}.{}'.format(this.config_prefix, key))
   return value if value is not None else default
 
+def get_int_pref(key, default = None):
+  value = config.getint('{}.{}'.format(this.config_prefix, key))
+  return value if value is not None else default
+
 def set_pref(key, value):
   return config.set('{}.{}'.format(this.config_prefix, key), value)
 
 def prefs_changed(cmdr, is_beta):
   set_pref('event', this.event.get())
+  this.nearby.set(Locale.numberFromString(this.nearby_entry.get()))
+  set_pref('nearby', this.nearby.get())
+  update_ui()
 
 def query_on_arrival():
   return get_pref('event', 'FSDJump') == 'FSDJump'
@@ -61,19 +92,36 @@ def arrival_star_checking():
   highlight(False)
   this.widget['text'] = 'Checking EDSM'
 
+def nearby_star_checking(text = 'Checking EDSM'):
+  this.nearby_widget['text'] = text
+  this.nearby_widget['url'] = ''
+
 def arrival_star_known(star_class):
   highlight(False)
   this.widget['text'] = star_class
 
+def nearby_star_known(star, url = None):
+  this.nearby_widget['text'] = star
+  this.nearby_widget['url'] = url if url is not None else star
+
 def arrival_star_unknown():
   highlight(True)
   this.widget['text'] = 'Scan needed!'
 
+def nearby_star_unknown(star, name = None):
+  this.nearby_widget['text'] = star
+  this.nearby_widget['url'] = 'https://www.edsm.net/show-system?systemName={}'.format(name if name is not None else star)
+
 def arrival_star_error():
   highlight(True)
   this.widget['text'] = 'ERROR!'
   plug.show_error('Failed to query EDSM for arrival star')
 
+def nearby_star_error():
+  this.nearby_widget['text'] = 'ERROR!'
+  this.nearby_widget['url'] = ''
+  plug.show_error('Failed to query EDSM for nearby stars')
+
 def journal_entry(cmdr, is_beta, system, station, entry, state):
   if is_beta:
     arrival_star_known('BETA')
@@ -106,11 +154,18 @@ def cmdr_data(data, is_beta):
 def query_arrival_star(system):
   if system in this.cache:
     arrival_star_known(this.cache[system])
+    query_nearby_star(system)
   else:
     thread = threading.Thread(target = edsm_query, name = 'EDSM query', args = (system,))
     thread.daemon = True
     thread.start()
 
+def query_nearby_star(system):
+  if this.nearby.get() > 0:
+    thread = threading.Thread(target = edsm_sphere_query, name = 'EDSM query', args = (system, this.nearby.get()))
+    thread.daemon = True
+    thread.start()
+
 def edsm_query(system):
   if not this.edsm_session:
     this.edsm_session = requests.Session()
@@ -125,15 +180,68 @@ def edsm_query(system):
     arrival_star_error()
     this.edsm_data = None
 
+def edsm_sphere_query(reference, radius):
+  if not this.edsm_session:
+    this.edsm_session = requests.Session()
+
+  try:
+    nearby_star_checking()
+    r = this.edsm_session.get('https://www.edsm.net/api-v1/sphere-systems/systemName/{}/radius/{}'.format(urllib2.quote(reference), radius), timeout = 30)
+    r.raise_for_status()
+    edsm_data = r.json()
+    if len(edsm_data):
+      systems = [system for system in edsm_data if system['name'] not in this.cache and system['name'] != reference]
+      if len(systems):
+        systems.sort(key = lambda system: system['distance'])
+        distances = { system['name']: system['distance'] for system in systems }
+        names = [system['name'] for system in systems[:50]]
+        nearby_star_checking('Checking {}'.format(len(names)))
+        r = this.edsm_session.get('https://www.edsm.net/api-v1/systems?{}&showPrimaryStar=1'.format('&'.join(['systemName%5b%5d={}'.format(urllib2.quote(name)) for name in names])), timeout = 10)
+        r.raise_for_status()
+        edsm_data = r.json()
+        if len(edsm_data):
+          edsm_data.sort(key = lambda system: distances[system['name']])
+          this.edsm_sphere_data = [{'name': system['name'], 'primaryStar': system['primaryStar'], 'distance': distances[system['name']]} for system in edsm_data]
+        else:
+          this.edsm_sphere_data = []
+        this.frame.event_generate('<<MissingArrivalStarSphere>>', when = 'tail')
+      else:
+        nearby_star_known('{} known'.format(len(edsm_data)), '')
+    else:
+      nearby_star_known('No known systems', '')
+  except:
+    nearby_star_error()
+    this.edsm_sphere_data = None
+
 def edsm_callback(event):
   if this.edsm_data is None:
     return
   if len(this.edsm_data):
+    system = this.edsm_data.get('name')
     star = this.edsm_data.get('primaryStar', None)
     if star is None:
       arrival_star_unknown()
     else:
-      this.cache[this.edsm_data.get('name')] = star['type']
+      this.cache[system] = star['type']
       arrival_star_known(star['type'])
+    query_nearby_star(system)
   else:
     arrival_star_known('Unknown system')
+
+def edsm_sphere_callback(event):
+  if this.edsm_sphere_data is None:
+    return
+  if len(this.edsm_sphere_data):
+    found = False
+    for data in this.edsm_sphere_data:
+      star = data.get('primaryStar', None)
+      if star is None:
+        if not found:
+          nearby_star_unknown('{} ({}Ly)'.format(data.get('name'), data.get('distance')), data.get('name'))
+          found = True
+      else:
+        this.cache[data.get('name')] = star['type']
+    if not found:
+      nearby_star_known('Known', '')
+  else:
+    nearby_star_known('')