chore: Setup tox+appveyor, refomat python code, prepare rust code to add branch pruning to search
This commit is contained in:
		
							parent
							
								
									865889712e
								
							
						
					
					
						commit
						2636ecbdb9
					
				
					 35 changed files with 1245 additions and 926 deletions
				
			
		
							
								
								
									
										23
									
								
								.appveyor.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.appveyor.yml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| image: Visual Studio 2019 | ||||
| platform: x64 | ||||
| version: 0.1.{build} | ||||
| branches: | ||||
|   only: | ||||
|   - pyqt_gui | ||||
| 
 | ||||
| environment: | ||||
|   VCVARS: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat | ||||
|   VCVARSARG: x64 | ||||
| 
 | ||||
| install: | ||||
|   - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe | ||||
|   - rustup-init -yv --default-toolchain nightly --default-host x86_64-pc-windows-msvc | ||||
|   - pip install tox | ||||
| 
 | ||||
| 
 | ||||
| before_build: | ||||
|   - if defined VCVARS call "%VCVARS%" %VCVARSARG% | ||||
|   - conda activate | ||||
| 
 | ||||
| test_script: | ||||
|   - tox | ||||
							
								
								
									
										2
									
								
								.cargo/config
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.cargo/config
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| [build] | ||||
| target-dir = "build\\temp.win-amd64-3.7\\ed_lrr_gui" | ||||
							
								
								
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -15,4 +15,5 @@ __pycache__ | |||
| build | ||||
| *.pdf | ||||
| .history | ||||
| pip-wheel-metadata | ||||
| .tox | ||||
| pip-wheel-metadata | ||||
|  |  | |||
							
								
								
									
										2
									
								
								LICENSE
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
										
									
									
									
								
							|  | @ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| SOFTWARE. | ||||
|  |  | |||
|  | @ -1,3 +1,3 @@ | |||
| include rust/Cargo.toml | ||||
| include rust/.cargo/config | ||||
| recursive-include rust/src * | ||||
| recursive-include rust/src * | ||||
|  |  | |||
							
								
								
									
										12
									
								
								Pipfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Pipfile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| [[source]] | ||||
| name = "pypi" | ||||
| url = "https://pypi.org/simple" | ||||
| verify_ssl = true | ||||
| 
 | ||||
| [dev-packages] | ||||
| 
 | ||||
| [packages] | ||||
| ed-lrr-gui = {path = "."} | ||||
| 
 | ||||
| [requires] | ||||
| python_version = "3.7" | ||||
							
								
								
									
										10
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
										
									
									
									
								
							|  | @ -1,3 +1,9 @@ | |||
| # Prerequisites | ||||
| 
 | ||||
| - conda (miniconda/anaconda) | ||||
| - Visual Studio 2019 | ||||
| - nightly rust compiler (`x86_64-pc-windows-msvc`) | ||||
| 
 | ||||
| # Testing | ||||
| 
 | ||||
| ```bash | ||||
|  | @ -14,7 +20,7 @@ rs_gui_test | |||
| conda create -n ed_lrr_gui_env python=3 | ||||
| conda activate ed_lrr_gui_env | ||||
| python build_gui.py | ||||
| pip install setuptools_rust | ||||
| pip install setuptools_rust pyinstaller | ||||
| pip install . | ||||
| python setup.py build | ||||
| python setup.py bdist_wheel | ||||
|  | @ -38,4 +44,4 @@ cd .. | |||
| 
 | ||||
| # TODO | ||||
| - integrate callbacks into the GUI: WIP | ||||
|   - QTimer pulls from queue updates UI (every 100ms) | ||||
|   - QTimer pulls from queue updates UI (every 100ms) | ||||
|  |  | |||
							
								
								
									
										23
									
								
								appveyor.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								appveyor.yml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| image: Visual Studio 2019 | ||||
| platform: x64 | ||||
| version: 0.1.{build} | ||||
| branches: | ||||
|   only: | ||||
|   - pyqt_gui | ||||
| 
 | ||||
| environment: | ||||
|   VCVARS: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat | ||||
|   VCVARSARG: x64 | ||||
| 
 | ||||
| install: | ||||
|   - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe | ||||
|   - rustup-init -yv --default-toolchain nightly --default-host x86_64-pc-windows-msvc | ||||
|   - pip install tox | ||||
| 
 | ||||
| 
 | ||||
| before_build: | ||||
|   - if defined VCVARS call "%VCVARS%" %VCVARSARG% | ||||
|   - conda activate | ||||
| 
 | ||||
| test_script: | ||||
|   - tox | ||||
							
								
								
									
										21
									
								
								build.bat
									
										
									
									
									
								
							
							
						
						
									
										21
									
								
								build.bat
									
										
									
									
									
								
							|  | @ -1,11 +1,10 @@ | |||
| rm -rf build dist *.egg-info exe | ||||
| python build_gui.py | ||||
| pip uninstall -y ed_lrr_gui | ||||
| pip install -I . setuptools_rust | ||||
| python setup.py build | ||||
| python setup.py bdist_wheel | ||||
| python setup.py sdist | ||||
| mkdir exe | ||||
| cd exe | ||||
| pyinstaller --noupx --noconsole --key="ED_LRR_GUI" --name ED_LRR_GUI ..\ed_lrr_gui\__main__.py | ||||
| cd .. | ||||
| @echo off | ||||
| :: TODO: convert to python script | ||||
| :: set up new conda env, install packages, build, remove conda env | ||||
| call conda create -y -n ed_lrr python=3 pycrypto || exit /b 1 | ||||
| call conda activate ed_lrr || exit /b 1 | ||||
| call conda install -y -c conda-forge nuitka | ||||
| vcvars x64 | ||||
| python build.py | ||||
| call conda deactivate || exit /b 1 | ||||
| call conda env remove -n ed_lrr || exit /b 1 | ||||
							
								
								
									
										66
									
								
								build.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								build.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| import subprocess as SP | ||||
| from glob import glob | ||||
| import os | ||||
| import shutil | ||||
| import pkg_resources as pkg | ||||
| from contextlib import contextmanager | ||||
| 
 | ||||
| @contextmanager | ||||
| def in_dir(name,remove=False): | ||||
|     pwd=os.getcwd() | ||||
|     if os.path.isdir(name): | ||||
|         shutil.rmtree(name) | ||||
|     os.makedirs(name) | ||||
|     os.chdir(name) | ||||
|     yield | ||||
|     os.chdir(pwd) | ||||
|     if remove: | ||||
|         shutil.rmtree(name) | ||||
| 
 | ||||
| SP.check_call(["pip", "install", "PyQt5"]) | ||||
| 
 | ||||
| ui_path = os.path.dirname(os.path.abspath(__file__)) | ||||
| for root, folders, files in os.walk(ui_path): | ||||
|     for file in files: | ||||
|         file = os.path.join(root, file) | ||||
|         outfile, ext = os.path.splitext(file) | ||||
|         if ext == ".ui": | ||||
|             outfile = outfile + ".py" | ||||
|             print(os.path.basename(file), "->", os.path.basename(outfile)) | ||||
|             SP.check_call(["pyuic5", "--from-imports", "-o", outfile, file]) | ||||
| 
 | ||||
| SP.check_call(["pip", "install", ".[dev]"]) | ||||
| main_py=os.path.abspath("ed_lrr_gui\__main__.py") | ||||
| with in_dir("exe"): | ||||
|     with in_dir("pyinstaller"): | ||||
|         SP.check_call( | ||||
|             [ | ||||
|                 "pyinstaller", | ||||
|                 "--clean", | ||||
|                 "--noupx", | ||||
|                 "-c", | ||||
|                 '--key="ED_LRR_GUI"', | ||||
|                 "--name", | ||||
|                 "ED_LRR", | ||||
|                 main_py, | ||||
|             ] | ||||
|         ) | ||||
|     with in_dir("nuitka"): | ||||
|         SP.check_call( | ||||
|             [ | ||||
|                 "python", | ||||
|                 "-m", | ||||
|                 "nuitka", | ||||
|                 "--plugin-enable=multiprocessing", | ||||
|                 "--plugin-enable=qt-plugins", | ||||
|                 "--standalone", | ||||
|                 "--follow-imports", | ||||
|                 main_py, | ||||
|             ] | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| # with in_dir("installer"): | ||||
| #     shutil.rmtree("Output") | ||||
| #     SP.check_call(["iscc", "/QP", "ED_LRR.iss"]) | ||||
| 
 | ||||
|  | @ -2,4 +2,4 @@ rm -rfv _*.pyd *.egg-info pip-wheel-metadata dist exe build __pycache__ | |||
| cd rust | ||||
| cargo clean | ||||
| cargo clean --release | ||||
| cd .. | ||||
| cd .. | ||||
|  |  | |||
							
								
								
									
										2
									
								
								docs/.vscode/settings.json
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								docs/.vscode/settings.json
									
										
									
									
										vendored
									
									
								
							|  | @ -8,4 +8,4 @@ | |||
|         "latex", | ||||
|         "plaintext" | ||||
|     ] | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -45,4 +45,4 @@ watch: | |||
| 	watchexec -w src -w data -w filters -w Makefile make all | ||||
| 
 | ||||
| clean: | ||||
| 	-rm $(PDFS) $(IMGS) | ||||
| 	-rm $(PDFS) $(IMGS) | ||||
|  |  | |||
|  | @ -1,18 +1,19 @@ | |||
| from panflute import * | ||||
| import tempfile | ||||
| import sys | ||||
| from jinja2 import Template, Environment, PackageLoader, select_autoescape | ||||
| import contextlib | ||||
| import io | ||||
| import hashlib | ||||
| from dateutil.parser import parse as dateparse | ||||
| from functools import partial | ||||
| import subprocess as SP | ||||
| import panflute as pf | ||||
| import os | ||||
| import csv | ||||
| import datetime | ||||
| import hashlib | ||||
| import io | ||||
| import os | ||||
| import re | ||||
| import subprocess as SP | ||||
| import sys | ||||
| import tempfile | ||||
| from functools import partial | ||||
| 
 | ||||
| import panflute as pf | ||||
| from dateutil.parser import parse as dateparse | ||||
| from jinja2 import Environment, PackageLoader, Template, select_autoescape | ||||
| from panflute import * | ||||
| 
 | ||||
| 
 | ||||
| def remove_pound(elem, doc): | ||||
|  | @ -29,10 +30,10 @@ def fix_color(elem, doc): | |||
| 
 | ||||
| def update_date(elem, doc): | ||||
|     if type(elem) == MetaMap: | ||||
|         datefmt = doc.get_metadata('datefmt', "%Y-%m-%d") | ||||
|         datefmt = doc.get_metadata("datefmt", "%Y-%m-%d") | ||||
|         today = datetime.date.today().strftime(datefmt) | ||||
|         date = dateparse(doc.get_metadata('date', today)).date() | ||||
|         elem['date'] = MetaInlines(Str(date.strftime(datefmt))) | ||||
|         date = dateparse(doc.get_metadata("date", today)).date() | ||||
|         elem["date"] = MetaInlines(Str(date.strftime(datefmt))) | ||||
|         return elem | ||||
| 
 | ||||
| 
 | ||||
|  | @ -42,8 +43,7 @@ def csv_table(elem, doc): | |||
|         ext = os.path.splitext(elem.url)[1][1:] | ||||
|         if ext == "csv": | ||||
|             caption = elem.content | ||||
|             has_header = elem.attributes.get( | ||||
|                 'has-header', "false").lower() == "true" | ||||
|             has_header = elem.attributes.get("has-header", "false").lower() == "true" | ||||
|             with open(elem.url) as f: | ||||
|                 reader = csv.reader(f) | ||||
|                 body = [] | ||||
|  | @ -62,7 +62,12 @@ def code_refs(elem, doc): | |||
|             label = label.text | ||||
|             filename = re.findall(r"^\[@lst:(.*)\]$", label) or [None] | ||||
|             if filename[0] in doc.inc_files: | ||||
|                 return [RawInline("\\hyperref[{}]{{{}}}".format(filename[0], filename[0]), format="tex")] | ||||
|                 return [ | ||||
|                     RawInline( | ||||
|                         "\\hyperref[{}]{{{}}}".format(filename[0], filename[0]), | ||||
|                         format="tex", | ||||
|                     ) | ||||
|                 ] | ||||
| 
 | ||||
| 
 | ||||
| def include_code(elem, doc): | ||||
|  | @ -71,9 +76,8 @@ def include_code(elem, doc): | |||
|             filepath = elem.attributes.pop("include") | ||||
|             filename = os.path.split(filepath)[-1] | ||||
|             try: | ||||
|                 elem.text += elem.text + \ | ||||
|                     open(filepath, encoding="utf-8").read() | ||||
|                 elem.attributes['caption'] = filename | ||||
|                 elem.text += elem.text + open(filepath, encoding="utf-8").read() | ||||
|                 elem.attributes["caption"] = filename | ||||
|                 doc.inc_files.append(filename) | ||||
|             except Exception as e: | ||||
|                 elem.text += "Error: {}".format(e) | ||||
|  | @ -92,28 +96,26 @@ def jinja_py_filt(doc, file): | |||
|     env = {} | ||||
|     code = open(file, encoding="utf-8").read() | ||||
|     exec(code, env) | ||||
|     return env['main'](doc) | ||||
|     return env["main"](doc) | ||||
| 
 | ||||
| 
 | ||||
| def prepare(doc): | ||||
|     doc.inc_files = [] | ||||
|     doc.env = Environment() | ||||
|     doc.pyenv = {} | ||||
|     filters = {'py': partial(jinja_py_filt, doc)} | ||||
|     filters = {"py": partial(jinja_py_filt, doc)} | ||||
|     doc.env.filters.update(filters) | ||||
| 
 | ||||
| 
 | ||||
| def process_templates(elem, doc): | ||||
|     if type(elem) == CodeBlock: | ||||
|         if elem.classes == ["@"]: | ||||
|             args = {'meta': doc.get_metadata()} | ||||
|             args = {"meta": doc.get_metadata()} | ||||
|             return convert_text(doc.env.from_string(elem.text).render(args)) | ||||
| 
 | ||||
| 
 | ||||
| def yaml_filt(elem, doc): | ||||
|     tags = { | ||||
|         'eval': py_eval, | ||||
|     } | ||||
|     tags = {"eval": py_eval} | ||||
|     return yaml_filter(elem, doc, tags=tags, strict_yaml=True) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -138,8 +140,16 @@ def checkboxes(elem, doc): | |||
| 
 | ||||
| 
 | ||||
| def main(doc=None): | ||||
|     f = [process_templates, update_date, csv_table, include_code, | ||||
|          fix_color, code_refs, yaml_filt, checkboxes] | ||||
|     f = [ | ||||
|         process_templates, | ||||
|         update_date, | ||||
|         csv_table, | ||||
|         include_code, | ||||
|         fix_color, | ||||
|         code_refs, | ||||
|         yaml_filt, | ||||
|         checkboxes, | ||||
|     ] | ||||
|     return run_filters(f, prepare=prepare, doc=doc) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| import sys | ||||
| import pylab as PL | ||||
| import numpy as np | ||||
| from scipy.spatial.ckdtree import cKDTree | ||||
| import heapq | ||||
| import sys | ||||
| 
 | ||||
| import numpy as np | ||||
| import pylab as PL | ||||
| from scipy.spatial.ckdtree import cKDTree | ||||
| 
 | ||||
| exit() | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| from _ed_lrr import * | ||||
| from . import gui | ||||
| from .router import Router | ||||
| 
 | ||||
| from .preprocess import Preprocessor | ||||
| from .router import Router | ||||
|  |  | |||
|  | @ -1,562 +1,111 @@ | |||
| import sys | ||||
| import os | ||||
| import requests as RQ | ||||
| from datetime import datetime, timedelta | ||||
| from PyQt5.QtCore import QTimer, QThread, pyqtSignal, Qt, QObject | ||||
| from PyQt5.QtWidgets import ( | ||||
|     QMainWindow, | ||||
|     QApplication, | ||||
|     QFileDialog, | ||||
|     QProgressDialog, | ||||
|     QTreeWidgetItem, | ||||
|     QAction, | ||||
|     QMessageBox, | ||||
| ) | ||||
| from urllib.request import Request, urlopen | ||||
| import gzip | ||||
| import pathlib | ||||
| from PyQt5.QtGui import QPalette, QColor | ||||
| import ed_lrr_gui | ||||
| import ed_lrr_gui.config as cfg | ||||
| from ed_lrr_gui.gui.ed_lrr import Ui_ED_LRR | ||||
| from ed_lrr_gui import Router, Preprocessor | ||||
| import multiprocessing as MP | ||||
| import queue | ||||
| import csv | ||||
| import _ed_lrr | ||||
| import ctypes | ||||
| from math import floor | ||||
| import click | ||||
| from click_default_group import DefaultGroup | ||||
| import requests as RQ | ||||
| from ed_lrr_gui import Router | ||||
| from ed_lrr_gui import Preprocessor | ||||
| import ed_lrr_gui.gui as ED_LRR_GUI | ||||
| CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) | ||||
| 
 | ||||
| 
 | ||||
| def sizeof_fmt(num, suffix="B"): | ||||
|     for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: | ||||
|         if abs(num) < 1024.0: | ||||
|             return "{:.02f}{}{}".format(num, unit, suffix) | ||||
|         num /= 1024.0 | ||||
|     return "{:.02f}{}{}".format(num, "Yi", suffix) | ||||
| 
 | ||||
| 
 | ||||
| def t_round(dt): | ||||
|     return dt - dt % timedelta(seconds=1) | ||||
| 
 | ||||
| 
 | ||||
| class ProgressDialog(QProgressDialog): | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.setWindowModality(Qt.WindowModal) | ||||
| 
 | ||||
| 
 | ||||
| class Job(QObject): | ||||
|     progress = pyqtSignal("PyQt_PyObject") | ||||
| 
 | ||||
|     def __init__(self, app, cls, *args, build_progress=None, **kwargs): | ||||
|         super().__init__() | ||||
|         self.job = cls(*args, **kwargs) | ||||
|         self.timer = QTimer(app) | ||||
|         self.app = app | ||||
|         self.timer.timeout.connect(self.interval) | ||||
|         self.timer.start(100) | ||||
|         self.last_val = None | ||||
|         self.build_progress = build_progress | ||||
|         self.progress_dialog = None | ||||
|         self.state = {} | ||||
| 
 | ||||
|     def start(self): | ||||
|         """ | ||||
|         if self.diag_prog is None: | ||||
|             self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window) | ||||
|             if self.dl_thread: | ||||
|                 self.diag_prog.canceled.connect(self.dl_canceled) | ||||
|             self.diag_prog.show() | ||||
|         t_elapsed = datetime.today() - self.dl_started | ||||
|         rate = args["done"] / t_elapsed.total_seconds() | ||||
|         remaining = (args["size"] - args["done"]) / rate | ||||
|         rate = round(rate, 2) | ||||
|         # print(rate, remaining) | ||||
|         try: | ||||
|             t_rem = timedelta(seconds=remaining) | ||||
|         except OverflowError: | ||||
|             t_rem = "-" | ||||
|         msg = "Downloading {} [{}/{}] ({}/s)\n[{}/{}]".format( | ||||
|             filename, | ||||
|             sizeof_fmt(args["done"]), | ||||
|             sizeof_fmt(args["size"]), | ||||
|             sizeof_fmt(rate), | ||||
|             t_round(t_elapsed), | ||||
|             t_round(t_rem), | ||||
|         ) | ||||
|         self.diag_prog.setLabelText(msg) | ||||
|         self.diag_prog.setWindowTitle("Downloading EDSM Dumps") | ||||
|         self.diag_prog.setValue((args["done"] * 1000) // args["size"]) | ||||
|         """ | ||||
|         self.started = datetime.today() | ||||
|         if self.build_progress: | ||||
|             self.progress_dialog = ProgressDialog("", "Cancel", 0, 1000, self.app) | ||||
|             self.progress_dialog.canceled.connect(self.cancel) | ||||
|             self.progress_dialog.show() | ||||
|             self.progress.connect(self.__build_progress) | ||||
|         else: | ||||
|             self.progress.connect( | ||||
|                 lambda *args, **kwargs: print("PROGRESS:", *args, **kwargs) | ||||
|             ) | ||||
|         return self.job.start() | ||||
| 
 | ||||
|     def __build_progress(self, *args, **kwargs): | ||||
|         kwargs["self"] = self | ||||
|         return self.build_progress(*args, **kwargs) | ||||
| 
 | ||||
|     def cancel(self): | ||||
|         self.job.terminate() | ||||
|         self.job = None | ||||
| 
 | ||||
|     def done(self): | ||||
|         return (self.job.is_alive() == False) and (self.job.queue.empty()) | ||||
| 
 | ||||
|     def interval(self): | ||||
|         while True: | ||||
|             try: | ||||
|                 res = self.job.queue.get(True, 0.1) | ||||
|             except queue.Empty: | ||||
|                 return | ||||
|             if res == self.last_val: | ||||
|                 continue | ||||
|             self.state.update(res) | ||||
|             self.progress.emit(self.state) | ||||
|             self.last_val = res | ||||
| 
 | ||||
| 
 | ||||
| class DownloadThread(QThread): | ||||
|     progress = pyqtSignal("PyQt_PyObject") | ||||
| 
 | ||||
|     def __init__(self, systems_url, systems_file, bodies_url, bodies_file): | ||||
|         super().__init__() | ||||
|         self.systems_url = systems_url | ||||
|         self.systems_file = systems_file | ||||
|         self.bodies_url = bodies_url | ||||
|         self.bodies_file = bodies_file | ||||
|         self.running = True | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         self.wait() | ||||
| 
 | ||||
|     def stop(self): | ||||
|         self.running = False | ||||
| 
 | ||||
|     def run(self): | ||||
|         dl_jobs = [ | ||||
|             (self.systems_url, self.systems_file), | ||||
|             (self.bodies_url, self.bodies_file), | ||||
|         ] | ||||
|         for url, dest in dl_jobs: | ||||
|             outfile = url.split("/")[-1] | ||||
|             size = RQ.head(url, headers={"Accept-Encoding": "None"}) | ||||
|             size.raise_for_status() | ||||
|             size = int(size.headers.get("Content-Length", 0)) | ||||
|             with open(dest, "wb") as of: | ||||
|                 resp = RQ.get(url, stream=True) | ||||
|                 for chunk in resp.iter_content(1024 * 1024): | ||||
|                     of.write(chunk) | ||||
|                     self.progress.emit( | ||||
|                         {"done": of.tell(), "size": size, "outfile": outfile} | ||||
|                     ) | ||||
|                     if not self.running: | ||||
|                         return | ||||
| 
 | ||||
| 
 | ||||
| class App(QApplication): | ||||
|     def __init__(self): | ||||
|         super().__init__(sys.argv) | ||||
|         self.setStyle("Fusion") | ||||
|         self.setup_styles() | ||||
| 
 | ||||
|     def set_style(self, style): | ||||
|         print("LOAD:", style) | ||||
|         self.setPalette(self.styles[style]) | ||||
| 
 | ||||
|     def setup_styles(self): | ||||
|         self.styles = {} | ||||
|         styles = { | ||||
|             "Dark": { | ||||
|                 "Window": QColor(53, 53, 53), | ||||
|                 "WindowText": Qt.white, | ||||
|                 "Base": QColor(15, 15, 15), | ||||
|                 "AlternateBase": QColor(53, 53, 53), | ||||
|                 "ToolTipBase": Qt.white, | ||||
|                 "ToolTipText": Qt.white, | ||||
|                 "Text": Qt.white, | ||||
|                 "Button": QColor(53, 53, 53), | ||||
|                 "ButtonText": Qt.white, | ||||
|                 "BrightText": Qt.red, | ||||
|                 "Highlight": QColor(255, 128, 0), | ||||
|                 "HighlightedText": Qt.black, | ||||
|             } | ||||
|         } | ||||
|         for style, colors in styles.items(): | ||||
|             palette = QPalette() | ||||
|             for entry, color in colors.items(): | ||||
|                 palette.setColor(getattr(QPalette, entry), color) | ||||
|                 if color == Qt.darkGray: | ||||
|                     palette.setColor( | ||||
|                         QPalette.Disabled, getattr(QPalette, entry), QColor(53, 53, 53) | ||||
|                     ) | ||||
|                 else: | ||||
|                     palette.setColor( | ||||
|                         QPalette.Disabled, getattr(QPalette, entry), Qt.darkGray | ||||
|                     ) | ||||
|             self.styles[style] = palette | ||||
|         self.styles["Light"] = self.style().standardPalette() | ||||
| 
 | ||||
| 
 | ||||
| class ED_LRR(Ui_ED_LRR): | ||||
|     dl_thread = None | ||||
|     diag_prog = None | ||||
|     dl_started = None | ||||
|     system_found = pyqtSignal("PyQt_PyObject") | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.config = cfg.load() | ||||
|         self.jobs = {} | ||||
| 
 | ||||
|     def start_job(self, cls, *args, **kwargs): | ||||
|         print("START JOB:", cls, args, kwargs) | ||||
|         name = cls.__name__ | ||||
|         if name in self.jobs and self.jobs[name].done(): | ||||
|             del self.jobs[name] | ||||
|         if not name in self.jobs: | ||||
|             self.jobs[name] = Job(self.app, cls, *args, **kwargs) | ||||
|             self.jobs[name].start() | ||||
| 
 | ||||
|     def get_open_file(self, filetypes, callback=None): | ||||
|         fileName, _ = QFileDialog.getOpenFileName( | ||||
|             self.main_window, | ||||
|             "Open file", | ||||
|             str(cfg.data_dir), | ||||
|             filetypes, | ||||
|             options=QFileDialog.DontUseNativeDialog, | ||||
|         ) | ||||
|         if callback: | ||||
|             return callback(fileName) | ||||
|         return fileName | ||||
| 
 | ||||
|     def get_save_file(self, filetypes, callback=None): | ||||
|         fileName, _ = QFileDialog.getSaveFileName( | ||||
|             self.main_window, | ||||
|             "Save file", | ||||
|             str(cfg.data_dir), | ||||
|             filetypes, | ||||
|             options=QFileDialog.DontUseNativeDialog, | ||||
|         ) | ||||
|         if callback: | ||||
|             return callback(fileName) | ||||
|         return fileName | ||||
| 
 | ||||
|     def set_sys_lst(self, path): | ||||
|         if path not in self.config.history_out_path: | ||||
|             self.config.history_out_path.append(path) | ||||
|             self.inp_sys_lst.addItem(path) | ||||
|             self.inp_out_pp.addItem(path) | ||||
|         self.inp_sys_lst.setCurrentText(path) | ||||
|         self.inp_out_pp.setCurrentText(path) | ||||
| 
 | ||||
|     def set_bodies_file(self, path): | ||||
|         if path not in self.config.history_bodies_path: | ||||
|             self.config.history_bodies_path.append(path) | ||||
|             self.inp_bodies_pp.addItem(path) | ||||
| 
 | ||||
|     def set_systems_file(self, path): | ||||
|         if path not in self.config.history_systems_path: | ||||
|             self.config.history_systems_path.append(path) | ||||
|             self.inp_systems_pp.addItem(path) | ||||
| 
 | ||||
|     def update_dropdowns(self): | ||||
| @click.group(invoke_without_command=True,context_settings=CONTEXT_SETTINGS) | ||||
| @click.pass_context | ||||
| def main(ctx): | ||||
|     "Elite: Dangerous long range router, command line interface" | ||||
|     if ctx.invoked_subcommand is None: | ||||
|         ctx.invoke(gui) | ||||
|         return | ||||
|     return | ||||
| 
 | ||||
|     def log(self, *args): | ||||
|         t = datetime.today() | ||||
|         msg_t = "[{}] {}".format(t, str.format(*args)) | ||||
|         self.txt_log.append(msg_t) | ||||
| @main.command() | ||||
| @click.option("--debug",help="Debug print",is_flag=True) | ||||
| def gui(debug): | ||||
|     "Run the ED LRR GUI (default)" | ||||
|     if not debug: | ||||
|         ctypes.windll.kernel32.FreeConsole() | ||||
|         sys.stdin=open("NUL","rt") | ||||
|         sys.stdout=open("NUL","wt") | ||||
|         sys.stderr=open("NUL","wt") | ||||
|     sys.exit(ED_LRR_GUI.main()) | ||||
| 
 | ||||
|     def set_comp_mode(self, _): | ||||
|         if self.rd_comp.isChecked(): | ||||
|             comp_mode = "Compute Route" | ||||
|             self.btn_add.setText("Add") | ||||
|         if self.rd_precomp.isChecked(): | ||||
|             comp_mode = "Precompute Graph" | ||||
|             self.btn_add.setText("Select") | ||||
|         self.log("COMP_MODE", comp_mode) | ||||
|         self.lst_sys.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.btn_rm.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.cmb_mode.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.chk_permute.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.lbl_keep.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.lbl_mode.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.chk_permute_keep_first.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.chk_permute_keep_last.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.set_route_mode(self.rd_precomp.isChecked() or None) | ||||
| @main.command() | ||||
| @click.option("--url","-u",help="Base URL",default="https://www.edsm.net/dump/",show_default=True) | ||||
| @click.option("--systems","-s",help="Target path for systemsWithCoordinates.json",default="systemsWithCoordinates.json",show_default=True) | ||||
| @click.option("--bodies","-b",help="Target path for bodies.json",default="bodies.json",show_default=True) | ||||
| def download(*args,**kwargs): | ||||
|     "Download EDSM dumps" | ||||
|     print("Download:",args,kwargs) | ||||
|     click.pause() | ||||
| 
 | ||||
|     def set_route_mode(self, mode=None): | ||||
|         if mode == None: | ||||
|             mode = self.cmb_mode.currentText() | ||||
|         self.lbl_greedyness.setEnabled(mode == "A*-Search") | ||||
|         self.sld_greedyness.setEnabled(mode == "A*-Search") | ||||
| @main.command() | ||||
| def preprocess(*args,**kwargs): | ||||
|     "Preprocess EDSM dumps" | ||||
|     print("PreProcess:",ctx,args,kwargs) | ||||
|     click.pause() | ||||
| 
 | ||||
|     def set_greedyness(self, value): | ||||
|         self.lbl_greedyness.setText("Greedyness Factor ({:.0%})".format(value / 100)) | ||||
| 
 | ||||
|     @property | ||||
|     def systems(self): | ||||
|         ret = [] | ||||
|         for n in range(self.lst_sys.topLevelItemCount()): | ||||
|             ret.append(self.sys_to_dict(n)) | ||||
|         return ret | ||||
| 
 | ||||
|     def sys_to_dict(self, n): | ||||
|         header = [ | ||||
|             self.lst_sys.headerItem().data(c, 0) | ||||
|             for c in range(self.lst_sys.headerItem().columnCount()) | ||||
|         ] | ||||
|         system = [ | ||||
|             self.lst_sys.topLevelItem(n).data(c, 0) | ||||
|             for c in range(self.lst_sys.topLevelItem(n).columnCount()) | ||||
|         ] | ||||
|         ret = dict(zip(header, system)) | ||||
|         ret["id"] = getattr(self.lst_sys.topLevelItem(n), "__id__", None) | ||||
|         ret.pop(None, None) | ||||
|         return ret | ||||
| 
 | ||||
|     def error(self, msg): | ||||
|         QMessageBox.critical(self.main_window, "ERROR!", msg) | ||||
| 
 | ||||
|     def get_sys_list(self): | ||||
|         if not self.inp_sys_lst.currentText(): | ||||
|             self.error("System list is required!") | ||||
|             return | ||||
|         path = pathlib.Path(self.inp_sys_lst.currentText()) | ||||
|         if not path.exists(): | ||||
|             self.error("System list does not exist, run download and preprocess first!") | ||||
|             return | ||||
|         return path | ||||
| 
 | ||||
|     def run(self): | ||||
|         if not all(s["Type"] for s in self.systems): | ||||
|             self.error('Not all systens have been resolved, please click "Search All"') | ||||
|             return | ||||
|         print(self.systems) | ||||
|         systems = [str(s["id"]) for s in self.systems] | ||||
|         jump_range = self.sb_range.value() | ||||
|         mode = self.cmb_mode.currentText() | ||||
|         primary = self.chk_primary.isChecked() | ||||
|         keep_first = self.chk_permute_keep_first.isChecked() | ||||
|         keep_last = self.chk_permute_keep_last.isChecked() | ||||
|         permute = self.chk_permute.isChecked() | ||||
|         greedyness = ( | ||||
|             self.sld_greedyness.value() / 100 | ||||
|             if self.sld_greedyness.isEnabled() | ||||
|             else None | ||||
|         ) | ||||
|         path = self.get_sys_list() | ||||
|         if path is None: | ||||
|             return | ||||
|         precomp = path.with_suffix(".idx") | ||||
|         path = str(path) | ||||
|         if not precomp.exists(): | ||||
|             precomp = None | ||||
|         else: | ||||
|             precomp = str(precomp) | ||||
|         mode = { | ||||
|             "Breadth-First Search": "bfs", | ||||
|             "A*-Search": "astar", | ||||
|             "Greedy-Search": "greedy", | ||||
|         }[mode] | ||||
|         print( | ||||
|             systems, | ||||
|             jump_range, | ||||
|             mode, | ||||
|             primary, | ||||
|             permute, | ||||
|             (keep_first, keep_last), | ||||
|             greedyness, | ||||
|             path, | ||||
|             precomp, | ||||
|         ) | ||||
|         self.start_job( | ||||
|             Router, | ||||
|             systems, | ||||
|             jump_range, | ||||
|             0.1, | ||||
|             mode, | ||||
|             primary, | ||||
|             permute, | ||||
|             keep_first, | ||||
|             keep_last, | ||||
|             greedyness, | ||||
|             precomp, | ||||
|             path, | ||||
|         ) | ||||
| 
 | ||||
|     def find_sys_by_names(self, names): | ||||
|         t_s = datetime.today() | ||||
|         if not self.get_sys_list(): | ||||
|             return None | ||||
|         ret = _ed_lrr.find_sys(names, self.inp_sys_lst.currentText()) | ||||
|         print("Took:", datetime.today() - t_s) | ||||
|         return ret | ||||
| 
 | ||||
|     def resolve_systems(self): | ||||
|         names = [] | ||||
|         for n in range(self.lst_sys.topLevelItemCount()): | ||||
|             names.append(self.sys_to_dict(n)["Name"]) | ||||
|         systems = self.find_sys_by_names(names) | ||||
|         if systems is None: | ||||
|             return | ||||
|         for i, name in enumerate(names): | ||||
|             _, system = systems[name] | ||||
|             self.lst_sys.topLevelItem(i).setData(0, 0, system["system"]) | ||||
|             self.lst_sys.topLevelItem(i).setData(1, 0, system["star_type"]) | ||||
|             self.lst_sys.topLevelItem(i).__id__ = system["id"] | ||||
|         # diff, item = self.find_sys_by_name(name) | ||||
|         # print("Found", (diff, item)) | ||||
| 
 | ||||
|     def add_system(self): | ||||
|         name = self.inp_sys.text() | ||||
|         item = QTreeWidgetItem(self.lst_sys, [name, None]) | ||||
|         item.resolved = False | ||||
|         item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled) | ||||
| 
 | ||||
|     def remove_system(self): | ||||
|         root = self.lst_sys.invisibleRootItem() | ||||
|         for item in self.lst_sys.selectedItems(): | ||||
|             root.removeChild(item) | ||||
| 
 | ||||
|     def dl_canceled(self): | ||||
|         if self.dl_thread: | ||||
|             print("Cancel!") | ||||
| @main.command() | ||||
| @click.option("--path","-i",required=True,metavar="<path>",help="Path to stars.csv",default="./stars.csv",type=click.Path(exists=True,dir_okay=False),show_default=True ) | ||||
| @click.option("--precomp_file","-pf",metavar="<path>",help="Precomputed routing graph to use",type=click.Path(exists=True,dir_okay=False)) | ||||
| @click.option("--range","-r",required=True,metavar="<float>",help="Jump range (Ly)",type=click.FloatRange(min=0)) | ||||
| @click.option("--prune","-d",default=(0,0),metavar="<n> <m>",help="Prune search branches",nargs=2,type=click.Tuple([click.IntRange(min=0),click.FloatRange(min=0)])) | ||||
| @click.option("--permute","-p",type=click.Choice(["all","keep_first","keep_last","keep_both"]),default=None,help="Permute hops to find shortest route",show_default=True) | ||||
| @click.option("--primary","-ps",is_flag=True,default=False,help="Only route through primary stars") | ||||
| @click.option("--factor","-g",metavar="<float>",default=0.5,help="Greedyness factor for A-Star",show_default=True) | ||||
| @click.option("--mode","-m",default="bfs",help="Search mode",type=click.Choice(["bfs","a-star","greedy"]),show_default=True) | ||||
| @click.argument('systems',nargs=-1) | ||||
| def route(**kwargs): | ||||
|     "Compute a route" | ||||
|     if kwargs['prune']==(0,0): | ||||
|         kwargs['prune']=None | ||||
|     def to_string(state): | ||||
|         if state: | ||||
|             return "[{}] {}".format(state['depth'],state['system']) | ||||
|     keep_first,keep_last={ | ||||
|         "all":(False,False), | ||||
|         "keep_first":(True,False), | ||||
|         "keep_last":(False,True), | ||||
|         "keep_both":(True,True), | ||||
|         None: (False,False) | ||||
|     }[kwargs['permute']] | ||||
|     args=[kwargs['systems'],kwargs['range'],kwargs['prune'],kwargs['mode'],kwargs['primary'],kwargs['permute']!=None,keep_first,keep_last,kwargs['factor'],None,kwargs['path']] | ||||
|     with click.progressbar(length=100,label="Computing route",show_percent=True,item_show_func=to_string,width=50) as pbar: | ||||
|         router=Router(*args) | ||||
|         router.start() | ||||
|         state={} | ||||
|         pstate={} | ||||
|         while not (router.queue.empty() and router.is_alive()==False): | ||||
|             try: | ||||
|                 self.dl_thread.progress.disconnect() | ||||
|             except TypeError: | ||||
|                 event = router.queue.get(True,0.1) | ||||
|                 state.update(event) | ||||
|                 if state!=pstate: | ||||
|                     pbar.current_item=state.get("status") | ||||
|                     if pbar.current_item: | ||||
|                         pbar.pos=floor(pbar.current_item["prc_done"]*10)/10 | ||||
|                         pbar.update(0) | ||||
|                     pstate=state | ||||
|             except queue.Empty: | ||||
|                 pass | ||||
|             self.dl_thread.stop() | ||||
|             self.dl_thread.wait() | ||||
|             self.diag_prog.close() | ||||
|             self.dl_thread = None | ||||
|             self.diag_prog = None | ||||
|             self.dl_started = None | ||||
|         pbar.pos=100 | ||||
|         pbar.update(0) | ||||
|     print(state.get("result")) | ||||
|     print("DONE!") | ||||
| 
 | ||||
|     def handle_dl_progress(self, args): | ||||
|         filename = os.path.split(args["outfile"])[-1] | ||||
|         if self.diag_prog is None: | ||||
|             self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window) | ||||
|             if self.dl_thread: | ||||
|                 self.diag_prog.canceled.connect(self.dl_canceled) | ||||
|             self.diag_prog.show() | ||||
|         t_elapsed = datetime.today() - self.dl_started | ||||
|         rate = args["done"] / t_elapsed.total_seconds() | ||||
|         remaining = (args["size"] - args["done"]) / rate | ||||
|         rate = round(rate, 2) | ||||
|         # print(rate, remaining) | ||||
|         try: | ||||
|             t_rem = timedelta(seconds=remaining) | ||||
|         except OverflowError: | ||||
|             t_rem = "-" | ||||
|         msg = "Downloading {} [{}/{}] ({}/s)\n[{}/{}]".format( | ||||
|             filename, | ||||
|             sizeof_fmt(args["done"]), | ||||
|             sizeof_fmt(args["size"]), | ||||
|             sizeof_fmt(rate), | ||||
|             t_round(t_elapsed), | ||||
|             t_round(t_rem), | ||||
|         ) | ||||
|         self.diag_prog.setLabelText(msg) | ||||
|         self.diag_prog.setWindowTitle("Downloading EDSM Dumps") | ||||
|         self.diag_prog.setValue((args["done"] * 1000) // args["size"]) | ||||
| 
 | ||||
|     def run_download(self): | ||||
|         if self.dl_thread: | ||||
|             return | ||||
|         self.dl_started = datetime.today() | ||||
|         self.dl_thread = DownloadThread( | ||||
|             self.inp_systems_dl.currentText(), | ||||
|             self.inp_systems_dest_dl.currentText(), | ||||
|             self.inp_bodies_dl.currentText(), | ||||
|             self.inp_bodies_dest_dl.currentText(), | ||||
|         ) | ||||
|         self.dl_thread.progress.connect(self.handle_dl_progress) | ||||
|         self.dl_thread.start() | ||||
|         print(".") | ||||
| 
 | ||||
|     def update_permute_chk(self, state): | ||||
|         self.chk_permute_keep_first.setEnabled(state) | ||||
|         self.chk_permute_keep_last.setEnabled(state) | ||||
|         self.lbl_keep.setEnabled(state) | ||||
| 
 | ||||
|     def setup_signals(self): | ||||
|         self.btn_download.clicked.connect(self.run_download) | ||||
|         self.inp_systems_dest_dl.setCurrentText(r"D:\devel\rust\ed_lrr_gui\DL\s.json") | ||||
|         self.inp_bodies_dest_dl.setCurrentText(r"D:\devel\rust\ed_lrr_gui\DL\b.json") | ||||
|         self.set_greedyness(self.sld_greedyness.value()) | ||||
|         self.cmb_mode.currentTextChanged.connect(self.set_route_mode) | ||||
|         self.rd_comp.toggled.connect(self.set_comp_mode) | ||||
|         self.rd_precomp.toggled.connect(self.set_comp_mode) | ||||
|         self.sld_greedyness.valueChanged.connect(self.set_greedyness) | ||||
|         self.btn_go.clicked.connect(self.run) | ||||
|         self.btn_add.clicked.connect(self.add_system) | ||||
|         self.btn_rm.clicked.connect(self.remove_system) | ||||
|         self.chk_permute.stateChanged.connect(self.update_permute_chk) | ||||
|         self.btn_search.clicked.connect(self.resolve_systems) | ||||
|         self.btn_out_browse_pp.clicked.connect( | ||||
|             lambda: self.get_save_file("CSV File (*.csv)", self.set_sys_lst) | ||||
|         ) | ||||
|         self.btn_sys_lst_browse.clicked.connect( | ||||
|             lambda: self.get_open_file("CSV File (*.csv)", self.set_sys_lst) | ||||
|         ) | ||||
| 
 | ||||
|         self.btn_bodies_browse_pp.clicked.connect( | ||||
|             lambda: self.get_open_file("JSON File (*.json)", self.set_bodies_file) | ||||
|         ) | ||||
|         self.btn_bodies_dest_browse_dl.clicked.connect( | ||||
|             lambda: self.get_save_file("JSON File (*.json)", self.set_bodies_file) | ||||
|         ) | ||||
|         self.btn_systems_browse_pp.clicked.connect( | ||||
|             lambda: self.get_open_file("JSON File (*.json)", self.set_systems_file) | ||||
|         ) | ||||
|         self.btn_systems_dest_browse_dl.clicked.connect( | ||||
|             lambda: self.get_save_file("JSON File (*.json)", self.set_systems_file) | ||||
|         ) | ||||
| 
 | ||||
|     def handle_close(self): | ||||
|         cfg.write(self.config) | ||||
|         print("BYEEEEEE!") | ||||
| 
 | ||||
|     def setup_styles(self, win, app): | ||||
|         for name in app.styles: | ||||
|             action = QAction(app) | ||||
|             action.setObjectName("action_load_style_" + name) | ||||
|             action.setText(name) | ||||
|             action.triggered.connect(lambda _, name=name: app.set_style(name)) | ||||
|             self.menuStyle.addAction(action) | ||||
| 
 | ||||
|     def setupUi(self, MainWindow, app): | ||||
|         super().setupUi(MainWindow) | ||||
|         self.update_dropdowns() | ||||
|         self.main_window = MainWindow | ||||
|         self.app = app | ||||
|         self.setup_signals() | ||||
|         self.lst_sys.setHeaderLabels(["Name", "Type"]) | ||||
|         self.set_route_mode() | ||||
|         self.update_permute_chk(self.chk_permute.isChecked()) | ||||
|         self.setup_styles(MainWindow, app) | ||||
| @main.command() | ||||
| @click.option("--path","-i",required=True,help="Path to stars.csv",default="./stars.csv",type=click.Path(exists=True,dir_okay=False),show_default=True ) | ||||
| @click.option("--precomp_file","-pc",help="Precomputed routing graph to use",type=click.Path(exists=True,dir_okay=False)) | ||||
| @click.option("--range","-r",required=True,help="Jump range (Ly)",type=click.FloatRange(min=0)) | ||||
| @click.option("--primary","-ps",help="Only route through primary stars") | ||||
| @click.option("--output","-o",required=True,help="Output path",default="./stars.idx",type=click.Path(exists=False,dir_okay=False),show_default=True ) | ||||
| @click.argument('systems',nargs=-1) | ||||
| def precompute(*args,**kwargs): | ||||
|     "Precompute routing graph" | ||||
|     print("PreComp:",ctx,args,kwargs) | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     app = App() | ||||
|     MainWindow = QMainWindow() | ||||
|     ui = ED_LRR() | ||||
|     ui.setupUi(MainWindow, app) | ||||
|     MainWindow.show() | ||||
|     ret = app.exec_() | ||||
|     ui.handle_close() | ||||
|     exit(ret) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
| if __name__ == '__main__': | ||||
|     MP.freeze_support() | ||||
|     main() | ||||
|     main() | ||||
|  | @ -1,7 +1,8 @@ | |||
| import pathlib | ||||
| from collections import namedtuple | ||||
| 
 | ||||
| import appdirs | ||||
| import yaml | ||||
| from collections import namedtuple | ||||
| 
 | ||||
| config_dir = pathlib.Path(appdirs.user_config_dir("ED_LRR")) | ||||
| config_dir.mkdir(parents=True, exist_ok=True) | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| from .main import main | ||||
|  | @ -2,7 +2,7 @@ | |||
| 
 | ||||
| # Form implementation generated from reading ui file 'D:\devel\rust\ed_lrr_gui\ed_lrr_gui\gui\ed_lrr.ui' | ||||
| # | ||||
| # Created by: PyQt5 UI code generator 5.13.0 | ||||
| # Created by: PyQt5 UI code generator 5.13.1 | ||||
| # | ||||
| # WARNING! All changes made in this file will be lost! | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										546
									
								
								ed_lrr_gui/gui/main.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										546
									
								
								ed_lrr_gui/gui/main.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,546 @@ | |||
| import csv | ||||
| import gzip | ||||
| import multiprocessing as MP | ||||
| import os | ||||
| import pathlib | ||||
| import queue | ||||
| import sys | ||||
| from sys import exit | ||||
| from datetime import datetime, timedelta | ||||
| from urllib.request import Request, urlopen | ||||
| 
 | ||||
| import _ed_lrr | ||||
| import ed_lrr_gui | ||||
| import ed_lrr_gui.config as cfg | ||||
| import requests as RQ | ||||
| from ed_lrr_gui import Preprocessor, Router | ||||
| from ed_lrr_gui.gui.ed_lrr import Ui_ED_LRR | ||||
| from PyQt5.QtCore import QObject, Qt, QThread, QTimer, pyqtSignal | ||||
| from PyQt5.QtGui import QColor, QPalette,QIcon | ||||
| from PyQt5.QtWidgets import ( | ||||
|     QAction, | ||||
|     QApplication, | ||||
|     QFileDialog, | ||||
|     QMainWindow, | ||||
|     QMessageBox, | ||||
|     QProgressDialog, | ||||
|     QTreeWidgetItem, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| def sizeof_fmt(num, suffix="B"): | ||||
|     for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: | ||||
|         if abs(num) < 1024.0: | ||||
|             return "{:.02f}{}{}".format(num, unit, suffix) | ||||
|         num /= 1024.0 | ||||
|     return "{:.02f}{}{}".format(num, "Yi", suffix) | ||||
| 
 | ||||
| 
 | ||||
| def t_round(dt): | ||||
|     return dt - dt % timedelta(seconds=1) | ||||
| 
 | ||||
| 
 | ||||
| class ProgressDialog(QProgressDialog): | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.setWindowModality(Qt.WindowModal) | ||||
| 
 | ||||
| 
 | ||||
| class Job(QObject): | ||||
|     progress = pyqtSignal("PyQt_PyObject") | ||||
| 
 | ||||
|     def __init__(self, app, main_window, cls, *args, **kwargs): | ||||
|         super().__init__() | ||||
|         self.job = cls(*args, **kwargs) | ||||
|         self.timer = QTimer(app) | ||||
|         self.app = app | ||||
|         self.main_window = main_window | ||||
|         self.timer.timeout.connect(self.interval) | ||||
|         self.timer.start(100) | ||||
|         self.last_val = None | ||||
|         self.progress_dialog = None | ||||
|         self.handle_progess = None | ||||
|         self.state = {} | ||||
| 
 | ||||
|     def setup_progress(self, handle_progess): | ||||
|         self.progress.connect( | ||||
|             lambda *args, **kwargs: handle_progess(self, *args, **kwargs) | ||||
|         ) | ||||
| 
 | ||||
|     def start(self): | ||||
|         if self.progress_dialog is None: | ||||
|             self.progress.connect( | ||||
|                 lambda *args, **kwargs: print("PROGRESS:", *args, **kwargs) | ||||
|             ) | ||||
|         self.started = datetime.today() | ||||
|         return self.job.start() | ||||
| 
 | ||||
|     def cancel(self): | ||||
|         self.job.terminate() | ||||
|         self.job = None | ||||
| 
 | ||||
|     def done(self): | ||||
|         return (self.job.is_alive() == False) and (self.job.queue.empty()) | ||||
| 
 | ||||
|     def interval(self): | ||||
|         while True: | ||||
|             try: | ||||
|                 res = self.job.queue.get(True, 0.1) | ||||
|             except queue.Empty: | ||||
|                 return | ||||
|             if res == self.last_val: | ||||
|                 continue | ||||
|             self.state.update(res) | ||||
|             self.progress.emit(self.state) | ||||
|             self.last_val = res | ||||
| 
 | ||||
| 
 | ||||
| class DownloadThread(QThread): | ||||
|     progress = pyqtSignal("PyQt_PyObject") | ||||
| 
 | ||||
|     def __init__(self, systems_url, systems_file, bodies_url, bodies_file): | ||||
|         super().__init__() | ||||
|         self.systems_url = systems_url | ||||
|         self.systems_file = systems_file | ||||
|         self.bodies_url = bodies_url | ||||
|         self.bodies_file = bodies_file | ||||
|         self.running = True | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         self.wait() | ||||
| 
 | ||||
|     def stop(self): | ||||
|         self.running = False | ||||
| 
 | ||||
|     def run(self): | ||||
|         dl_jobs = [ | ||||
|             (self.systems_url, self.systems_file), | ||||
|             (self.bodies_url, self.bodies_file), | ||||
|         ] | ||||
|         for url, dest in dl_jobs: | ||||
|             outfile = url.split("/")[-1] | ||||
|             size = RQ.head(url, headers={"Accept-Encoding": "None"}) | ||||
|             size.raise_for_status() | ||||
|             size = int(size.headers.get("Content-Length", 0)) | ||||
|             with open(dest, "wb") as of: | ||||
|                 resp = RQ.get(url, stream=True) | ||||
|                 for chunk in resp.iter_content(1024 * 1024): | ||||
|                     of.write(chunk) | ||||
|                     self.progress.emit( | ||||
|                         {"done": of.tell(), "size": size, "outfile": outfile} | ||||
|                     ) | ||||
|                     if not self.running: | ||||
|                         return | ||||
| 
 | ||||
| 
 | ||||
| class App(QApplication): | ||||
|     def __init__(self): | ||||
|         super().__init__(sys.argv) | ||||
|         self.setStyle("Fusion") | ||||
|         self.setup_styles() | ||||
| 
 | ||||
|     def set_style(self, style): | ||||
|         print("LOAD:", style) | ||||
|         self.setPalette(self.styles[style]) | ||||
| 
 | ||||
|     def setup_styles(self): | ||||
|         self.styles = {} | ||||
|         styles = { | ||||
|             "Dark": { | ||||
|                 "Window": QColor(53, 53, 53), | ||||
|                 "WindowText": Qt.white, | ||||
|                 "Base": QColor(15, 15, 15), | ||||
|                 "AlternateBase": QColor(53, 53, 53), | ||||
|                 "ToolTipBase": Qt.white, | ||||
|                 "ToolTipText": Qt.white, | ||||
|                 "Text": Qt.white, | ||||
|                 "Button": QColor(53, 53, 53), | ||||
|                 "ButtonText": Qt.white, | ||||
|                 "BrightText": Qt.red, | ||||
|                 "Highlight": QColor(255, 128, 0), | ||||
|                 "HighlightedText": Qt.black, | ||||
|             } | ||||
|         } | ||||
|         for style, colors in styles.items(): | ||||
|             palette = QPalette() | ||||
|             for entry, color in colors.items(): | ||||
|                 palette.setColor(getattr(QPalette, entry), color) | ||||
|                 if color == Qt.darkGray: | ||||
|                     palette.setColor( | ||||
|                         QPalette.Disabled, getattr(QPalette, entry), QColor(53, 53, 53) | ||||
|                     ) | ||||
|                 else: | ||||
|                     palette.setColor( | ||||
|                         QPalette.Disabled, getattr(QPalette, entry), Qt.darkGray | ||||
|                     ) | ||||
|             self.styles[style] = palette | ||||
|         self.styles["Light"] = self.style().standardPalette() | ||||
| 
 | ||||
| 
 | ||||
| class ED_LRR(Ui_ED_LRR): | ||||
|     dl_thread = None | ||||
|     diag_prog = None | ||||
|     dl_started = None | ||||
|     system_found = pyqtSignal("PyQt_PyObject") | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.config = cfg.load() | ||||
|         self.jobs = {} | ||||
| 
 | ||||
|     def new_job(self, cls, *args, **kwargs): | ||||
|         print("CREATE JOB:", cls, args, kwargs) | ||||
|         name = cls.__name__ | ||||
|         if name in self.jobs and self.jobs[name].done(): | ||||
|             del self.jobs[name] | ||||
|         if not name in self.jobs: | ||||
|             self.jobs[name] = Job(self.app, self.main_window, cls, *args, **kwargs) | ||||
|             return self.jobs[name] | ||||
| 
 | ||||
|     def get_open_file(self, filetypes, callback=None): | ||||
|         fileName, _ = QFileDialog.getOpenFileName( | ||||
|             self.main_window, | ||||
|             "Open file", | ||||
|             str(cfg.data_dir), | ||||
|             filetypes, | ||||
|             options=QFileDialog.DontUseNativeDialog, | ||||
|         ) | ||||
|         if callback: | ||||
|             return callback(fileName) | ||||
|         return fileName | ||||
| 
 | ||||
|     def get_save_file(self, filetypes, callback=None): | ||||
|         fileName, _ = QFileDialog.getSaveFileName( | ||||
|             self.main_window, | ||||
|             "Save file", | ||||
|             str(cfg.data_dir), | ||||
|             filetypes, | ||||
|             options=QFileDialog.DontUseNativeDialog, | ||||
|         ) | ||||
|         if callback: | ||||
|             return callback(fileName) | ||||
|         return fileName | ||||
| 
 | ||||
|     def set_sys_lst(self, path): | ||||
|         if path not in self.config.history_out_path: | ||||
|             self.config.history_out_path.append(path) | ||||
|             self.inp_sys_lst.addItem(path) | ||||
|             self.inp_out_pp.addItem(path) | ||||
|         self.inp_sys_lst.setCurrentText(path) | ||||
|         self.inp_out_pp.setCurrentText(path) | ||||
| 
 | ||||
|     def set_bodies_file(self, path): | ||||
|         if path not in self.config.history_bodies_path: | ||||
|             self.config.history_bodies_path.append(path) | ||||
|             self.inp_bodies_pp.addItem(path) | ||||
| 
 | ||||
|     def set_systems_file(self, path): | ||||
|         if path not in self.config.history_systems_path: | ||||
|             self.config.history_systems_path.append(path) | ||||
|             self.inp_systems_pp.addItem(path) | ||||
| 
 | ||||
|     def update_dropdowns(self): | ||||
|         return | ||||
| 
 | ||||
|     def log(self, *args): | ||||
|         t = datetime.today() | ||||
|         msg_t = "[{}] {}".format(t, str.format(*args)) | ||||
|         self.txt_log.append(msg_t) | ||||
| 
 | ||||
|     def set_comp_mode(self, _): | ||||
|         if self.rd_comp.isChecked(): | ||||
|             comp_mode = "Compute Route" | ||||
|             self.btn_add.setText("Add") | ||||
|         if self.rd_precomp.isChecked(): | ||||
|             comp_mode = "Precompute Graph" | ||||
|             self.btn_add.setText("Select") | ||||
|         self.log("COMP_MODE", comp_mode) | ||||
|         self.lst_sys.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.btn_rm.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.cmb_mode.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.chk_permute.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.lbl_keep.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.lbl_mode.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.chk_permute_keep_first.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.chk_permute_keep_last.setEnabled(self.rd_comp.isChecked()) | ||||
|         self.set_route_mode(self.rd_precomp.isChecked() or None) | ||||
| 
 | ||||
|     def set_route_mode(self, mode=None): | ||||
|         if mode == None: | ||||
|             mode = self.cmb_mode.currentText() | ||||
|         self.lbl_greedyness.setEnabled(mode == "A*-Search") | ||||
|         self.sld_greedyness.setEnabled(mode == "A*-Search") | ||||
| 
 | ||||
|     def set_greedyness(self, value): | ||||
|         self.lbl_greedyness.setText("Greedyness Factor ({:.0%})".format(value / 100)) | ||||
| 
 | ||||
|     @property | ||||
|     def systems(self): | ||||
|         ret = [] | ||||
|         for n in range(self.lst_sys.topLevelItemCount()): | ||||
|             ret.append(self.sys_to_dict(n)) | ||||
|         return ret | ||||
| 
 | ||||
|     def sys_to_dict(self, n): | ||||
|         header = [ | ||||
|             self.lst_sys.headerItem().data(c, 0) | ||||
|             for c in range(self.lst_sys.headerItem().columnCount()) | ||||
|         ] | ||||
|         system = [ | ||||
|             self.lst_sys.topLevelItem(n).data(c, 0) | ||||
|             for c in range(self.lst_sys.topLevelItem(n).columnCount()) | ||||
|         ] | ||||
|         ret = dict(zip(header, system)) | ||||
|         ret["id"] = getattr(self.lst_sys.topLevelItem(n), "__id__", None) | ||||
|         ret.pop(None, None) | ||||
|         return ret | ||||
| 
 | ||||
|     def error(self, msg): | ||||
|         QMessageBox.critical(self.main_window, "ERROR!", msg) | ||||
| 
 | ||||
|     def get_sys_list(self): | ||||
|         if not self.inp_sys_lst.currentText(): | ||||
|             self.error("System list is required!") | ||||
|             return | ||||
|         path = pathlib.Path(self.inp_sys_lst.currentText()) | ||||
|         if not path.exists(): | ||||
|             self.error("System list does not exist, run download and preprocess first!") | ||||
|             return | ||||
|         return path | ||||
| 
 | ||||
|     def route_progress(self, job, state): | ||||
|         print("RP:", job, state) | ||||
| 
 | ||||
|     def run(self): | ||||
|         if not all(s["Type"] for s in self.systems): | ||||
|             self.error('Not all systens have been resolved, please click "Search All"') | ||||
|             return | ||||
|         print(self.systems) | ||||
|         systems = [str(s["id"]) for s in self.systems] | ||||
|         jump_range = self.sb_range.value() | ||||
|         mode = self.cmb_mode.currentText() | ||||
|         primary = self.chk_primary.isChecked() | ||||
|         keep_first = self.chk_permute_keep_first.isChecked() | ||||
|         keep_last = self.chk_permute_keep_last.isChecked() | ||||
|         permute = self.chk_permute.isChecked() | ||||
|         greedyness = ( | ||||
|             self.sld_greedyness.value() / 100 | ||||
|             if self.sld_greedyness.isEnabled() | ||||
|             else None | ||||
|         ) | ||||
|         path = self.get_sys_list() | ||||
|         if path is None: | ||||
|             return | ||||
|         precomp = None | ||||
|         path = str(path) | ||||
|         mode = { | ||||
|             "Breadth-First Search": "bfs", | ||||
|             "A*-Search": "astar", | ||||
|             "Greedy-Search": "greedy", | ||||
|         }[mode] | ||||
|         print( | ||||
|             systems, | ||||
|             jump_range, | ||||
|             mode, | ||||
|             primary, | ||||
|             permute, | ||||
|             (keep_first, keep_last), | ||||
|             greedyness, | ||||
|             path, | ||||
|             precomp, | ||||
|         ) | ||||
|         route_job = self.new_job( | ||||
|             Router, | ||||
|             systems, | ||||
|             jump_range, | ||||
|             0.1, | ||||
|             mode, | ||||
|             primary, | ||||
|             permute, | ||||
|             keep_first, | ||||
|             keep_last, | ||||
|             greedyness, | ||||
|             precomp, | ||||
|             path, | ||||
|         ) | ||||
|         if route_job: | ||||
|             self.route_progress_dialog = ProgressDialog( | ||||
|                 "Computing route...", "Cancel", 0, 100, self.main_window | ||||
|             ) | ||||
|             self.route_progress_dialog.canceled.connect(route_job.cancel) | ||||
|             route_job.start() | ||||
|             self.route_progress_dialog.show() | ||||
|         else: | ||||
|             self.error("Another route job is already running!") | ||||
| 
 | ||||
|     def find_sys_by_names(self, names): | ||||
|         t_s = datetime.today() | ||||
|         if not self.get_sys_list(): | ||||
|             return None | ||||
|         # TODO: start thread/subprocess | ||||
|         ret = _ed_lrr.find_sys(names, self.inp_sys_lst.currentText()) | ||||
|         print("Took:", datetime.today() - t_s) | ||||
|         return ret | ||||
| 
 | ||||
|     def resolve_systems(self): | ||||
|         # TODO: show spinner | ||||
|         names = [] | ||||
|         for n in range(self.lst_sys.topLevelItemCount()): | ||||
|             names.append(self.sys_to_dict(n)["Name"]) | ||||
|         systems = self.find_sys_by_names(names) | ||||
|         if systems is None: | ||||
|             return | ||||
|         for i, name in enumerate(names): | ||||
|             _, system = systems[name] | ||||
|             self.lst_sys.topLevelItem(i).setData(0, 0, system["system"]) | ||||
|             self.lst_sys.topLevelItem(i).setData(1, 0, system["star_type"]) | ||||
|             self.lst_sys.topLevelItem(i).__id__ = system["id"] | ||||
|         # diff, item = self.find_sys_by_name(name) | ||||
|         # print("Found", (diff, item)) | ||||
| 
 | ||||
|     def add_system(self): | ||||
|         name = self.inp_sys.text() | ||||
|         item = QTreeWidgetItem(self.lst_sys, [name, None]) | ||||
|         item.resolved = False | ||||
|         item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled) | ||||
| 
 | ||||
|     def remove_system(self): | ||||
|         root = self.lst_sys.invisibleRootItem() | ||||
|         for item in self.lst_sys.selectedItems(): | ||||
|             root.removeChild(item) | ||||
| 
 | ||||
|     def dl_canceled(self): | ||||
|         if self.dl_thread: | ||||
|             print("Cancel!") | ||||
|             try: | ||||
|                 self.dl_thread.progress.disconnect() | ||||
|             except TypeError: | ||||
|                 pass | ||||
|             self.dl_thread.stop() | ||||
|             self.dl_thread.wait() | ||||
|             self.diag_prog.close() | ||||
|             self.dl_thread = None | ||||
|             self.diag_prog = None | ||||
|             self.dl_started = None | ||||
| 
 | ||||
|     def handle_dl_progress(self, args): | ||||
|         filename = os.path.split(args["outfile"])[-1] | ||||
|         if self.diag_prog is None: | ||||
|             self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window) | ||||
|             if self.dl_thread: | ||||
|                 self.diag_prog.canceled.connect(self.dl_canceled) | ||||
|             self.diag_prog.show() | ||||
|         t_elapsed = datetime.today() - self.dl_started | ||||
|         rate = args["done"] / t_elapsed.total_seconds() | ||||
|         remaining = (args["size"] - args["done"]) / rate | ||||
|         rate = round(rate, 2) | ||||
|         # print(rate, remaining) | ||||
|         try: | ||||
|             t_rem = timedelta(seconds=remaining) | ||||
|         except OverflowError: | ||||
|             t_rem = "-" | ||||
|         msg = "Downloading {} [{}/{}] ({}/s)\n[{}/{}]".format( | ||||
|             filename, | ||||
|             sizeof_fmt(args["done"]), | ||||
|             sizeof_fmt(args["size"]), | ||||
|             sizeof_fmt(rate), | ||||
|             t_round(t_elapsed), | ||||
|             t_round(t_rem), | ||||
|         ) | ||||
|         self.diag_prog.setLabelText(msg) | ||||
|         self.diag_prog.setWindowTitle("Downloading EDSM Dumps") | ||||
|         self.diag_prog.setValue((args["done"] * 1000) // args["size"]) | ||||
| 
 | ||||
|     def run_download(self): | ||||
|         if self.dl_thread: | ||||
|             return | ||||
|         self.dl_started = datetime.today() | ||||
|         self.dl_thread = DownloadThread( | ||||
|             self.inp_systems_dl.currentText(), | ||||
|             self.inp_systems_dest_dl.currentText(), | ||||
|             self.inp_bodies_dl.currentText(), | ||||
|             self.inp_bodies_dest_dl.currentText(), | ||||
|         ) | ||||
|         self.dl_thread.progress.connect(self.handle_dl_progress) | ||||
|         self.dl_thread.start() | ||||
|         print(".") | ||||
| 
 | ||||
|     def update_permute_chk(self, state): | ||||
|         self.chk_permute_keep_first.setEnabled(state) | ||||
|         self.chk_permute_keep_last.setEnabled(state) | ||||
|         self.lbl_keep.setEnabled(state) | ||||
| 
 | ||||
|     def setup_signals(self): | ||||
|         self.btn_download.clicked.connect(self.run_download) | ||||
|         self.inp_systems_dest_dl.setCurrentText(r"D:\devel\rust\ed_lrr_gui\DL\s.json") | ||||
|         self.inp_bodies_dest_dl.setCurrentText(r"D:\devel\rust\ed_lrr_gui\DL\b.json") | ||||
|         self.set_greedyness(self.sld_greedyness.value()) | ||||
|         self.cmb_mode.currentTextChanged.connect(self.set_route_mode) | ||||
|         self.rd_comp.toggled.connect(self.set_comp_mode) | ||||
|         self.rd_precomp.toggled.connect(self.set_comp_mode) | ||||
|         self.sld_greedyness.valueChanged.connect(self.set_greedyness) | ||||
|         self.btn_go.clicked.connect(self.run) | ||||
|         self.btn_add.clicked.connect(self.add_system) | ||||
|         self.btn_rm.clicked.connect(self.remove_system) | ||||
|         self.chk_permute.stateChanged.connect(self.update_permute_chk) | ||||
|         self.btn_search.clicked.connect(self.resolve_systems) | ||||
|         self.btn_out_browse_pp.clicked.connect( | ||||
|             lambda: self.get_save_file("CSV File (*.csv)", self.set_sys_lst) | ||||
|         ) | ||||
|         self.btn_sys_lst_browse.clicked.connect( | ||||
|             lambda: self.get_open_file("CSV File (*.csv)", self.set_sys_lst) | ||||
|         ) | ||||
| 
 | ||||
|         self.btn_bodies_browse_pp.clicked.connect( | ||||
|             lambda: self.get_open_file("JSON File (*.json)", self.set_bodies_file) | ||||
|         ) | ||||
|         self.btn_bodies_dest_browse_dl.clicked.connect( | ||||
|             lambda: self.get_save_file("JSON File (*.json)", self.set_bodies_file) | ||||
|         ) | ||||
|         self.btn_systems_browse_pp.clicked.connect( | ||||
|             lambda: self.get_open_file("JSON File (*.json)", self.set_systems_file) | ||||
|         ) | ||||
|         self.btn_systems_dest_browse_dl.clicked.connect( | ||||
|             lambda: self.get_save_file("JSON File (*.json)", self.set_systems_file) | ||||
|         ) | ||||
| 
 | ||||
|     def handle_close(self): | ||||
|         cfg.write(self.config) | ||||
|         print("BYEEEEEE!") | ||||
| 
 | ||||
|     def setup_styles(self, win, app): | ||||
|         for name in app.styles: | ||||
|             action = QAction(app) | ||||
|             action.setObjectName("action_load_style_" + name) | ||||
|             action.setText(name) | ||||
|             action.triggered.connect(lambda _, name=name: app.set_style(name)) | ||||
|             self.menuStyle.addAction(action) | ||||
| 
 | ||||
|     def setupUi(self, MainWindow, app): | ||||
|         super().setupUi(MainWindow) | ||||
|         self.update_dropdowns() | ||||
|         self.main_window = MainWindow | ||||
|         self.app = app | ||||
|         self.setup_signals() | ||||
|         self.lst_sys.setHeaderLabels(["Name", "Type"]) | ||||
|         self.set_route_mode() | ||||
|         self.update_permute_chk(self.chk_permute.isChecked()) | ||||
|         self.setup_styles(MainWindow, app) | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     MP.freeze_support() | ||||
|     app = App() | ||||
|     app.setWindowIcon(QIcon(r'D:\devel\rust\ed_lrr_gui\icon\icon.ico')) | ||||
|     MainWindow = QMainWindow() | ||||
|     MainWindow.setWindowIcon(QIcon(r'D:\devel\rust\ed_lrr_gui\icon\icon.ico')) | ||||
|     ui = ED_LRR() | ||||
|     ui.setupUi(MainWindow, app) | ||||
|     MainWindow.show() | ||||
|     ret = app.exec_() | ||||
|     ui.handle_close() | ||||
|     exit(ret) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
|  | @ -1,8 +1,9 @@ | |||
| from multiprocessing import Process, Queue, freeze_support | ||||
| import queue | ||||
| from datetime import datetime, timedelta | ||||
| import _ed_lrr | ||||
| from collections import namedtuple | ||||
| from datetime import datetime, timedelta | ||||
| from multiprocessing import Process, Queue, freeze_support | ||||
| 
 | ||||
| import _ed_lrr | ||||
| 
 | ||||
| 
 | ||||
| class Preprocessor(Process): | ||||
|  |  | |||
|  | @ -1,8 +1,16 @@ | |||
| from multiprocessing import Process, Queue, freeze_support | ||||
| import queue | ||||
| from datetime import datetime, timedelta | ||||
| import _ed_lrr | ||||
| from collections import namedtuple | ||||
| from datetime import datetime, timedelta | ||||
| from multiprocessing import Process, Queue, freeze_support | ||||
| 
 | ||||
| import _ed_lrr | ||||
| # from PyQt5.QtWidgets import QProgressDialog | ||||
| 
 | ||||
| 
 | ||||
| # class RouteProgress(QProgressDialog): | ||||
| #     def __init__(self, *args, **kwargs): | ||||
| #         super().__init__(*args, **kwargs) | ||||
| #         self.setWindowModality(Qt.WindowModal) | ||||
| 
 | ||||
| 
 | ||||
| class Router(Process): | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								icon/icon.ico
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icon/icon.ico
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 368 KiB | 
							
								
								
									
										115
									
								
								icon/make.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								icon/make.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| import svgwrite | ||||
| import random | ||||
| import time | ||||
| from math import factorial | ||||
| from itertools import permutations | ||||
| import tsp as m_tsp | ||||
| 
 | ||||
| def dist(p1,p2): | ||||
|     return dist2(p1,p2)**0.5 | ||||
| 
 | ||||
| 
 | ||||
| def dist2(p1,p2): | ||||
|     diff=0 | ||||
|     for a,b in zip(p1,p2): | ||||
|         diff+=(a-b)**2 | ||||
|     return diff | ||||
| 
 | ||||
| 
 | ||||
| def tsp(points): | ||||
|     res=[] | ||||
|     for idx in m_tsp.tsp(points)[1]: | ||||
|         res.append(points[idx]) | ||||
|     return res | ||||
| 
 | ||||
| 
 | ||||
| def make_points(n,size,min_dist=0): | ||||
|     min_dist*=min_dist | ||||
|     points=[] | ||||
|     while len(points)<n: | ||||
|         px,py=random.random(),random.random() | ||||
|         px*=size/2 | ||||
|         py*=size/2 | ||||
|         px+=70 | ||||
|         py+=70 | ||||
|         valid=True | ||||
|         for p in points: | ||||
|             if dist2(p,(px,py))<min_dist: | ||||
|                 valid=False | ||||
|                 break | ||||
|         if valid: | ||||
|             points.append((px,py)) | ||||
|             print("{}/{}".format(len(points),n)) | ||||
|     return points | ||||
| def generate(seed,name=None,small=False): | ||||
|     sd=1 | ||||
|     if small: | ||||
|         sd=2 | ||||
|     random.seed(seed) | ||||
|     w=2 | ||||
|     max_rings=3 | ||||
|     num_points=10 | ||||
|     min_dist=10+10+20*(max_rings+1) | ||||
|     base_r=10 | ||||
|     ring_step=lambda v:10+v*10 | ||||
|     size=1000 | ||||
|     if name is None: | ||||
|         name=seed | ||||
|     dwg=svgwrite.Drawing(filename="out/{}.svg".format(name)) | ||||
|     dwg.defs.add(dwg.style(".background { fill: #222; }")) | ||||
|     dwg.add(dwg.rect(size=('100%','100%'), class_='background')) | ||||
|     print("Generating points...") | ||||
|     color="#eee" | ||||
|     pos=make_points(num_points,size,min_dist=min_dist) | ||||
|     print("TSP...") | ||||
|      | ||||
|     min_d=float('inf') | ||||
| 
 | ||||
|     for p1 in pos: | ||||
|         for p2 in pos: | ||||
|             if p1==p2: | ||||
|                 continue | ||||
|             min_d=min(min_d,dist(p1,p2)) | ||||
|     print(min_d,min_dist) | ||||
|     pos=tsp(pos) | ||||
| 
 | ||||
|     for (x1,y1),(x2,y2) in zip(pos,pos[1:]): | ||||
|         if small: | ||||
|             x1/=sd | ||||
|             x2/=sd | ||||
|             y1/=sd | ||||
|             y2/=sd | ||||
|         line=dwg.add(dwg.line((x1,y1),(x2,y2),stroke_width=w,stroke=color)) | ||||
| 
 | ||||
|     for (px,py) in pos: | ||||
|         base_r=3 | ||||
|         if small: | ||||
|             base_r=5 | ||||
|             px/=sd | ||||
|             py/=sd | ||||
|         px=svgwrite.px(px) | ||||
|         py=svgwrite.px(py) | ||||
|         if random.random()>0.8: | ||||
|             dwg.add(dwg.circle((px,py),r=base_r+random.random()*base_r,stroke_width=w,stroke='#0ae')).fill('#0ae') | ||||
|         else: | ||||
|             dwg.add(dwg.circle((px,py),r=base_r+random.random()*base_r,stroke_width=w,stroke=color)).fill(color) | ||||
|         r=base_r | ||||
|         for _ in range(random.randint(1,max_rings)): | ||||
|             if small: | ||||
|                 random.random() | ||||
|                 random.random() | ||||
|                 continue | ||||
|             r+=ring_step(random.random()) | ||||
|             if random.random()>0.75: | ||||
|                 circ=dwg.add(dwg.circle((px,py),r=r,stroke_width=w,stroke="#ea0")) | ||||
|             else: | ||||
|                 circ=dwg.add(dwg.circle((px,py),r=r,stroke_width=w,stroke=color)) | ||||
|             circ.fill(color,opacity=0) | ||||
| 
 | ||||
|     dwg.save() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| seed=0 | ||||
| generate(seed,"icon_1",small=False) | ||||
| generate(seed,"icon_1_small",small=True) | ||||
							
								
								
									
										2
									
								
								icon/out/icon_1.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								icon/out/icon_1.svg
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| After Width: | Height: | Size: 5.8 KiB | 
							
								
								
									
										2
									
								
								icon/out/icon_1_small.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								icon/out/icon_1_small.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| <?xml version="1.0" encoding="utf-8" ?> | ||||
| <svg baseProfile="full" height="100%" version="1.1" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"><![CDATA[.background { fill: #222; }]]></style></defs><rect class="background" height="100%" width="100%" x="0" y="0" /><line stroke="#eee" stroke-width="2" x1="246.10546288126204" x2="262.0282212988338" y1="224.4886007350756" y2="161.17171395434758" /><line stroke="#eee" stroke-width="2" x1="262.0282212988338" x2="230.94964725869315" y1="161.17171395434758" y2="110.82818151973186" /><line stroke="#eee" stroke-width="2" x1="230.94964725869315" x2="172.17482595889732" y1="110.82818151973186" y2="38.51042504100474" /><line stroke="#eee" stroke-width="2" x1="172.17482595889732" x2="140.14289520771126" y1="38.51042504100474" y2="99.72918757324084" /><line stroke="#eee" stroke-width="2" x1="140.14289520771126" x2="35.28570482860707" y1="99.72918757324084" y2="158.39446661633116" /><line stroke="#eee" stroke-width="2" x1="35.28570482860707" x2="105.45946109992596" y1="158.39446661633116" y2="223.95105103930598" /><line stroke="#eee" stroke-width="2" x1="105.45946109992596" x2="154.14923853808895" y1="223.95105103930598" y2="180.8455098637578" /><line stroke="#eee" stroke-width="2" x1="154.14923853808895" x2="154.25244413817927" y1="180.8455098637578" y2="251.32748194291003" /><line stroke="#eee" stroke-width="2" x1="154.25244413817927" x2="262.43656399206003" y1="251.32748194291003" y2="280.6963690094133" /><circle cx="246.10546288126204px" cy="224.4886007350756px" fill="#0ae" r="6.21955438443566" stroke="#0ae" stroke-width="2" /><circle cx="262.0282212988338px" cy="161.17171395434758px" fill="#0ae" r="5.712471969544122" stroke="#0ae" stroke-width="2" /><circle cx="230.94964725869315px" cy="110.82818151973186px" fill="#eee" r="8.532807049334448" stroke="#eee" stroke-width="2" /><circle cx="172.17482595889732px" cy="38.51042504100474px" fill="#eee" r="8.989675096605016" stroke="#eee" stroke-width="2" /><circle cx="140.14289520771126px" cy="99.72918757324084px" fill="#eee" r="8.283296944948145" stroke="#eee" stroke-width="2" /><circle cx="35.28570482860707px" cy="158.39446661633116px" fill="#eee" r="5.401241589269531" stroke="#eee" stroke-width="2" /><circle cx="105.45946109992596px" cy="223.95105103930598px" fill="#0ae" r="9.475194837133376" stroke="#0ae" stroke-width="2" /><circle cx="154.14923853808895px" cy="180.8455098637578px" fill="#0ae" r="6.786837729900069" stroke="#0ae" stroke-width="2" /><circle cx="154.25244413817927px" cy="251.32748194291003px" fill="#eee" r="8.65744610395424" stroke="#eee" stroke-width="2" /><circle cx="262.43656399206003px" cy="280.6963690094133px" fill="#eee" r="7.1306556767192895" stroke="#eee" stroke-width="2" /></svg> | ||||
| After Width: | Height: | Size: 2.8 KiB | 
							
								
								
									
										22
									
								
								installer/ED_LRR.iss
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								installer/ED_LRR.iss
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| [Setup] | ||||
| AppName = "ED_LRR" | ||||
| AppVersion ="0.1.0" | ||||
| ; WizardStyle = modern | ||||
| DefaultDirName = {autopf}\ED_LRR | ||||
| DefaultGroupName=ED_LRR | ||||
| Compression = lzma/ultra | ||||
| SolidCompression = true | ||||
| InternalCompressLevel = ultra | ||||
| OutputBaseFilename="ED_LRR Setup" | ||||
| ChangesEnvironment = true | ||||
| 
 | ||||
| [Files] | ||||
| Source: "..\exe\dist\ED_LRR\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs | ||||
| 
 | ||||
| [Icons] | ||||
| Name: "{group}\ED_LRR"; Filename: "{app}\ED_LRR.exe"; WorkingDir: "{app}" | ||||
| Name: "{group}\Uninstall ED_LRR"; Filename: "{uninstallexe}" | ||||
| 
 | ||||
| [Run] | ||||
| Filename: "{app}\ED_LRR.exe"; Description: "Launch ED_LRR"; Flags: postinstall nowait skipifsilent unchecked | ||||
| Filename: "{app}\ED_LRR.exe"; Parameters: "download" | ||||
|  | @ -1,2 +1,2 @@ | |||
| [build] | ||||
| rustflags = ["-C", "target-cpu=native"] | ||||
| rustflags = ["-C", "target-cpu=native"] | ||||
|  |  | |||
							
								
								
									
										392
									
								
								rust/Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										392
									
								
								rust/Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -8,15 +8,6 @@ dependencies = [ | |||
|  "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "atty" | ||||
| version = "0.2.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "autocfg" | ||||
| version = "0.1.5" | ||||
|  | @ -29,14 +20,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "1.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "block-buffer" | ||||
| version = "0.7.3" | ||||
|  | @ -64,7 +50,7 @@ dependencies = [ | |||
|  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -77,47 +63,6 @@ name = "byteorder" | |||
| version = "1.3.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| version = "0.1.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "clicolors-control" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cloudabi" | ||||
| version = "0.0.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "console" | ||||
| version = "0.7.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "csv" | ||||
| version = "1.1.1" | ||||
|  | @ -127,7 +72,7 @@ dependencies = [ | |||
|  "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -163,12 +108,11 @@ dependencies = [ | |||
|  "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pyo3 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rstar 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pyo3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rstar 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -179,11 +123,6 @@ name = "either" | |||
| version = "1.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "encode_unicode" | ||||
| version = "0.3.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "fnv" | ||||
| version = "1.0.6" | ||||
|  | @ -209,42 +148,51 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "humantime" | ||||
| version = "1.2.0" | ||||
| version = "1.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "indicatif" | ||||
| version = "0.11.0" | ||||
| name = "indoc" | ||||
| version = "0.3.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "indoc-impl" | ||||
| version = "0.3.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "unindent 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "inventory" | ||||
| version = "0.1.3" | ||||
| version = "0.1.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ghost 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "inventory-impl 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "inventory-impl" | ||||
| version = "0.1.3" | ||||
| version = "0.1.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -272,41 +220,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 
 | ||||
| [[package]] | ||||
| name = "libc" | ||||
| version = "0.2.60" | ||||
| version = "0.2.62" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lock_api" | ||||
| version = "0.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "mashup" | ||||
| version = "0.1.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "mashup-impl" | ||||
| version = "0.1.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "memchr" | ||||
| version = "2.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -317,41 +239,29 @@ dependencies = [ | |||
|  "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "number_prefix" | ||||
| version = "0.2.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "opaque-debug" | ||||
| version = "0.2.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "parking_lot" | ||||
| version = "0.9.0" | ||||
| name = "paste" | ||||
| version = "0.1.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "parking_lot_core" | ||||
| version = "0.6.2" | ||||
| name = "paste-impl" | ||||
| version = "0.1.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -366,17 +276,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-hack" | ||||
| version = "0.4.2" | ||||
| version = "0.5.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro-hack-impl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-hack-impl" | ||||
| version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "0.4.30" | ||||
|  | @ -386,39 +293,51 @@ dependencies = [ | |||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pyo3" | ||||
| version = "0.7.0" | ||||
| name = "proc-macro2" | ||||
| version = "1.0.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "inventory 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pyo3" | ||||
| version = "0.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pyo3cls 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pyo3cls 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "unindent 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pyo3-derive-backend" | ||||
| version = "0.7.0" | ||||
| version = "0.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "pyo3cls" | ||||
| version = "0.7.0" | ||||
| version = "0.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pyo3-derive-backend 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pyo3-derive-backend 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -435,18 +354,21 @@ dependencies = [ | |||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "redox_syscall" | ||||
| version = "0.1.56" | ||||
| name = "quote" | ||||
| version = "1.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "regex" | ||||
| version = "1.2.1" | ||||
| version = "1.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -460,12 +382,12 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "regex-syntax" | ||||
| version = "0.6.11" | ||||
| version = "0.6.12" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rstar" | ||||
| version = "0.5.0" | ||||
| version = "0.5.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -473,40 +395,14 @@ dependencies = [ | |||
|  "pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustc_version" | ||||
| version = "0.2.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ryu" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "scopeguard" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "semver" | ||||
| version = "0.9.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "semver-parser" | ||||
| version = "0.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.98" | ||||
| version = "1.0.100" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -529,7 +425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -544,14 +440,9 @@ dependencies = [ | |||
|  "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "smallvec" | ||||
| version = "0.6.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "spin" | ||||
| version = "0.5.0" | ||||
| version = "0.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -570,11 +461,13 @@ dependencies = [ | |||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "termios" | ||||
| version = "0.3.1" | ||||
| name = "syn" | ||||
| version = "1.0.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -590,116 +483,85 @@ name = "typenum" | |||
| version = "1.10.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-width" | ||||
| version = "0.1.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-xid" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-xid" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unindent" | ||||
| version = "0.1.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "version_check" | ||||
| version = "0.1.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "winapi" | ||||
| version = "0.3.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "winapi-i686-pc-windows-gnu" | ||||
| version = "0.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "winapi-x86_64-pc-windows-gnu" | ||||
| version = "0.4.0" | ||||
| version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [metadata] | ||||
| "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" | ||||
| "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" | ||||
| "checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" | ||||
| "checksum bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9f04a5e50dc80b3d5d35320889053637d15011aed5e66b66b37ae798c65da6f7" | ||||
| "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" | ||||
| "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" | ||||
| "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" | ||||
| "checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" | ||||
| "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" | ||||
| "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" | ||||
| "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" | ||||
| "checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" | ||||
| "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" | ||||
| "checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628" | ||||
| "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" | ||||
| "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" | ||||
| "checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" | ||||
| "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" | ||||
| "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" | ||||
| "checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" | ||||
| "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" | ||||
| "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" | ||||
| "checksum ghost 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5297b71943dc9fea26a3241b178c140ee215798b7f79f7773fd61683e25bca74" | ||||
| "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" | ||||
| "checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c" | ||||
| "checksum inventory 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21df85981fe094480bc2267723d3dc0fd1ae0d1f136affc659b7398be615d922" | ||||
| "checksum inventory-impl 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a877ae8bce77402d5e9ed870730939e097aad827b2a932b361958fa9d6e75aa" | ||||
| "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" | ||||
| "checksum indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9553c1e16c114b8b77ebeb329e5f2876eed62a8d51178c8bc6bff0d65f98f8" | ||||
| "checksum indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75" | ||||
| "checksum inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4cece20baea71d9f3435e7bbe9adf4765f091c5fe404975f844006964a71299" | ||||
| "checksum inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9" | ||||
| "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" | ||||
| "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" | ||||
| "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" | ||||
| "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" | ||||
| "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" | ||||
| "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" | ||||
| "checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" | ||||
| "checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" | ||||
| "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" | ||||
| "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" | ||||
| "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" | ||||
| "checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee" | ||||
| "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" | ||||
| "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" | ||||
| "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" | ||||
| "checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" | ||||
| "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" | ||||
| "checksum pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" | ||||
| "checksum permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c" | ||||
| "checksum proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "463bf29e7f11344e58c9e01f171470ab15c925c6822ad75028cc1c0e1d1eb63b" | ||||
| "checksum proc-macro-hack-impl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38c47dcb1594802de8c02f3b899e2018c78291168a22c281be21ea0fb4796842" | ||||
| "checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" | ||||
| "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" | ||||
| "checksum pyo3 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d09e6e2d3fa5ae1a8af694f865e03e763e730768b16e3097851ff0b7f2276086" | ||||
| "checksum pyo3-derive-backend 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d7ae8ab3017515cd7c82d88ce49b55e12a56c602dc69993e123da45c91b186" | ||||
| "checksum pyo3cls 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c494f8161f5b73096cc50f00fbb90fe670f476cde5e59c1decff39b546d54f40" | ||||
| "checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" | ||||
| "checksum pyo3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5862a106c576591645b9fa36b56764b6c894dda70800479892997e5b4fd41c0f" | ||||
| "checksum pyo3-derive-backend 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6d14afa2d06a63331dad47b4b40cac06c3be1e3d7de56d020eab2b3e9484b" | ||||
| "checksum pyo3cls 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e39529c2416febd394f7d032abbce5fa1915e32b2fc9b564e1d9d017acac78d" | ||||
| "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" | ||||
| "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" | ||||
| "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" | ||||
| "checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" | ||||
| "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" | ||||
| "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" | ||||
| "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" | ||||
| "checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" | ||||
| "checksum rstar 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90bb34cd8efef7ed3ebfb29e713e51301c3e60fba37c3e9185a1afaf9ce643a" | ||||
| "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" | ||||
| "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" | ||||
| "checksum rstar 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08c3cf91d6318ed050a8dda79bc857665f9c3d41524b6f70bbd0396c5d9d662d" | ||||
| "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" | ||||
| "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" | ||||
| "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" | ||||
| "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | ||||
| "checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" | ||||
| "checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a" | ||||
| "checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c" | ||||
| "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" | ||||
| "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" | ||||
| "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" | ||||
| "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" | ||||
| "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" | ||||
| "checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" | ||||
| "checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" | ||||
| "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" | ||||
| "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" | ||||
| "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" | ||||
| "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" | ||||
| "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" | ||||
| "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" | ||||
| "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" | ||||
| "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" | ||||
| "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||||
| "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||||
| "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" | ||||
| "checksum unindent 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d0d32a92c9ed197278e09140c32dec854ad5826f0e0e18c1d2a1690f15c8d5" | ||||
| "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" | ||||
|  |  | |||
|  | @ -1,32 +1,27 @@ | |||
| [package] | ||||
| name = "ed_lrr" | ||||
| version = "0.1.0" | ||||
| authors = ["Daniel Seiller <earthnuker@gmail.com>"] | ||||
| edition = "2018" | ||||
| repository = "https://gitlab.com/Earthnuker/ed_lrr.git" | ||||
| license = "WTFPL" | ||||
| 
 | ||||
| 
 | ||||
| [lib] | ||||
| crate-type = ["cdylib"] | ||||
| 
 | ||||
| [profile.release] | ||||
| #debug=true | ||||
| 
 | ||||
| [dependencies] | ||||
| csv = "1.1.1" | ||||
| serde = { version = "1.0", features = ["derive"] } | ||||
| rstar = "0.5.0" | ||||
| humantime = "1.2.0" | ||||
| permutohedron = "0.2.4" | ||||
| serde_json = "1.0.40" | ||||
| indicatif = "0.11.0" | ||||
| fnv = "1.0.6" | ||||
| bincode = "1.1.4" | ||||
| sha3 = "0.8.2" | ||||
| byteorder = "1.3.2" | ||||
| strsim  = "0.9.2" | ||||
| 
 | ||||
| [dependencies.pyo3] | ||||
| version = "0.7.0" | ||||
| features = ["extension-module"] | ||||
| [package] | ||||
| name = "ed_lrr" | ||||
| version = "0.1.0" | ||||
| authors = ["Daniel Seiller <earthnuker@gmail.com>"] | ||||
| edition = "2018" | ||||
| repository = "https://gitlab.com/Earthnuker/ed_lrr.git" | ||||
| license = "WTFPL" | ||||
| 
 | ||||
| 
 | ||||
| [lib] | ||||
| crate-type = ["cdylib"] | ||||
| name = "_ed_lrr" | ||||
| 
 | ||||
| [dependencies] | ||||
| pyo3 = { version = "0.8.0", features = ["extension-module"] } | ||||
| csv = "1.1.1" | ||||
| serde = { version = "1.0", features = ["derive"] } | ||||
| rstar = "0.5.1" | ||||
| humantime = "1.3.0" | ||||
| permutohedron = "0.2.4" | ||||
| serde_json = "1.0.40" | ||||
| fnv = "1.0.6" | ||||
| bincode = "1.1.4" | ||||
| sha3 = "0.8.2" | ||||
| byteorder = "1.3.2" | ||||
| strsim = "0.9.2" | ||||
| 
 | ||||
|  |  | |||
|  | @ -114,7 +114,7 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { | |||
|         py: Python<'static>, | ||||
|         hops: Vec<String>, | ||||
|         range: f32, | ||||
|         radius_mult: f32, | ||||
|         prune: Option<(usize,f64)>, | ||||
|         mode: String, | ||||
|         primary: bool, | ||||
|         permute: bool, | ||||
|  | @ -145,13 +145,14 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { | |||
|             state_dict.set_item("prc_done", state.prc_done)?; | ||||
|             state_dict.set_item("n_seen", state.n_seen)?; | ||||
|             state_dict.set_item("prc_seen", state.prc_seen)?; | ||||
|             state_dict.set_item("from", state.from.clone())?; | ||||
|             state_dict.set_item("to", state.to.clone())?; | ||||
|             callback.call(py, (state_dict,), None) | ||||
|         }; | ||||
|         let mut systems = Vec::new(); | ||||
|         for sys in hops { | ||||
|             systems.push(route::SysEntry::parse(&sys)) | ||||
|         } | ||||
|         println!("SYSTEMS: {:?}", systems); | ||||
|         let opts = RouteOpts { | ||||
|             systems, | ||||
|             range: Some(range), | ||||
|  | @ -165,7 +166,7 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { | |||
|             keep_first, | ||||
|             keep_last, | ||||
|             primary, | ||||
|             radius_mult, | ||||
|             prune, | ||||
|         }; | ||||
|         let none = ().to_object(py); | ||||
|         match route(opts) { | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ pub struct SearchState { | |||
|     pub mode: String, | ||||
|     pub system: String, | ||||
|     pub body: String, | ||||
|     pub from: String, | ||||
|     pub to: String, | ||||
|     pub depth: usize, | ||||
|     pub queue_size: usize, | ||||
|     pub d_rem: f32, | ||||
|  | @ -55,7 +57,7 @@ pub struct RouteOpts { | |||
|     pub keep_last: bool, | ||||
|     pub factor: Option<f32>, | ||||
|     pub mode: Mode, | ||||
|     pub radius_mult: f32, | ||||
|     pub prune: Option<(usize,f64)>, | ||||
|     pub systems: Vec<SysEntry>, | ||||
|     pub callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>, | ||||
| } | ||||
|  | @ -191,7 +193,8 @@ pub struct Router { | |||
|     range: f32, | ||||
|     primary_only: bool, | ||||
|     path: PathBuf, | ||||
|     radius_mult: f32, | ||||
|     prune: Option<(usize,f64)>, | ||||
|     prune_map: FnvHashMap<u32, (usize,f64)>, | ||||
|     callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>, | ||||
| } | ||||
| 
 | ||||
|  | @ -199,7 +202,7 @@ impl Router { | |||
|     pub fn new( | ||||
|         path: &PathBuf, | ||||
|         range: f32, | ||||
|         radius_mult: f32, | ||||
|         prune: Option<(usize,f64)>, | ||||
|         primary_only: bool, | ||||
|         callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>, | ||||
|     ) -> Result<Self, String> { | ||||
|  | @ -245,7 +248,8 @@ impl Router { | |||
|             cache: LineCache::new(path), | ||||
|             path: path.clone(), | ||||
|             callback, | ||||
|             radius_mult, | ||||
|             prune, | ||||
|             prune_map: FnvHashMap::default() | ||||
|         }; | ||||
|         println!( | ||||
|             "{} Systems loaded in {}", | ||||
|  | @ -302,7 +306,8 @@ impl Router { | |||
|                 primary_only: primary, | ||||
|                 path, | ||||
|                 callback, | ||||
|                 radius_mult: 0f32, | ||||
|                 prune: None, | ||||
|                 prune_map: FnvHashMap::default() | ||||
|             }, | ||||
|         )) | ||||
|     } | ||||
|  | @ -317,11 +322,8 @@ impl Router { | |||
| 
 | ||||
|     fn valid(&self, sys: &System, src: &System, dst: &System) -> bool { | ||||
|         let scoopable = self.scoopable.contains(&sys.id); | ||||
|         if self.radius_mult == 0.0 { | ||||
|             return scoopable; | ||||
|         } | ||||
|         let df = src.distp(dst); | ||||
|         (sys.distp(src) + sys.distp(dst)) < (df * (1.0 + self.radius_mult)) | ||||
|         return scoopable; | ||||
|         // TODO: check prune map
 | ||||
|     } | ||||
| 
 | ||||
|     pub fn best_multiroute( | ||||
|  | @ -466,6 +468,8 @@ impl Router { | |||
|             prc_done: 0.0, | ||||
|             n_seen: 0, | ||||
|             prc_seen: 0.0, | ||||
|             from: src_name.clone(), | ||||
|             to: dst_name.clone(), | ||||
|             body: start_sys.body.clone(), | ||||
|             system: start_sys.system.clone(), | ||||
|         }; | ||||
|  | @ -569,6 +573,8 @@ impl Router { | |||
|             prc_done: 0.0, | ||||
|             n_seen: 0, | ||||
|             prc_seen: 0.0, | ||||
|             from: src_name.clone(), | ||||
|             to: dst_name.clone(), | ||||
|             body: start_sys.body.clone(), | ||||
|             system: start_sys.system.clone(), | ||||
|         }; | ||||
|  | @ -793,6 +799,8 @@ impl Router { | |||
|             prc_done: 0.0, | ||||
|             n_seen: 0, | ||||
|             prc_seen: 0.0, | ||||
|             from: src_name.clone(), | ||||
|             to: dst_name.clone(), | ||||
|             system: start_sys.system.clone(), | ||||
|             body: start_sys.body.clone(), | ||||
|         }; | ||||
|  | @ -879,6 +887,7 @@ impl Router { | |||
|     } | ||||
| } | ||||
| pub fn route(opts: RouteOpts) -> Result<Option<Vec<System>>, String> { | ||||
|     // TODO: implement pruning (check if dist to target improved by at least $n*jump_range$ Ly in the last $m$ steps)
 | ||||
|     if opts.systems.is_empty() { | ||||
|         if opts.precomp_file.is_some() { | ||||
|             return Err("Error: Please specify exatly one system".to_owned()); | ||||
|  | @ -898,7 +907,7 @@ pub fn route(opts: RouteOpts) -> Result<Option<Vec<System>>, String> { | |||
|         Router::new( | ||||
|             &path, | ||||
|             opts.range.unwrap(), | ||||
|             opts.radius_mult, | ||||
|             opts.prune, | ||||
|             opts.primary, | ||||
|             Box::new(opts.callback), | ||||
|         )? | ||||
|  | @ -906,14 +915,12 @@ pub fn route(opts: RouteOpts) -> Result<Option<Vec<System>>, String> { | |||
|         Router::new( | ||||
|             &path, | ||||
|             opts.range.unwrap(), | ||||
|             opts.radius_mult, | ||||
|             opts.prune, | ||||
|             opts.primary, | ||||
|             opts.callback, | ||||
|         )? | ||||
|     }; | ||||
|     let systems: Vec<System> = router | ||||
|         .resolve_systems(&opts.systems)? | ||||
|         .to_vec(); | ||||
|     let systems: Vec<System> = router.resolve_systems(&opts.systems)?.to_vec(); | ||||
|     if opts.precompute { | ||||
|         for sys in systems { | ||||
|             router.route_tree = None; | ||||
|  |  | |||
							
								
								
									
										40
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								setup.py
									
										
									
									
									
								
							|  | @ -1,11 +1,21 @@ | |||
| from setuptools import setup,find_packages | ||||
| import sys | ||||
| import distutils.cmd | ||||
| import distutils.log | ||||
| from setuptools import find_packages, setup | ||||
| from setuptools_rust import Binding, RustExtension, Strip | ||||
| 
 | ||||
| with open("README.md", "r") as fh: | ||||
|     long_description = fh.read() | ||||
| 
 | ||||
| 
 | ||||
| setup( | ||||
|     name="ed_lrr_gui", | ||||
|     version="0.1.0", | ||||
|     author="Daniel Seiller", | ||||
|     author_email="earthnuker@gmail.com", | ||||
|     description="Elite: Dangerous long range route plotter", | ||||
|     long_description=long_description, | ||||
|     long_description_content_type="text/markdown", | ||||
|     url="none yet", | ||||
|     rust_extensions=[ | ||||
|         RustExtension( | ||||
|  | @ -17,14 +27,38 @@ setup( | |||
|         ) | ||||
|     ], | ||||
|     packages=find_packages(), | ||||
|     entry_points={"console_scripts": ["ed_lrr_gui=ed_lrr_gui.__main__:main"]}, | ||||
|     entry_points={ | ||||
|         "console_scripts": [ | ||||
|             "ed_lrr_gui_console = ed_lrr_gui.gui.__main__:main", | ||||
|             "ed_lrr = ed_lrr_gui.__main__:main", | ||||
|         ], | ||||
|         "gui_scripts": ["ed_lrr_gui = ed_lrr_gui.gui.__main__:main"], | ||||
|     }, | ||||
|     install_requires=[ | ||||
|         "PyQt5", | ||||
|         "appdirs", | ||||
|         "PyYAML", | ||||
|         "requests", | ||||
|         "python-dateutil", | ||||
|         "pyperclip", | ||||
|         "click", | ||||
|         "PyQt5", | ||||
|         "click-default-group" | ||||
|     ], | ||||
|     setup_requires=[ | ||||
|         "setuptools", | ||||
|         "setuptools-rust", | ||||
|         "wheel", | ||||
|         "pyinstaller", | ||||
|         "pytest-runner", | ||||
|     ], | ||||
|     tests_require=["pytest", "pytest-pep8", "pytest-cov"], | ||||
|     extras_require={ | ||||
|         "dev": ["black", "pyinstaller","jinja2","svgwrite","tsp"], | ||||
|     }, | ||||
|     classifiers=[ | ||||
|         "Programming Language :: Python :: 3", | ||||
|         "License :: OSI Approved :: MIT License", | ||||
|         "Operating System :: OS Independent", | ||||
|     ], | ||||
|     include_package_data=True, | ||||
|     zip_safe=False, | ||||
|  |  | |||
							
								
								
									
										30
									
								
								tox.ini
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tox.ini
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| [tox] | ||||
| envlist = py37 | ||||
| requires = tox-conda | ||||
| 
 | ||||
| [testenv] | ||||
| recreate = True | ||||
| skip_install = True | ||||
| deps = | ||||
|     PyQt5 | ||||
|     setuptools_rust | ||||
| conda_deps =  | ||||
|     pycrypto | ||||
|     nuitka | ||||
| passenv = | ||||
|     CARGO_HOME | ||||
|     RUSTUP_HOME | ||||
|     INCLUDE | ||||
|     LIB | ||||
|     MSSdk | ||||
|     DISTUTILS_USE_SDK | ||||
| whitelist_externals = | ||||
|     cargo | ||||
| conda_channels = | ||||
|     conda-forge | ||||
| extras = | ||||
|     dev | ||||
| commands = | ||||
|     python build_gui.py | ||||
|     pip install .[dev] | ||||
|     python -m nuitka --plugin-enable=multiprocessing --plugin-enable=qt-plugins --standalone --follow-imports --output-dir=exe ed_lrr_gui\__main__.py | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue