feat(GUI): Implement route plotting and fuzzy search
Implement route plotting in GUI Use batch fuzzy search to find systems search all systems at once after adding added some error checking
This commit is contained in:
parent
ec3972b06c
commit
c290d5eb12
18 changed files with 1075 additions and 391 deletions
40
.chglog/CHANGELOG.tpl.md
Normal file
40
.chglog/CHANGELOG.tpl.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{{ if .Versions -}}
|
||||||
|
<a name="unreleased"></a>
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
{{ if .Unreleased.CommitGroups -}}
|
||||||
|
{{ range .Unreleased.CommitGroups -}}
|
||||||
|
{{ range .Commits -}}
|
||||||
|
- {{ .Header }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
{{ range .Versions }}
|
||||||
|
<a name="{{ .Tag.Name }}"></a>
|
||||||
|
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
|
||||||
|
{{ range .CommitGroups -}}
|
||||||
|
{{ range .Commits -}}
|
||||||
|
- {{ .Header }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
{{- if .NoteGroups -}}
|
||||||
|
{{ range .NoteGroups -}}
|
||||||
|
### {{ .Title }}
|
||||||
|
{{ range .Notes }}
|
||||||
|
{{ .Body }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
{{- if .Versions }}
|
||||||
|
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
|
||||||
|
{{ range .Versions -}}
|
||||||
|
{{ if .Tag.Previous -}}
|
||||||
|
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
13
.chglog/config.yml
Normal file
13
.chglog/config.yml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
style: gitlab
|
||||||
|
template: CHANGELOG.tpl.md
|
||||||
|
info:
|
||||||
|
title: CHANGELOG
|
||||||
|
repository_url: https://gitlab.com/Earthnuker/ed_lrr
|
||||||
|
options:
|
||||||
|
header:
|
||||||
|
pattern: "^(.*)$"
|
||||||
|
pattern_maps:
|
||||||
|
- Subject
|
||||||
|
notes:
|
||||||
|
keywords:
|
||||||
|
- BREAKING CHANGE
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -1,15 +1,14 @@
|
||||||
/target
|
rust/target
|
||||||
/dist
|
|
||||||
/build
|
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
*.tmp
|
*.tmp
|
||||||
*.idx
|
*.idx
|
||||||
.vscode/**
|
.vscode/**
|
||||||
|
*.csv
|
||||||
|
*.router
|
||||||
|
plot.py
|
||||||
|
*.tmp
|
||||||
|
*.idx
|
||||||
*.pyd
|
*.pyd
|
||||||
build.bat
|
|
||||||
test.bat
|
|
||||||
__pycache__
|
__pycache__
|
||||||
DL
|
|
||||||
*.egg-info
|
*.egg-info
|
||||||
pip-wheel-metadata
|
build
|
||||||
rust/target/*
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
include rust/Cargo.toml
|
include rust/Cargo.toml
|
||||||
|
include rust/.cargo/config
|
||||||
recursive-include rust/src *
|
recursive-include rust/src *
|
11
build.bat
Normal file
11
build.bat
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
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 ..
|
|
@ -1,2 +1,4 @@
|
||||||
from _ed_lrr import *
|
from _ed_lrr import *
|
||||||
from . import gui
|
from . import gui
|
||||||
|
from .router import Router
|
||||||
|
from .preprocess import Preprocessor
|
||||||
|
|
|
@ -2,21 +2,28 @@ import sys
|
||||||
import os
|
import os
|
||||||
import requests as RQ
|
import requests as RQ
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from PyQt5.QtCore import QThread, pyqtSignal, Qt
|
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, Qt, QObject
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QMainWindow,
|
QMainWindow,
|
||||||
QApplication,
|
QApplication,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
QProgressDialog,
|
QProgressDialog,
|
||||||
QTreeWidgetItem,
|
QTreeWidgetItem,
|
||||||
|
QAction,
|
||||||
|
QMessageBox,
|
||||||
)
|
)
|
||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
import gzip
|
import gzip
|
||||||
|
import pathlib
|
||||||
from PyQt5.QtGui import QPalette, QColor
|
from PyQt5.QtGui import QPalette, QColor
|
||||||
import ed_lrr_gui
|
import ed_lrr_gui
|
||||||
import ed_lrr_gui.config as cfg
|
import ed_lrr_gui.config as cfg
|
||||||
from ed_lrr_gui.gui.ed_lrr import Ui_ED_LRR
|
from ed_lrr_gui.gui.ed_lrr import Ui_ED_LRR
|
||||||
|
from ed_lrr_gui import Router, Preprocessor
|
||||||
import multiprocessing as MP
|
import multiprocessing as MP
|
||||||
|
import queue
|
||||||
|
import csv
|
||||||
|
import _ed_lrr
|
||||||
|
|
||||||
|
|
||||||
def sizeof_fmt(num, suffix="B"):
|
def sizeof_fmt(num, suffix="B"):
|
||||||
|
@ -37,6 +44,85 @@ class ProgressDialog(QProgressDialog):
|
||||||
self.setWindowModality(Qt.WindowModal)
|
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):
|
class DownloadThread(QThread):
|
||||||
progress = pyqtSignal("PyQt_PyObject")
|
progress = pyqtSignal("PyQt_PyObject")
|
||||||
|
|
||||||
|
@ -79,10 +165,16 @@ class App(QApplication):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(sys.argv)
|
super().__init__(sys.argv)
|
||||||
self.setStyle("Fusion")
|
self.setStyle("Fusion")
|
||||||
self.set_pallete()
|
self.setup_styles()
|
||||||
|
|
||||||
def set_pallete(self):
|
def set_style(self, style):
|
||||||
colors = {
|
print("LOAD:", style)
|
||||||
|
self.setPalette(self.styles[style])
|
||||||
|
|
||||||
|
def setup_styles(self):
|
||||||
|
self.styles = {}
|
||||||
|
styles = {
|
||||||
|
"Dark": {
|
||||||
"Window": QColor(53, 53, 53),
|
"Window": QColor(53, 53, 53),
|
||||||
"WindowText": Qt.white,
|
"WindowText": Qt.white,
|
||||||
"Base": QColor(15, 15, 15),
|
"Base": QColor(15, 15, 15),
|
||||||
|
@ -96,6 +188,8 @@ class App(QApplication):
|
||||||
"Highlight": QColor(255, 128, 0),
|
"Highlight": QColor(255, 128, 0),
|
||||||
"HighlightedText": Qt.black,
|
"HighlightedText": Qt.black,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for style, colors in styles.items():
|
||||||
palette = QPalette()
|
palette = QPalette()
|
||||||
for entry, color in colors.items():
|
for entry, color in colors.items():
|
||||||
palette.setColor(getattr(QPalette, entry), color)
|
palette.setColor(getattr(QPalette, entry), color)
|
||||||
|
@ -107,17 +201,29 @@ class App(QApplication):
|
||||||
palette.setColor(
|
palette.setColor(
|
||||||
QPalette.Disabled, getattr(QPalette, entry), Qt.darkGray
|
QPalette.Disabled, getattr(QPalette, entry), Qt.darkGray
|
||||||
)
|
)
|
||||||
self.setPalette(palette)
|
self.styles[style] = palette
|
||||||
|
self.styles["Light"] = self.style().standardPalette()
|
||||||
|
|
||||||
|
|
||||||
class ED_LRR(Ui_ED_LRR):
|
class ED_LRR(Ui_ED_LRR):
|
||||||
dl_thread = None
|
dl_thread = None
|
||||||
diag_prog = None
|
diag_prog = None
|
||||||
dl_started = None
|
dl_started = None
|
||||||
|
system_found = pyqtSignal("PyQt_PyObject")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.config = cfg.load()
|
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):
|
def get_open_file(self, filetypes, callback=None):
|
||||||
fileName, _ = QFileDialog.getOpenFileName(
|
fileName, _ = QFileDialog.getOpenFileName(
|
||||||
|
@ -148,6 +254,8 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.config.history_out_path.append(path)
|
self.config.history_out_path.append(path)
|
||||||
self.inp_sys_lst.addItem(path)
|
self.inp_sys_lst.addItem(path)
|
||||||
self.inp_out_pp.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):
|
def set_bodies_file(self, path):
|
||||||
if path not in self.config.history_bodies_path:
|
if path not in self.config.history_bodies_path:
|
||||||
|
@ -170,7 +278,7 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
def set_comp_mode(self, _):
|
def set_comp_mode(self, _):
|
||||||
if self.rd_comp.isChecked():
|
if self.rd_comp.isChecked():
|
||||||
comp_mode = "Compute Route"
|
comp_mode = "Compute Route"
|
||||||
self.btn_add.setText("Search+Add")
|
self.btn_add.setText("Add")
|
||||||
if self.rd_precomp.isChecked():
|
if self.rd_precomp.isChecked():
|
||||||
comp_mode = "Precompute Graph"
|
comp_mode = "Precompute Graph"
|
||||||
self.btn_add.setText("Select")
|
self.btn_add.setText("Select")
|
||||||
|
@ -178,7 +286,7 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.lst_sys.setEnabled(self.rd_comp.isChecked())
|
self.lst_sys.setEnabled(self.rd_comp.isChecked())
|
||||||
self.btn_rm.setEnabled(self.rd_comp.isChecked())
|
self.btn_rm.setEnabled(self.rd_comp.isChecked())
|
||||||
self.cmb_mode.setEnabled(self.rd_comp.isChecked())
|
self.cmb_mode.setEnabled(self.rd_comp.isChecked())
|
||||||
self.btn_permute.setEnabled(self.rd_comp.isChecked())
|
self.chk_permute.setEnabled(self.rd_comp.isChecked())
|
||||||
self.lbl_keep.setEnabled(self.rd_comp.isChecked())
|
self.lbl_keep.setEnabled(self.rd_comp.isChecked())
|
||||||
self.lbl_mode.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_first.setEnabled(self.rd_comp.isChecked())
|
||||||
|
@ -190,11 +298,17 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
mode = self.cmb_mode.currentText()
|
mode = self.cmb_mode.currentText()
|
||||||
self.lbl_greedyness.setEnabled(mode == "A*-Search")
|
self.lbl_greedyness.setEnabled(mode == "A*-Search")
|
||||||
self.sld_greedyness.setEnabled(mode == "A*-Search")
|
self.sld_greedyness.setEnabled(mode == "A*-Search")
|
||||||
self.log("ROUTE_MODE", mode)
|
|
||||||
|
|
||||||
def set_greedyness(self, value):
|
def set_greedyness(self, value):
|
||||||
self.lbl_greedyness.setText("Greedyness Factor ({:.0%})".format(value / 100))
|
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):
|
def sys_to_dict(self, n):
|
||||||
header = [
|
header = [
|
||||||
self.lst_sys.headerItem().data(c, 0)
|
self.lst_sys.headerItem().data(c, 0)
|
||||||
|
@ -204,34 +318,108 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.lst_sys.topLevelItem(n).data(c, 0)
|
self.lst_sys.topLevelItem(n).data(c, 0)
|
||||||
for c in range(self.lst_sys.topLevelItem(n).columnCount())
|
for c in range(self.lst_sys.topLevelItem(n).columnCount())
|
||||||
]
|
]
|
||||||
return dict(zip(header, system))
|
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):
|
def run(self):
|
||||||
settings = {}
|
if not all(s["Type"] for s in self.systems):
|
||||||
settings["permute"] = (
|
self.error('Not all systens have been resolved, please click "Search All"')
|
||||||
self.chk_permute_keep_first.checkState(),
|
return
|
||||||
self.chk_permute_keep_last.checkState(),
|
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
|
||||||
)
|
)
|
||||||
settings["range"] = self.sb_range.value()
|
path = self.get_sys_list()
|
||||||
settings["systems"] = [
|
if path is None:
|
||||||
self.sys_to_dict(i) for i in range(self.lst_sys.topLevelItemCount())
|
return
|
||||||
]
|
precomp = path.with_suffix(".idx")
|
||||||
print(settings)
|
path = str(path)
|
||||||
progress = ProgressDialog(
|
if not precomp.exists():
|
||||||
"(Not actually computing)", "Cancel", 0, 0, self.main_window
|
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,
|
||||||
)
|
)
|
||||||
progress.setWindowTitle("Computing Route")
|
self.start_job(
|
||||||
progress.setFixedSize(400, 100)
|
Router,
|
||||||
progress.setRange(0, 0)
|
systems,
|
||||||
progress.show()
|
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):
|
def add_system(self):
|
||||||
n = self.lst_sys.topLevelItemCount() + 1
|
|
||||||
name = self.inp_sys.text()
|
name = self.inp_sys.text()
|
||||||
item = QTreeWidgetItem(
|
item = QTreeWidgetItem(self.lst_sys, [name, None])
|
||||||
self.lst_sys, [str(n) + ". Name: " + name, "Type: " + name[::-1]]
|
item.resolved = False
|
||||||
)
|
|
||||||
item.sys_id = "SYS_ID_HERE"
|
|
||||||
item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled)
|
item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled)
|
||||||
|
|
||||||
def remove_system(self):
|
def remove_system(self):
|
||||||
|
@ -253,7 +441,7 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.diag_prog = None
|
self.diag_prog = None
|
||||||
self.dl_started = None
|
self.dl_started = None
|
||||||
|
|
||||||
def handle_progress(self, args):
|
def handle_dl_progress(self, args):
|
||||||
filename = os.path.split(args["outfile"])[-1]
|
filename = os.path.split(args["outfile"])[-1]
|
||||||
if self.diag_prog is None:
|
if self.diag_prog is None:
|
||||||
self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window)
|
self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window)
|
||||||
|
@ -291,10 +479,15 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.inp_bodies_dl.currentText(),
|
self.inp_bodies_dl.currentText(),
|
||||||
self.inp_bodies_dest_dl.currentText(),
|
self.inp_bodies_dest_dl.currentText(),
|
||||||
)
|
)
|
||||||
self.dl_thread.progress.connect(self.handle_progress)
|
self.dl_thread.progress.connect(self.handle_dl_progress)
|
||||||
self.dl_thread.start()
|
self.dl_thread.start()
|
||||||
print(".")
|
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):
|
def setup_signals(self):
|
||||||
self.btn_download.clicked.connect(self.run_download)
|
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_systems_dest_dl.setCurrentText(r"D:\devel\rust\ed_lrr_gui\DL\s.json")
|
||||||
|
@ -307,6 +500,8 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.btn_go.clicked.connect(self.run)
|
self.btn_go.clicked.connect(self.run)
|
||||||
self.btn_add.clicked.connect(self.add_system)
|
self.btn_add.clicked.connect(self.add_system)
|
||||||
self.btn_rm.clicked.connect(self.remove_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(
|
self.btn_out_browse_pp.clicked.connect(
|
||||||
lambda: self.get_save_file("CSV File (*.csv)", self.set_sys_lst)
|
lambda: self.get_save_file("CSV File (*.csv)", self.set_sys_lst)
|
||||||
)
|
)
|
||||||
|
@ -331,6 +526,14 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
cfg.write(self.config)
|
cfg.write(self.config)
|
||||||
print("BYEEEEEE!")
|
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):
|
def setupUi(self, MainWindow, app):
|
||||||
super().setupUi(MainWindow)
|
super().setupUi(MainWindow)
|
||||||
self.update_dropdowns()
|
self.update_dropdowns()
|
||||||
|
@ -339,6 +542,8 @@ class ED_LRR(Ui_ED_LRR):
|
||||||
self.setup_signals()
|
self.setup_signals()
|
||||||
self.lst_sys.setHeaderLabels(["Name", "Type"])
|
self.lst_sys.setHeaderLabels(["Name", "Type"])
|
||||||
self.set_route_mode()
|
self.set_route_mode()
|
||||||
|
self.update_permute_chk(self.chk_permute.isChecked())
|
||||||
|
self.setup_styles(MainWindow, app)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
@ -26,6 +26,14 @@ class Ui_ED_LRR(object):
|
||||||
ED_LRR.setDocumentMode(False)
|
ED_LRR.setDocumentMode(False)
|
||||||
ED_LRR.setTabShape(QtWidgets.QTabWidget.Rounded)
|
ED_LRR.setTabShape(QtWidgets.QTabWidget.Rounded)
|
||||||
self.centralwidget = QtWidgets.QWidget(ED_LRR)
|
self.centralwidget = QtWidgets.QWidget(ED_LRR)
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
=======
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
|
||||||
|
self.centralwidget.setSizePolicy(sizePolicy)
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.centralwidget.setObjectName("centralwidget")
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
@ -214,9 +222,12 @@ class Ui_ED_LRR(object):
|
||||||
self.rd_precomp.setObjectName("rd_precomp")
|
self.rd_precomp.setObjectName("rd_precomp")
|
||||||
self.gr_mode.addWidget(self.rd_precomp, 0, 2, 1, 1)
|
self.gr_mode.addWidget(self.rd_precomp, 0, 2, 1, 1)
|
||||||
self.formLayout_2.setLayout(3, QtWidgets.QFormLayout.FieldRole, self.gr_mode)
|
self.formLayout_2.setLayout(3, QtWidgets.QFormLayout.FieldRole, self.gr_mode)
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.btn_permute = QtWidgets.QPushButton(self.tab_route)
|
self.btn_permute = QtWidgets.QPushButton(self.tab_route)
|
||||||
self.btn_permute.setObjectName("btn_permute")
|
self.btn_permute.setObjectName("btn_permute")
|
||||||
self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.btn_permute)
|
self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.btn_permute)
|
||||||
|
=======
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.lst_sys = QtWidgets.QTreeWidget(self.tab_route)
|
self.lst_sys = QtWidgets.QTreeWidget(self.tab_route)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
@ -231,6 +242,7 @@ class Ui_ED_LRR(object):
|
||||||
self.lst_sys.setAlternatingRowColors(True)
|
self.lst_sys.setAlternatingRowColors(True)
|
||||||
self.lst_sys.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
self.lst_sys.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
self.lst_sys.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
self.lst_sys.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.lst_sys.setHeaderHidden(True)
|
self.lst_sys.setHeaderHidden(True)
|
||||||
self.lst_sys.setObjectName("lst_sys")
|
self.lst_sys.setObjectName("lst_sys")
|
||||||
self.lst_sys.headerItem().setText(0, "1")
|
self.lst_sys.headerItem().setText(0, "1")
|
||||||
|
@ -241,6 +253,19 @@ class Ui_ED_LRR(object):
|
||||||
self.lbl_range = QtWidgets.QLabel(self.tab_route)
|
self.lbl_range = QtWidgets.QLabel(self.tab_route)
|
||||||
self.lbl_range.setObjectName("lbl_range")
|
self.lbl_range.setObjectName("lbl_range")
|
||||||
self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.lbl_range)
|
self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.lbl_range)
|
||||||
|
=======
|
||||||
|
self.lst_sys.setHeaderHidden(False)
|
||||||
|
self.lst_sys.setObjectName("lst_sys")
|
||||||
|
self.lst_sys.headerItem().setText(0, "Name")
|
||||||
|
self.lst_sys.header().setVisible(False)
|
||||||
|
self.formLayout_2.setWidget(7, QtWidgets.QFormLayout.SpanningRole, self.lst_sys)
|
||||||
|
self.sb_range = QtWidgets.QDoubleSpinBox(self.tab_route)
|
||||||
|
self.sb_range.setObjectName("sb_range")
|
||||||
|
self.formLayout_2.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.sb_range)
|
||||||
|
self.lbl_range = QtWidgets.QLabel(self.tab_route)
|
||||||
|
self.lbl_range.setObjectName("lbl_range")
|
||||||
|
self.formLayout_2.setWidget(9, QtWidgets.QFormLayout.LabelRole, self.lbl_range)
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.gr_opts = QtWidgets.QGridLayout()
|
self.gr_opts = QtWidgets.QGridLayout()
|
||||||
self.gr_opts.setObjectName("gr_opts")
|
self.gr_opts.setObjectName("gr_opts")
|
||||||
self.cmb_mode = QtWidgets.QComboBox(self.tab_route)
|
self.cmb_mode = QtWidgets.QComboBox(self.tab_route)
|
||||||
|
@ -268,16 +293,28 @@ class Ui_ED_LRR(object):
|
||||||
self.lbl_mode = QtWidgets.QLabel(self.tab_route)
|
self.lbl_mode = QtWidgets.QLabel(self.tab_route)
|
||||||
self.lbl_mode.setObjectName("lbl_mode")
|
self.lbl_mode.setObjectName("lbl_mode")
|
||||||
self.gr_opts.addWidget(self.lbl_mode, 0, 1, 1, 1)
|
self.gr_opts.addWidget(self.lbl_mode, 0, 1, 1, 1)
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.formLayout_2.setLayout(9, QtWidgets.QFormLayout.SpanningRole, self.gr_opts)
|
self.formLayout_2.setLayout(9, QtWidgets.QFormLayout.SpanningRole, self.gr_opts)
|
||||||
self.btn_go = QtWidgets.QPushButton(self.tab_route)
|
self.btn_go = QtWidgets.QPushButton(self.tab_route)
|
||||||
self.btn_go.setFlat(False)
|
self.btn_go.setFlat(False)
|
||||||
self.btn_go.setObjectName("btn_go")
|
self.btn_go.setObjectName("btn_go")
|
||||||
self.formLayout_2.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.btn_go)
|
self.formLayout_2.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.btn_go)
|
||||||
|
=======
|
||||||
|
self.formLayout_2.setLayout(10, QtWidgets.QFormLayout.SpanningRole, self.gr_opts)
|
||||||
|
self.btn_go = QtWidgets.QPushButton(self.tab_route)
|
||||||
|
self.btn_go.setFlat(False)
|
||||||
|
self.btn_go.setObjectName("btn_go")
|
||||||
|
self.formLayout_2.setWidget(11, QtWidgets.QFormLayout.LabelRole, self.btn_go)
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.gridLayout_4 = QtWidgets.QGridLayout()
|
self.gridLayout_4 = QtWidgets.QGridLayout()
|
||||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||||
self.chk_permute_keep_last = QtWidgets.QCheckBox(self.tab_route)
|
self.chk_permute_keep_last = QtWidgets.QCheckBox(self.tab_route)
|
||||||
self.chk_permute_keep_last.setObjectName("chk_permute_keep_last")
|
self.chk_permute_keep_last.setObjectName("chk_permute_keep_last")
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.gridLayout_4.addWidget(self.chk_permute_keep_last, 0, 2, 1, 1)
|
self.gridLayout_4.addWidget(self.chk_permute_keep_last, 0, 2, 1, 1)
|
||||||
|
=======
|
||||||
|
self.gridLayout_4.addWidget(self.chk_permute_keep_last, 0, 3, 1, 1)
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.chk_permute_keep_first = QtWidgets.QCheckBox(self.tab_route)
|
self.chk_permute_keep_first = QtWidgets.QCheckBox(self.tab_route)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
@ -286,7 +323,11 @@ class Ui_ED_LRR(object):
|
||||||
self.chk_permute_keep_first.setSizePolicy(sizePolicy)
|
self.chk_permute_keep_first.setSizePolicy(sizePolicy)
|
||||||
self.chk_permute_keep_first.setTristate(False)
|
self.chk_permute_keep_first.setTristate(False)
|
||||||
self.chk_permute_keep_first.setObjectName("chk_permute_keep_first")
|
self.chk_permute_keep_first.setObjectName("chk_permute_keep_first")
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.gridLayout_4.addWidget(self.chk_permute_keep_first, 0, 1, 1, 1)
|
self.gridLayout_4.addWidget(self.chk_permute_keep_first, 0, 1, 1, 1)
|
||||||
|
=======
|
||||||
|
self.gridLayout_4.addWidget(self.chk_permute_keep_first, 0, 2, 1, 1)
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.lbl_keep = QtWidgets.QLabel(self.tab_route)
|
self.lbl_keep = QtWidgets.QLabel(self.tab_route)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
@ -294,8 +335,19 @@ class Ui_ED_LRR(object):
|
||||||
sizePolicy.setHeightForWidth(self.lbl_keep.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.lbl_keep.sizePolicy().hasHeightForWidth())
|
||||||
self.lbl_keep.setSizePolicy(sizePolicy)
|
self.lbl_keep.setSizePolicy(sizePolicy)
|
||||||
self.lbl_keep.setObjectName("lbl_keep")
|
self.lbl_keep.setObjectName("lbl_keep")
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.gridLayout_4.addWidget(self.lbl_keep, 0, 0, 1, 1)
|
self.gridLayout_4.addWidget(self.lbl_keep, 0, 0, 1, 1)
|
||||||
self.formLayout_2.setLayout(4, QtWidgets.QFormLayout.FieldRole, self.gridLayout_4)
|
self.formLayout_2.setLayout(4, QtWidgets.QFormLayout.FieldRole, self.gridLayout_4)
|
||||||
|
=======
|
||||||
|
self.gridLayout_4.addWidget(self.lbl_keep, 0, 1, 1, 1)
|
||||||
|
self.formLayout_2.setLayout(4, QtWidgets.QFormLayout.FieldRole, self.gridLayout_4)
|
||||||
|
self.chk_permute = QtWidgets.QCheckBox(self.tab_route)
|
||||||
|
self.chk_permute.setObjectName("chk_permute")
|
||||||
|
self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.chk_permute)
|
||||||
|
self.btn_search = QtWidgets.QPushButton(self.tab_route)
|
||||||
|
self.btn_search.setObjectName("btn_search")
|
||||||
|
self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.btn_search)
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.tabs.addTab(self.tab_route, "")
|
self.tabs.addTab(self.tab_route, "")
|
||||||
self.tab_log = QtWidgets.QWidget()
|
self.tab_log = QtWidgets.QWidget()
|
||||||
self.tab_log.setObjectName("tab_log")
|
self.tab_log.setObjectName("tab_log")
|
||||||
|
@ -317,14 +369,32 @@ class Ui_ED_LRR(object):
|
||||||
self.menu.setObjectName("menu")
|
self.menu.setObjectName("menu")
|
||||||
self.menu_file = QtWidgets.QMenu(self.menu)
|
self.menu_file = QtWidgets.QMenu(self.menu)
|
||||||
self.menu_file.setObjectName("menu_file")
|
self.menu_file.setObjectName("menu_file")
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
=======
|
||||||
|
self.menuWindow = QtWidgets.QMenu(self.menu)
|
||||||
|
self.menuWindow.setObjectName("menuWindow")
|
||||||
|
self.menuStyle = QtWidgets.QMenu(self.menuWindow)
|
||||||
|
self.menuStyle.setObjectName("menuStyle")
|
||||||
|
>>>>>>> Stashed changes
|
||||||
ED_LRR.setMenuBar(self.menu)
|
ED_LRR.setMenuBar(self.menu)
|
||||||
self.bar_status = QtWidgets.QStatusBar(ED_LRR)
|
self.bar_status = QtWidgets.QStatusBar(ED_LRR)
|
||||||
self.bar_status.setObjectName("bar_status")
|
self.bar_status.setObjectName("bar_status")
|
||||||
ED_LRR.setStatusBar(self.bar_status)
|
ED_LRR.setStatusBar(self.bar_status)
|
||||||
self.menu_act_quit = QtWidgets.QAction(ED_LRR)
|
self.menu_act_quit = QtWidgets.QAction(ED_LRR)
|
||||||
self.menu_act_quit.setObjectName("menu_act_quit")
|
self.menu_act_quit.setObjectName("menu_act_quit")
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.menu_file.addAction(self.menu_act_quit)
|
self.menu_file.addAction(self.menu_act_quit)
|
||||||
self.menu.addAction(self.menu_file.menuAction())
|
self.menu.addAction(self.menu_file.menuAction())
|
||||||
|
=======
|
||||||
|
self.actionA = QtWidgets.QAction(ED_LRR)
|
||||||
|
self.actionA.setObjectName("actionA")
|
||||||
|
self.actionB = QtWidgets.QAction(ED_LRR)
|
||||||
|
self.actionB.setObjectName("actionB")
|
||||||
|
self.menu_file.addAction(self.menu_act_quit)
|
||||||
|
self.menuWindow.addAction(self.menuStyle.menuAction())
|
||||||
|
self.menu.addAction(self.menu_file.menuAction())
|
||||||
|
self.menu.addAction(self.menuWindow.menuAction())
|
||||||
|
>>>>>>> Stashed changes
|
||||||
|
|
||||||
self.retranslateUi(ED_LRR)
|
self.retranslateUi(ED_LRR)
|
||||||
self.tabs.setCurrentIndex(2)
|
self.tabs.setCurrentIndex(2)
|
||||||
|
@ -358,12 +428,20 @@ class Ui_ED_LRR(object):
|
||||||
self.tabs.setTabText(self.tabs.indexOf(self.tab_preprocess), _translate("ED_LRR", "Preprocess"))
|
self.tabs.setTabText(self.tabs.indexOf(self.tab_preprocess), _translate("ED_LRR", "Preprocess"))
|
||||||
self.lbl_sys_lst.setText(_translate("ED_LRR", "System List"))
|
self.lbl_sys_lst.setText(_translate("ED_LRR", "System List"))
|
||||||
self.btn_sys_lst_browse.setText(_translate("ED_LRR", "..."))
|
self.btn_sys_lst_browse.setText(_translate("ED_LRR", "..."))
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.btn_add.setText(_translate("ED_LRR", "Search+Add"))
|
self.btn_add.setText(_translate("ED_LRR", "Search+Add"))
|
||||||
|
=======
|
||||||
|
self.btn_add.setText(_translate("ED_LRR", "Add"))
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.inp_sys.setPlaceholderText(_translate("ED_LRR", "System Name"))
|
self.inp_sys.setPlaceholderText(_translate("ED_LRR", "System Name"))
|
||||||
self.btn_rm.setText(_translate("ED_LRR", "Remove"))
|
self.btn_rm.setText(_translate("ED_LRR", "Remove"))
|
||||||
self.rd_comp.setText(_translate("ED_LRR", "Compute Route"))
|
self.rd_comp.setText(_translate("ED_LRR", "Compute Route"))
|
||||||
self.rd_precomp.setText(_translate("ED_LRR", "Precompute Graph"))
|
self.rd_precomp.setText(_translate("ED_LRR", "Precompute Graph"))
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.btn_permute.setText(_translate("ED_LRR", "Permute"))
|
self.btn_permute.setText(_translate("ED_LRR", "Permute"))
|
||||||
|
=======
|
||||||
|
self.lst_sys.headerItem().setText(1, _translate("ED_LRR", "Type"))
|
||||||
|
>>>>>>> Stashed changes
|
||||||
self.lbl_range.setText(_translate("ED_LRR", "Jump Range (Ly)"))
|
self.lbl_range.setText(_translate("ED_LRR", "Jump Range (Ly)"))
|
||||||
self.cmb_mode.setCurrentText(_translate("ED_LRR", "Breadth-First Search"))
|
self.cmb_mode.setCurrentText(_translate("ED_LRR", "Breadth-First Search"))
|
||||||
self.cmb_mode.setItemText(0, _translate("ED_LRR", "Breadth-First Search"))
|
self.cmb_mode.setItemText(0, _translate("ED_LRR", "Breadth-First Search"))
|
||||||
|
@ -376,8 +454,22 @@ class Ui_ED_LRR(object):
|
||||||
self.chk_permute_keep_last.setText(_translate("ED_LRR", "Last"))
|
self.chk_permute_keep_last.setText(_translate("ED_LRR", "Last"))
|
||||||
self.chk_permute_keep_first.setText(_translate("ED_LRR", "First"))
|
self.chk_permute_keep_first.setText(_translate("ED_LRR", "First"))
|
||||||
self.lbl_keep.setText(_translate("ED_LRR", "Keep Endpoints:"))
|
self.lbl_keep.setText(_translate("ED_LRR", "Keep Endpoints:"))
|
||||||
|
<<<<<<< Updated upstream
|
||||||
self.tabs.setTabText(self.tabs.indexOf(self.tab_route), _translate("ED_LRR", "Route"))
|
self.tabs.setTabText(self.tabs.indexOf(self.tab_route), _translate("ED_LRR", "Route"))
|
||||||
self.tabs.setTabText(self.tabs.indexOf(self.tab_log), _translate("ED_LRR", "Log"))
|
self.tabs.setTabText(self.tabs.indexOf(self.tab_log), _translate("ED_LRR", "Log"))
|
||||||
self.menu_file.setTitle(_translate("ED_LRR", "File"))
|
self.menu_file.setTitle(_translate("ED_LRR", "File"))
|
||||||
self.menu_act_quit.setText(_translate("ED_LRR", "Quit"))
|
self.menu_act_quit.setText(_translate("ED_LRR", "Quit"))
|
||||||
self.menu_act_quit.setShortcut(_translate("ED_LRR", "Ctrl+Q"))
|
self.menu_act_quit.setShortcut(_translate("ED_LRR", "Ctrl+Q"))
|
||||||
|
=======
|
||||||
|
self.chk_permute.setText(_translate("ED_LRR", "Permute"))
|
||||||
|
self.btn_search.setText(_translate("ED_LRR", "Search All"))
|
||||||
|
self.tabs.setTabText(self.tabs.indexOf(self.tab_route), _translate("ED_LRR", "Route"))
|
||||||
|
self.tabs.setTabText(self.tabs.indexOf(self.tab_log), _translate("ED_LRR", "Log"))
|
||||||
|
self.menu_file.setTitle(_translate("ED_LRR", "File"))
|
||||||
|
self.menuWindow.setTitle(_translate("ED_LRR", "Window"))
|
||||||
|
self.menuStyle.setTitle(_translate("ED_LRR", "Style"))
|
||||||
|
self.menu_act_quit.setText(_translate("ED_LRR", "Quit"))
|
||||||
|
self.menu_act_quit.setShortcut(_translate("ED_LRR", "Ctrl+Q"))
|
||||||
|
self.actionA.setText(_translate("ED_LRR", "A"))
|
||||||
|
self.actionB.setText(_translate("ED_LRR", "B"))
|
||||||
|
>>>>>>> Stashed changes
|
||||||
|
|
|
@ -44,6 +44,15 @@
|
||||||
<enum>QTabWidget::Rounded</enum>
|
<enum>QTabWidget::Rounded</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
=======
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabs">
|
<widget class="QTabWidget" name="tabs">
|
||||||
|
@ -363,7 +372,11 @@
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QPushButton" name="btn_add">
|
<widget class="QPushButton" name="btn_add">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<string>Search+Add</string>
|
<string>Search+Add</string>
|
||||||
|
=======
|
||||||
|
<string>Add</string>
|
||||||
|
>>>>>>> Stashed changes
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -402,6 +415,7 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QPushButton" name="btn_permute">
|
<widget class="QPushButton" name="btn_permute">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -409,6 +423,8 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
=======
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<item row="7" column="0" colspan="2">
|
<item row="7" column="0" colspan="2">
|
||||||
<widget class="QTreeWidget" name="lst_sys">
|
<widget class="QTreeWidget" name="lst_sys">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -445,26 +461,53 @@
|
||||||
<enum>QAbstractItemView::SelectRows</enum>
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="headerHidden">
|
<property name="headerHidden">
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">1</string>
|
<string notr="true">1</string>
|
||||||
|
=======
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="headerVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Name</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
>>>>>>> Stashed changes
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="8" column="1">
|
<item row="8" column="1">
|
||||||
<widget class="QDoubleSpinBox" name="sb_range"/>
|
<widget class="QDoubleSpinBox" name="sb_range"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="8" column="0">
|
||||||
|
=======
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="sb_range"/>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<widget class="QLabel" name="lbl_range">
|
<widget class="QLabel" name="lbl_range">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Jump Range (Ly)</string>
|
<string>Jump Range (Ly)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="9" column="0" colspan="2">
|
<item row="9" column="0" colspan="2">
|
||||||
|
=======
|
||||||
|
<item row="10" column="0" colspan="2">
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<layout class="QGridLayout" name="gr_opts">
|
<layout class="QGridLayout" name="gr_opts">
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QComboBox" name="cmb_mode">
|
<widget class="QComboBox" name="cmb_mode">
|
||||||
|
@ -536,7 +579,11 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="10" column="0">
|
<item row="10" column="0">
|
||||||
|
=======
|
||||||
|
<item row="11" column="0">
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<widget class="QPushButton" name="btn_go">
|
<widget class="QPushButton" name="btn_go">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>GO!</string>
|
<string>GO!</string>
|
||||||
|
@ -548,14 +595,22 @@
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
|
=======
|
||||||
|
<item row="0" column="3">
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<widget class="QCheckBox" name="chk_permute_keep_last">
|
<widget class="QCheckBox" name="chk_permute_keep_last">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Last</string>
|
<string>Last</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
|
=======
|
||||||
|
<item row="0" column="2">
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<widget class="QCheckBox" name="chk_permute_keep_first">
|
<widget class="QCheckBox" name="chk_permute_keep_first">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
@ -571,7 +626,11 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
=======
|
||||||
|
<item row="0" column="1">
|
||||||
|
>>>>>>> Stashed changes
|
||||||
<widget class="QLabel" name="lbl_keep">
|
<widget class="QLabel" name="lbl_keep">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
@ -586,6 +645,23 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
=======
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="chk_permute">
|
||||||
|
<property name="text">
|
||||||
|
<string>Permute</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QPushButton" name="btn_search">
|
||||||
|
<property name="text">
|
||||||
|
<string>Search All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
>>>>>>> Stashed changes
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_log">
|
<widget class="QWidget" name="tab_log">
|
||||||
|
@ -633,7 +709,23 @@
|
||||||
</property>
|
</property>
|
||||||
<addaction name="menu_act_quit"/>
|
<addaction name="menu_act_quit"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
<addaction name="menu_file"/>
|
<addaction name="menu_file"/>
|
||||||
|
=======
|
||||||
|
<widget class="QMenu" name="menuWindow">
|
||||||
|
<property name="title">
|
||||||
|
<string>Window</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuStyle">
|
||||||
|
<property name="title">
|
||||||
|
<string>Style</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuStyle"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menu_file"/>
|
||||||
|
<addaction name="menuWindow"/>
|
||||||
|
>>>>>>> Stashed changes
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="bar_status"/>
|
<widget class="QStatusBar" name="bar_status"/>
|
||||||
<action name="menu_act_quit">
|
<action name="menu_act_quit">
|
||||||
|
@ -644,6 +736,19 @@
|
||||||
<string>Ctrl+Q</string>
|
<string>Ctrl+Q</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
=======
|
||||||
|
<action name="actionA">
|
||||||
|
<property name="text">
|
||||||
|
<string>A</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionB">
|
||||||
|
<property name="text">
|
||||||
|
<string>B</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
>>>>>>> Stashed changes
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>rd_comp</tabstop>
|
<tabstop>rd_comp</tabstop>
|
||||||
|
|
|
@ -14,24 +14,13 @@ class Preprocessor(Process):
|
||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.kwargs["callback"] = self.callback
|
self.kwargs["callback"] = self.callback
|
||||||
self.start()
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
while self.is_alive():
|
|
||||||
try:
|
|
||||||
self.state.update(self.queue.get(True, 0.5))
|
|
||||||
yield self.state
|
|
||||||
except queue.Empty:
|
|
||||||
pass
|
|
||||||
while not self.queue.empty():
|
|
||||||
self.state.update(self.queue.get(True, 0.5))
|
|
||||||
yield self.state
|
|
||||||
|
|
||||||
def callback(self, state):
|
def callback(self, state):
|
||||||
self.queue.put({"status": state})
|
self.queue.put({"status": state})
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
_ed_lrr.preprocess(*self.args, **self.kwargs)
|
res = _ed_lrr.preprocess(*self.args, **self.kwargs)
|
||||||
|
self.queue.put({"result": res})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -14,18 +14,6 @@ class Router(Process):
|
||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.kwargs["callback"] = self.callback
|
self.kwargs["callback"] = self.callback
|
||||||
self.start()
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
while self.is_alive():
|
|
||||||
try:
|
|
||||||
self.state.update(self.queue.get(True, 0.5))
|
|
||||||
yield self.state
|
|
||||||
except queue.Empty:
|
|
||||||
pass
|
|
||||||
while not self.queue.empty():
|
|
||||||
self.state.update(self.queue.get(True, 0.5))
|
|
||||||
yield self.state
|
|
||||||
|
|
||||||
def callback(self, state):
|
def callback(self, state):
|
||||||
self.queue.put({"status": state})
|
self.queue.put({"status": state})
|
||||||
|
|
88
rust/Cargo.lock
generated
88
rust/Cargo.lock
generated
|
@ -168,10 +168,19 @@ dependencies = [
|
||||||
"indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"permutohedron 0.2.4 (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)",
|
"pyo3 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
"rstar 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rstar 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.40 (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)",
|
"sha3 0.8.2 (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.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.39 (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)",
|
||||||
|
"structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -205,6 +214,19 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ghost"
|
name = "ghost"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
|
=======
|
||||||
|
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.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.1"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -294,7 +316,11 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
=======
|
||||||
|
"proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -302,7 +328,11 @@ name = "mashup-impl"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
=======
|
||||||
|
"proc-macro-hack 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -377,15 +407,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
=======
|
||||||
|
version = "0.4.2"
|
||||||
|
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)",
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack-impl"
|
name = "proc-macro-hack-impl"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
=======
|
||||||
|
version = "0.4.2"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -592,7 +633,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rstar"
|
name = "rstar"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -679,6 +720,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
|
=======
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt"
|
||||||
|
version = "0.2.18"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -748,6 +807,11 @@ name = "version_check"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -792,6 +856,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
"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 ghost 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5297b71943dc9fea26a3241b178c140ee215798b7f79f7773fd61683e25bca74"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
|
=======
|
||||||
|
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
"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 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 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21df85981fe094480bc2267723d3dc0fd1ae0d1f136affc659b7398be615d922"
|
||||||
|
@ -813,8 +881,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c"
|
"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c"
|
||||||
"checksum pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27"
|
"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 permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
|
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
|
||||||
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
|
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
|
||||||
|
=======
|
||||||
|
"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"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
"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 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 pyo3-derive-backend 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d7ae8ab3017515cd7c82d88ce49b55e12a56c602dc69993e123da45c91b186"
|
||||||
|
@ -837,7 +910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd"
|
"checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd"
|
||||||
"checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86"
|
"checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86"
|
||||||
"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48"
|
"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48"
|
||||||
"checksum rstar 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd08ae4f9661517777346592956ea6cdbba2895a28037af7daa600382f4b4001"
|
"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 rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
"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 scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||||
|
@ -849,6 +922,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
|
"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 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.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
|
=======
|
||||||
|
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6"
|
||||||
|
"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7"
|
||||||
|
"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
|
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
|
||||||
"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330"
|
"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330"
|
||||||
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
||||||
|
@ -858,6 +938,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
"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 unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde"
|
"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde"
|
||||||
|
<<<<<<< Updated upstream:rust/Cargo.lock
|
||||||
|
=======
|
||||||
|
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||||
|
>>>>>>> Stashed changes:Cargo.lock
|
||||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
"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 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-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
|
@ -11,12 +11,12 @@ license = "WTFPL"
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug=true
|
#debug=true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
csv = "1.1.1"
|
csv = "1.1.1"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
rstar = "0.4.0"
|
rstar = "0.5.0"
|
||||||
humantime = "1.2.0"
|
humantime = "1.2.0"
|
||||||
permutohedron = "0.2.4"
|
permutohedron = "0.2.4"
|
||||||
serde_json = "1.0.40"
|
serde_json = "1.0.40"
|
||||||
|
@ -25,6 +25,7 @@ fnv = "1.0.6"
|
||||||
bincode = "1.1.4"
|
bincode = "1.1.4"
|
||||||
sha3 = "0.8.2"
|
sha3 = "0.8.2"
|
||||||
byteorder = "1.3.2"
|
byteorder = "1.3.2"
|
||||||
|
strsim = "0.9.2"
|
||||||
|
|
||||||
[dependencies.pyo3]
|
[dependencies.pyo3]
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
|
@ -27,6 +27,7 @@ impl SystemSerde {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct System {
|
pub struct System {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
|
@ -37,3 +38,16 @@ pub struct System {
|
||||||
pub distance: u32,
|
pub distance: u32,
|
||||||
pub pos: [f32; 3],
|
pub pos: [f32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ord for System {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
return self.id.cmp(&other.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for System {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
return Some(self.cmp(other));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
186
rust/src/lib.rs
186
rust/src/lib.rs
|
@ -1,14 +1,43 @@
|
||||||
|
extern crate strsim;
|
||||||
mod common;
|
mod common;
|
||||||
mod preprocess;
|
mod preprocess;
|
||||||
mod route;
|
mod route;
|
||||||
use pyo3::prelude::*;
|
use std::collections::HashMap;
|
||||||
use pyo3::types::{PyDict,PyList};
|
|
||||||
use pyo3::exceptions::*;
|
use pyo3::exceptions::*;
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::types::{PyDict, PyList};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use common::{System,SystemSerde};
|
||||||
|
|
||||||
|
fn find_matches(path:&PathBuf,names:Vec<String>) -> Result<HashMap<String,(f64,Option<System>)>,String> {
|
||||||
|
let mut best: HashMap<String,(f64,Option<System>)> = HashMap::new();
|
||||||
|
for name in &names {
|
||||||
|
best.insert(name.to_string(),(0.0,None));
|
||||||
|
};
|
||||||
|
let mut reader = match csv::ReaderBuilder::new().from_path(path) {
|
||||||
|
Ok(rdr) => rdr,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e).to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let systems=reader
|
||||||
|
.deserialize::<SystemSerde>();
|
||||||
|
for sys in systems {
|
||||||
|
let sys=sys.unwrap();
|
||||||
|
for name in &names {
|
||||||
|
best.entry(name.clone()).and_modify(|ent| {
|
||||||
|
let d1=strsim::normalized_levenshtein(&sys.system,&name);
|
||||||
|
if d1>ent.0 {
|
||||||
|
*ent=(d1,Some(sys.build()))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(best);
|
||||||
|
}
|
||||||
|
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
|
pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
/// preprocess(infile_systems, infile_bodies, outfile, callback)
|
/// preprocess(infile_systems, infile_bodies, outfile, callback)
|
||||||
/// --
|
/// --
|
||||||
///
|
///
|
||||||
|
@ -24,108 +53,139 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
use preprocess::*;
|
use preprocess::*;
|
||||||
let state = PyDict::new(py);
|
let state = PyDict::new(py);
|
||||||
let state_dict = PyDict::new(py);
|
let state_dict = PyDict::new(py);
|
||||||
callback.call(py,(state_dict,),None).unwrap();
|
callback.call(py, (state_dict,), None).unwrap();
|
||||||
let callback_wrapped = move |state: &PreprocessState| {
|
let callback_wrapped = move |state: &PreprocessState| {
|
||||||
// println!("SEND: {:?}",state);
|
// println!("SEND: {:?}",state);
|
||||||
state_dict.set_item("file",state.file.clone())?;
|
state_dict.set_item("file", state.file.clone())?;
|
||||||
state_dict.set_item("total",state.total)?;
|
state_dict.set_item("total", state.total)?;
|
||||||
state_dict.set_item("done",state.done)?;
|
state_dict.set_item("count", state.count)?;
|
||||||
callback.call(py,(state_dict,),None)
|
state_dict.set_item("done", state.done)?;
|
||||||
|
state_dict.set_item("message", state.message.clone())?;
|
||||||
|
callback.call(py, (state_dict,), None)
|
||||||
};
|
};
|
||||||
preprocess_files(&PathBuf::from(infile_bodies), &PathBuf::from(infile_systems), &PathBuf::from(outfile), Box::new(callback_wrapped)).unwrap();
|
preprocess_files(
|
||||||
return Ok(state.to_object(py));
|
&PathBuf::from(infile_bodies),
|
||||||
|
&PathBuf::from(infile_systems),
|
||||||
|
&PathBuf::from(outfile),
|
||||||
|
Box::new(callback_wrapped),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
Ok(state.to_object(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// route(infile, hops, range, mode,primary, greedyness, precomp, callback)
|
///find_sys(sys_names,sys_list)
|
||||||
|
/// --
|
||||||
|
///
|
||||||
|
/// Find system by name
|
||||||
|
#[pyfn(m, "find_sys")]
|
||||||
|
fn find_sys(py:Python,sys_names:Vec<String>,sys_list:String) -> PyResult<PyObject> {
|
||||||
|
let path=PathBuf::from(sys_list);
|
||||||
|
match find_matches(&path,sys_names) {
|
||||||
|
Ok(vals) => {
|
||||||
|
let ret=PyDict::new(py);
|
||||||
|
for (key,(diff,sys)) in vals {
|
||||||
|
let ret_dict=PyDict::new(py);
|
||||||
|
if let Some(val)= sys {
|
||||||
|
let pos = PyList::new(py, val.pos.iter());
|
||||||
|
ret_dict.set_item("star_type", val.star_type.clone())?;
|
||||||
|
ret_dict.set_item("system", val.system.clone())?;
|
||||||
|
ret_dict.set_item("body", val.body.clone())?;
|
||||||
|
ret_dict.set_item("distance", val.distance)?;
|
||||||
|
ret_dict.set_item("pos", pos)?;
|
||||||
|
ret_dict.set_item("id", val.id)?;
|
||||||
|
ret.set_item(key,(diff,ret_dict).to_object(py))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(ret.to_object(py));
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
return Err(PyErr::new::<ValueError, _>(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// route(infile, hops, range, radius_mult, mode,primary, greedyness, precomp, callback)
|
||||||
/// --
|
/// --
|
||||||
///
|
///
|
||||||
/// Compute a Route using the suplied parameters
|
/// Compute a Route using the suplied parameters
|
||||||
#[pyfn(m, "route")]
|
#[pyfn(m, "route")]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn route(
|
fn route(
|
||||||
py: Python<'static>,
|
py: Python<'static>,
|
||||||
hops: Vec<String>,
|
hops: Vec<String>,
|
||||||
range: f32,
|
range: f32,
|
||||||
|
radius_mult: f32,
|
||||||
mode: String,
|
mode: String,
|
||||||
primary: bool,
|
primary: bool,
|
||||||
permute: bool,
|
permute: bool,
|
||||||
|
keep_first: bool,
|
||||||
|
keep_last: bool,
|
||||||
greedyness: Option<f32>,
|
greedyness: Option<f32>,
|
||||||
precomp: Option<String>,
|
precomp: Option<String>,
|
||||||
path: String,
|
path: String,
|
||||||
callback: PyObject,
|
callback: PyObject,
|
||||||
) -> PyResult<PyObject> {
|
) -> PyResult<PyObject> {
|
||||||
use route::*;
|
use route::*;
|
||||||
// TODO: Verify Parameters
|
|
||||||
let mode = match Mode::parse(&mode) {
|
let mode = match Mode::parse(&mode) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(PyErr::new::<ValueError,_>(e));
|
return Err(PyErr::new::<ValueError, _>(e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let state_dict = PyDict::new(py);
|
let state_dict = PyDict::new(py);
|
||||||
callback.call(py,(state_dict,),None).unwrap();
|
callback.call(py, (state_dict,), None).unwrap();
|
||||||
let callback_wrapped = move |state: &SearchState| {
|
let callback_wrapped = move |state: &SearchState| {
|
||||||
println!("SEND: {:?}",state);
|
state_dict.set_item("mode", state.mode.clone())?;
|
||||||
state_dict.set_item("mode",state.mode.clone())?;
|
state_dict.set_item("system", state.system.clone())?;
|
||||||
state_dict.set_item("system",state.system.clone())?;
|
state_dict.set_item("body", state.body.clone())?;
|
||||||
state_dict.set_item("body",state.body.clone())?;
|
state_dict.set_item("depth", state.depth)?;
|
||||||
state_dict.set_item("depth",state.depth)?;
|
state_dict.set_item("queue_size", state.queue_size)?;
|
||||||
state_dict.set_item("queue_size",state.queue_size)?;
|
state_dict.set_item("d_rem", state.d_rem)?;
|
||||||
state_dict.set_item("d_rem",state.d_rem)?;
|
state_dict.set_item("d_total", state.d_total)?;
|
||||||
state_dict.set_item("d_total",state.d_total)?;
|
state_dict.set_item("prc_done", state.prc_done)?;
|
||||||
state_dict.set_item("prc_done",state.prc_done)?;
|
state_dict.set_item("n_seen", state.n_seen)?;
|
||||||
state_dict.set_item("n_seen",state.n_seen)?;
|
state_dict.set_item("prc_seen", state.prc_seen)?;
|
||||||
state_dict.set_item("prc_seen",state.prc_seen)?;
|
callback.call(py, (state_dict,), None)
|
||||||
callback.call(py,(state_dict,),None)
|
|
||||||
};
|
};
|
||||||
let opts=RouteOpts{
|
let mut systems=Vec::new();
|
||||||
systems:hops,
|
for sys in hops {
|
||||||
range:Some(range),
|
systems.push(route::SysEntry::parse(&sys))
|
||||||
|
}
|
||||||
|
println!("SYSTEMS: {:?}",systems);
|
||||||
|
let opts = RouteOpts {
|
||||||
|
systems,
|
||||||
|
range: Some(range),
|
||||||
file_path: PathBuf::from(path),
|
file_path: PathBuf::from(path),
|
||||||
precomp_file: precomp.map(PathBuf::from),
|
precomp_file: precomp.map(PathBuf::from),
|
||||||
callback: Box::new(callback_wrapped),
|
callback: Box::new(callback_wrapped),
|
||||||
mode,
|
mode,
|
||||||
factor: greedyness,
|
factor: greedyness,
|
||||||
precompute: false,
|
precompute: false,
|
||||||
permute: permute,
|
permute,
|
||||||
keep_first: true,
|
keep_first,
|
||||||
keep_last: true,
|
keep_last,
|
||||||
primary
|
primary,
|
||||||
|
radius_mult
|
||||||
};
|
};
|
||||||
let none=().to_object(py);
|
let none = ().to_object(py);
|
||||||
match route(opts) {
|
match route(opts) {
|
||||||
Ok(Some(route)) => {
|
Ok(Some(route)) => {
|
||||||
let hops=route.iter().map(|hop| {
|
let hops = route.iter().map(|hop| {
|
||||||
let pos=PyList::new(py,hop.pos.iter());
|
let pos = PyList::new(py, hop.pos.iter());
|
||||||
let elem=PyDict::new(py);
|
let elem = PyDict::new(py);
|
||||||
elem.set_item("star_type",hop.star_type.clone()).unwrap();
|
elem.set_item("star_type", hop.star_type.clone()).unwrap();
|
||||||
elem.set_item("system",hop.system.clone()).unwrap();
|
elem.set_item("system", hop.system.clone()).unwrap();
|
||||||
elem.set_item("body",hop.body.clone()).unwrap();
|
elem.set_item("body", hop.body.clone()).unwrap();
|
||||||
elem.set_item("distance",hop.distance).unwrap();
|
elem.set_item("distance", hop.distance).unwrap();
|
||||||
elem.set_item("pos",pos).unwrap();
|
elem.set_item("pos", pos).unwrap();
|
||||||
return elem;
|
elem
|
||||||
});
|
});
|
||||||
let lst=PyList::new(py,hops);
|
let lst = PyList::new(py, hops);
|
||||||
return Ok(lst.to_object(py));
|
Ok(lst.to_object(py))
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => Ok(none),
|
||||||
return Ok(none);
|
Err(e) => Err(PyErr::new::<ValueError, _>(e)),
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
return Err(PyErr::new::<ValueError,_>(e));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
/*
|
|
||||||
let state = PyDict::new(py);
|
|
||||||
state.set_item("infile", infile)?;
|
|
||||||
state.set_item("source", source)?;
|
|
||||||
state.set_item("dest", dest)?;
|
|
||||||
state.set_item("range", range)?;
|
|
||||||
state.set_item("mode", mode)?;
|
|
||||||
state.set_item("greedyness", greedyness)?;
|
|
||||||
state.set_item("precomp", precomp)?;
|
|
||||||
state.set_item("callback", callback)?;
|
|
||||||
return callback.call(py,(state.to_object(py),),None);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
use crate::common::{System, SystemSerde};
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use csv::StringRecord;
|
use csv::StringRecord;
|
||||||
use fnv::{FnvHashMap, FnvHashSet};
|
use fnv::{FnvHashMap, FnvHashSet};
|
||||||
use humantime::format_duration;
|
use humantime::format_duration;
|
||||||
use permutohedron::LexicalPermutation;
|
use permutohedron::LexicalPermutation;
|
||||||
|
use pyo3::prelude::*;
|
||||||
use rstar::{PointDistance, RTree, RTreeObject, AABB};
|
use rstar::{PointDistance, RTree, RTreeObject, AABB};
|
||||||
use sha3::{Digest, Sha3_256};
|
use sha3::{Digest, Sha3_256};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -12,8 +14,6 @@ use std::io::Seek;
|
||||||
use std::io::{BufRead, BufReader, BufWriter, Write};
|
use std::io::{BufRead, BufReader, BufWriter, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use pyo3::prelude::*;
|
|
||||||
use crate::common::{System, SystemSerde};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SearchState {
|
pub struct SearchState {
|
||||||
|
@ -26,9 +26,23 @@ pub struct SearchState {
|
||||||
pub d_total: f32,
|
pub d_total: f32,
|
||||||
pub prc_done: f32,
|
pub prc_done: f32,
|
||||||
pub n_seen: usize,
|
pub n_seen: usize,
|
||||||
pub prc_seen: f32
|
pub prc_seen: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum SysEntry {
|
||||||
|
ID(u32),
|
||||||
|
Name(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysEntry {
|
||||||
|
pub fn parse(s: &str) -> SysEntry {
|
||||||
|
match s.parse() {
|
||||||
|
Ok(n) => SysEntry::ID(n),
|
||||||
|
_ => SysEntry::Name(s.to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RouteOpts {
|
pub struct RouteOpts {
|
||||||
pub range: Option<f32>,
|
pub range: Option<f32>,
|
||||||
|
@ -41,8 +55,9 @@ pub struct RouteOpts {
|
||||||
pub keep_last: bool,
|
pub keep_last: bool,
|
||||||
pub factor: Option<f32>,
|
pub factor: Option<f32>,
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub systems: Vec<String>,
|
pub radius_mult: f32,
|
||||||
pub callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>
|
pub systems: Vec<SysEntry>,
|
||||||
|
pub callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -54,7 +69,7 @@ pub enum Mode {
|
||||||
|
|
||||||
impl Mode {
|
impl Mode {
|
||||||
pub fn parse(s: &str) -> Result<Mode, String> {
|
pub fn parse(s: &str) -> Result<Mode, String> {
|
||||||
let s=s.to_lowercase();
|
let s = s.to_lowercase();
|
||||||
match s.as_ref() {
|
match s.as_ref() {
|
||||||
"bfs" => Ok(Mode::BFS),
|
"bfs" => Ok(Mode::BFS),
|
||||||
"greedy" => Ok(Mode::Greedy),
|
"greedy" => Ok(Mode::Greedy),
|
||||||
|
@ -160,8 +175,8 @@ impl LineCache {
|
||||||
}
|
}
|
||||||
pub fn get(&mut self, id: u32) -> Option<System> {
|
pub fn get(&mut self, id: u32) -> Option<System> {
|
||||||
let pos = self.cache[id as usize];
|
let pos = self.cache[id as usize];
|
||||||
self.file.seek(std::io::SeekFrom::Start(pos)).unwrap();
|
self.file.seek(std::io::SeekFrom::Start(pos)).ok()?;
|
||||||
let rec = Self::read_record(&mut self.file).unwrap();
|
let rec = Self::read_record(&mut self.file)?;
|
||||||
let sys: SystemSerde = rec.deserialize(self.header.as_ref()).unwrap();
|
let sys: SystemSerde = rec.deserialize(self.header.as_ref()).unwrap();
|
||||||
Some(sys.build())
|
Some(sys.build())
|
||||||
}
|
}
|
||||||
|
@ -175,18 +190,26 @@ pub struct Router {
|
||||||
range: f32,
|
range: f32,
|
||||||
primary_only: bool,
|
primary_only: bool,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>
|
radius_mult: f32,
|
||||||
|
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Router {
|
impl Router {
|
||||||
pub fn new(path: &PathBuf, range: f32, primary_only: bool,callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>) -> Result<Self,String> {
|
pub fn new(
|
||||||
|
path: &PathBuf,
|
||||||
|
range: f32,
|
||||||
|
radius_mult: f32,
|
||||||
|
primary_only: bool,
|
||||||
|
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
|
) -> Result<Self, String> {
|
||||||
let mut scoopable = FnvHashSet::default();
|
let mut scoopable = FnvHashSet::default();
|
||||||
let mut reader = match csv::ReaderBuilder::new().from_path(path) {
|
let mut reader = match csv::ReaderBuilder::new().from_path(path) {
|
||||||
Ok(rdr) => rdr,
|
Ok(rdr) => rdr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e).to_string());
|
return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let t_load = Instant::now();
|
||||||
println!("Loading {}...", path.to_str().unwrap());
|
println!("Loading {}...", path.to_str().unwrap());
|
||||||
let systems: Vec<System> = reader
|
let systems: Vec<System> = reader
|
||||||
.deserialize::<SystemSerde>()
|
.deserialize::<SystemSerde>()
|
||||||
|
@ -220,25 +243,54 @@ impl Router {
|
||||||
primary_only,
|
primary_only,
|
||||||
cache: LineCache::new(path),
|
cache: LineCache::new(path),
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
callback: callback,
|
callback,
|
||||||
|
radius_mult,
|
||||||
};
|
};
|
||||||
|
println!(
|
||||||
|
"{} Systems loaded in {}",
|
||||||
|
ret.tree.size(),
|
||||||
|
format_duration(t_load.elapsed())
|
||||||
|
);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_file(filename: &PathBuf,callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>) -> Result<(PathBuf, Self),String> {
|
pub fn from_file(
|
||||||
let mut reader = BufReader::new(File::open(&filename).unwrap());
|
filename: &PathBuf,
|
||||||
|
callback: Box<dyn Fn(&SearchState) -> PyResult<PyObject>>,
|
||||||
|
) -> Result<(PathBuf, Self), String> {
|
||||||
|
let t_load = Instant::now();
|
||||||
|
let mut reader = BufReader::new(match File::open(&filename) {
|
||||||
|
Ok(fh) => fh,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(format!(
|
||||||
|
"Error opening file {}: {}",
|
||||||
|
filename.to_str().unwrap(),
|
||||||
|
e
|
||||||
|
))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
println!("Loading {}", filename.to_str().unwrap());
|
||||||
let (primary, range, file_hash, path, route_tree): (
|
let (primary, range, file_hash, path, route_tree): (
|
||||||
bool,
|
bool,
|
||||||
f32,
|
f32,
|
||||||
Vec<u8>,
|
Vec<u8>,
|
||||||
String,
|
String,
|
||||||
FnvHashMap<u32, u32>,
|
FnvHashMap<u32, u32>,
|
||||||
) = bincode::deserialize_from(&mut reader).unwrap();
|
) = match bincode::deserialize_from(&mut reader) {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(format!(
|
||||||
|
"Error loading file {}: {}",
|
||||||
|
filename.to_str().unwrap(),
|
||||||
|
e
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
if hash_file(&path) != file_hash {
|
if hash_file(&path) != file_hash {
|
||||||
return Err("File hash mismatch!".to_string());
|
return Err("File hash mismatch!".to_string());
|
||||||
}
|
}
|
||||||
let cache = LineCache::new(&path);
|
let cache = LineCache::new(&path).ok();
|
||||||
Ok((
|
Ok((
|
||||||
path.clone(),
|
path.clone(),
|
||||||
Self {
|
Self {
|
||||||
|
@ -249,14 +301,12 @@ impl Router {
|
||||||
cache,
|
cache,
|
||||||
primary_only: primary,
|
primary_only: primary,
|
||||||
path,
|
path,
|
||||||
callback
|
callback,
|
||||||
|
radius_mult: 0f32,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn closest(&self, point: &[f32; 3]) -> &System {
|
|
||||||
self.tree.nearest_neighbor(point).unwrap()
|
|
||||||
}
|
|
||||||
fn points_in_sphere(&self, center: &[f32; 3], radius: f32) -> impl Iterator<Item = &System> {
|
fn points_in_sphere(&self, center: &[f32; 3], radius: f32) -> impl Iterator<Item = &System> {
|
||||||
self.tree.locate_within_distance(*center, radius * radius)
|
self.tree.locate_within_distance(*center, radius * radius)
|
||||||
}
|
}
|
||||||
|
@ -265,18 +315,23 @@ impl Router {
|
||||||
self.points_in_sphere(&sys.pos, sys.mult * r)
|
self.points_in_sphere(&sys.pos, sys.mult * r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn valid(&self, sys: &System) -> bool {
|
fn valid(&self, sys: &System, src: &System, dst: &System) -> bool {
|
||||||
self.scoopable.contains(&sys.id)
|
let scoopable = self.scoopable.contains(&sys.id);
|
||||||
|
if self.radius_mult == 0.0 {
|
||||||
|
return scoopable;
|
||||||
|
}
|
||||||
|
let df = src.distp(dst);
|
||||||
|
return (sys.distp(src) + sys.distp(dst)) < (df * (1.0 + self.radius_mult));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn best_name_multiroute(
|
pub fn best_multiroute(
|
||||||
&self,
|
&self,
|
||||||
waypoints: &[String],
|
waypoints: &Vec<System>,
|
||||||
range: f32,
|
range: f32,
|
||||||
keep: (bool,bool),
|
keep: (bool, bool),
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
factor: f32,
|
factor: f32,
|
||||||
) -> Result<Vec<System>,String> {
|
) -> Result<Vec<System>, String> {
|
||||||
let mut best_score: f32 = std::f32::MAX;
|
let mut best_score: f32 = std::f32::MAX;
|
||||||
let mut waypoints = waypoints.to_owned();
|
let mut waypoints = waypoints.to_owned();
|
||||||
let mut best_permutation_waypoints = waypoints.to_owned();
|
let mut best_permutation_waypoints = waypoints.to_owned();
|
||||||
|
@ -287,17 +342,12 @@ impl Router {
|
||||||
loop {
|
loop {
|
||||||
let c_first = waypoints.first().cloned();
|
let c_first = waypoints.first().cloned();
|
||||||
let c_last = waypoints.last().cloned();
|
let c_last = waypoints.last().cloned();
|
||||||
let valid = (keep.0 && (c_first == first)) && (keep.1 && (c_last==last));
|
let valid = (keep.0 && (c_first == first)) && (keep.1 && (c_last == last));
|
||||||
if valid {
|
if valid {
|
||||||
let mut total_d = 0.0;
|
let mut total_d = 0.0;
|
||||||
for pair in waypoints.windows(2) {
|
for pair in waypoints.windows(2) {
|
||||||
match pair {
|
match pair {
|
||||||
[src, dst] => {
|
[src, dst] => {
|
||||||
let (mut src, dst) =
|
|
||||||
(self.name_to_systems(&src)?, self.name_to_systems(&dst)?);
|
|
||||||
src.sort_by_key(|&p| (p.mult * 10.0) as u8);
|
|
||||||
let src = src.last().unwrap();
|
|
||||||
let dst = dst.last().unwrap();
|
|
||||||
total_d += src.distp2(dst);
|
total_d += src.distp2(dst);
|
||||||
}
|
}
|
||||||
_ => return Err("Invalid routing parameters!".to_string()),
|
_ => return Err("Invalid routing parameters!".to_string()),
|
||||||
|
@ -313,35 +363,19 @@ impl Router {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("Best permutation: {:?}", best_permutation_waypoints);
|
println!("Best permutation: {:?}", best_permutation_waypoints);
|
||||||
self.name_multiroute(&best_permutation_waypoints, range, mode, factor)
|
self.multiroute(&best_permutation_waypoints, range, mode, factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_multiroute(
|
|
||||||
&self,
|
|
||||||
waypoints: &[String],
|
|
||||||
range: f32,
|
|
||||||
mode: Mode,
|
|
||||||
factor: f32,
|
|
||||||
) -> Result<Vec<System>,String> {
|
|
||||||
let mut coords = Vec::new();
|
|
||||||
for p_name in waypoints {
|
|
||||||
let mut p_l = self.name_to_systems(p_name)?;
|
|
||||||
p_l.sort_by_key(|&p| (p.mult * 10.0) as u8);
|
|
||||||
let p = p_l.last().unwrap();
|
|
||||||
coords.push((p_name, p.pos));
|
|
||||||
}
|
|
||||||
self.multiroute(coords.as_slice(), range, mode, factor)
|
|
||||||
}
|
|
||||||
pub fn multiroute(
|
pub fn multiroute(
|
||||||
&self,
|
&self,
|
||||||
waypoints: &[(&String, [f32; 3])],
|
waypoints: &Vec<System>,
|
||||||
range: f32,
|
range: f32,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
factor: f32,
|
factor: f32,
|
||||||
) -> Result<Vec<System>,String> {
|
) -> Result<Vec<System>, String> {
|
||||||
let mut route: Vec<System> = Vec::new();
|
let mut route: Vec<System> = Vec::new();
|
||||||
for pair in waypoints.windows(2) {
|
for pair in waypoints.windows(2) {
|
||||||
match *pair {
|
match pair.clone() {
|
||||||
[src, dst] => {
|
[src, dst] => {
|
||||||
let block = match mode {
|
let block = match mode {
|
||||||
Mode::BFS => self.route_bfs(&src, &dst, range)?,
|
Mode::BFS => self.route_bfs(&src, &dst, range)?,
|
||||||
|
@ -358,56 +392,88 @@ impl Router {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err("Invalid routing parameters!".to_string()),
|
_ => {
|
||||||
|
return Err("Invalid routing parameters!".to_owned());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(route)
|
Ok(route)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_to_systems(&self, name: &str) -> Result<Vec<&System>,String> {
|
fn resolve_systems(&self, systems: &[SysEntry]) -> Result<Vec<System>, String> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
let mut sys_by_id: FnvHashMap<u32, &System> = FnvHashMap::default();
|
||||||
|
let mut sys_by_name: FnvHashMap<String, &System> = FnvHashMap::default();
|
||||||
for sys in &self.tree {
|
for sys in &self.tree {
|
||||||
if sys.system == name {
|
for ent in systems {
|
||||||
return Ok(self.neighbours(&sys, 0.0).collect());
|
match ent {
|
||||||
|
SysEntry::ID(i) => {
|
||||||
|
let i = *i;
|
||||||
|
if sys.id == i {
|
||||||
|
sys_by_id.insert(i, sys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(format!("System not found: \"{}\"", name))
|
SysEntry::Name(n) => {
|
||||||
|
if &sys.body == n || &sys.system == n {
|
||||||
|
sys_by_name.insert(n.to_string(), sys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ent in systems {
|
||||||
|
match ent {
|
||||||
|
SysEntry::ID(i) => match sys_by_id.get(i) {
|
||||||
|
Some(sys) => ret.push(sys.clone().clone()),
|
||||||
|
None => {
|
||||||
|
return Err(format!("System: {:?} not found", ent));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SysEntry::Name(n) => match sys_by_name.get(n) {
|
||||||
|
Some(sys) => ret.push(sys.clone().clone()),
|
||||||
|
None => {
|
||||||
|
return Err(format!("System: {:?} not found", ent));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route_astar(
|
pub fn route_astar(
|
||||||
&self,
|
&self,
|
||||||
src: &(&String, [f32; 3]),
|
src: &System,
|
||||||
dst: &(&String, [f32; 3]),
|
dst: &System,
|
||||||
range: f32,
|
range: f32,
|
||||||
factor: f32,
|
factor: f32,
|
||||||
) -> Result<Vec<System>,String> {
|
) -> Result<Vec<System>, String> {
|
||||||
if factor == 0.0 {
|
if factor == 0.0 {
|
||||||
return self.route_bfs(src, dst, range);
|
return self.route_bfs(src, dst, range);
|
||||||
}
|
}
|
||||||
let (src_name, src) = src;
|
let src_name = src.system.clone();
|
||||||
let (dst_name, dst) = dst;
|
let dst_name = dst.system.clone();
|
||||||
let start_sys = self.closest(src);
|
let start_sys = src;
|
||||||
let goal_sys = self.closest(dst);
|
let goal_sys = dst;
|
||||||
let d_total = dist(&start_sys.pos,&goal_sys.pos);
|
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
||||||
let mut d_rem=d_total;
|
let mut d_rem = d_total;
|
||||||
|
|
||||||
let mut state=SearchState {
|
let mut state = SearchState {
|
||||||
mode:"A-Star".into(),
|
mode: "A-Star".into(),
|
||||||
depth:0,
|
depth: 0,
|
||||||
queue_size:0,
|
queue_size: 0,
|
||||||
d_rem: d_total,
|
d_rem: d_total,
|
||||||
d_total: d_total,
|
d_total,
|
||||||
prc_done: 0.0,
|
prc_done: 0.0,
|
||||||
n_seen:0,
|
n_seen: 0,
|
||||||
prc_seen: 0.0,
|
prc_seen: 0.0,
|
||||||
body: start_sys.body.clone(),
|
body: start_sys.body.clone(),
|
||||||
system: start_sys.system.clone()
|
system: start_sys.system.clone(),
|
||||||
};
|
};
|
||||||
let total = self.tree.size() as f32;
|
let total = self.tree.size() as f32;
|
||||||
let t_start = Instant::now();
|
let mut t_last = Instant::now();
|
||||||
let mut prev = FnvHashMap::default();
|
let mut prev = FnvHashMap::default();
|
||||||
let mut seen = FnvHashSet::default();
|
let mut seen = FnvHashSet::default();
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
let mut maxd = 0;
|
|
||||||
let mut queue: Vec<(usize, usize, &System)> = Vec::new();
|
let mut queue: Vec<(usize, usize, &System)> = Vec::new();
|
||||||
queue.push((
|
queue.push((
|
||||||
0, // depth
|
0, // depth
|
||||||
|
@ -417,31 +483,22 @@ impl Router {
|
||||||
seen.insert(start_sys.id);
|
seen.insert(start_sys.id);
|
||||||
while !(queue.is_empty() || found) {
|
while !(queue.is_empty() || found) {
|
||||||
while let Some((depth, _, sys)) = queue.pop() {
|
while let Some((depth, _, sys)) = queue.pop() {
|
||||||
if (depth+1) > maxd {
|
if t_last.elapsed().as_millis() > 100 {
|
||||||
maxd = depth+1;
|
t_last = Instant::now();
|
||||||
state.depth=depth;
|
state.depth = depth;
|
||||||
state.queue_size=queue.len();
|
state.queue_size = queue.len();
|
||||||
state.prc_done=((d_total-d_rem)*100f32) / d_total;
|
state.prc_done = ((d_total - d_rem) * 100f32) / d_total;
|
||||||
state.d_rem=d_rem;
|
state.d_rem = d_rem;
|
||||||
state.n_seen=seen.len();
|
state.n_seen = seen.len();
|
||||||
state.prc_seen=((seen.len()*100) as f32) / total;
|
state.prc_seen = ((seen.len() * 100) as f32) / total;
|
||||||
state.body=sys.body.clone();
|
state.body = sys.body.clone();
|
||||||
state.system=sys.system.clone();
|
state.system = sys.system.clone();
|
||||||
match (self.callback)(&state) {
|
match (self.callback)(&state) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format!("{:?}",e).to_string());
|
return Err(format!("{:?}", e).to_string());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
print!(
|
|
||||||
"[{}] Depth: {}, Queue: {}, Seen: {} ({:.02}%) \r",
|
|
||||||
format_duration(t_start.elapsed()),
|
|
||||||
depth,
|
|
||||||
queue.len(),
|
|
||||||
seen.len(),
|
|
||||||
((seen.len() * 100) as f32) / total
|
|
||||||
);
|
|
||||||
std::io::stdout().flush().unwrap();
|
|
||||||
}
|
}
|
||||||
if sys.id == goal_sys.id {
|
if sys.id == goal_sys.id {
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -449,16 +506,15 @@ impl Router {
|
||||||
}
|
}
|
||||||
queue.extend(
|
queue.extend(
|
||||||
self.neighbours(&sys, range)
|
self.neighbours(&sys, range)
|
||||||
.filter(|&nb| (self.valid(nb) || (nb.id == goal_sys.id)))
|
.filter(|&nb| (self.valid(nb, &src, &dst) || (nb.id == goal_sys.id)))
|
||||||
.filter(|&nb| seen.insert(nb.id))
|
.filter(|&nb| seen.insert(nb.id))
|
||||||
.map(|nb| {
|
.map(|nb| {
|
||||||
prev.insert(nb.id, sys);
|
prev.insert(nb.id, sys);
|
||||||
let d_g = (nb.distp(goal_sys) / range) as usize;
|
let d_g=nb.distp(goal_sys);
|
||||||
let dist = dist(&nb.pos, &goal_sys.pos);
|
if d_g<d_rem {
|
||||||
if dist < d_rem {
|
d_rem=d_g;
|
||||||
d_rem = dist;
|
|
||||||
}
|
}
|
||||||
(depth + 1, d_g, nb)
|
(depth + 1, (d_g / range) as usize, nb)
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
queue.sort_by(|b, a| {
|
queue.sort_by(|b, a| {
|
||||||
|
@ -475,7 +531,7 @@ impl Router {
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
if !found {
|
if !found {
|
||||||
return Err(format!("No route from {} to {} found!", src_name, dst_name).to_string());
|
return Err(format!("No route from {} to {} found!", src_name, dst_name));
|
||||||
}
|
}
|
||||||
let mut v: Vec<System> = Vec::new();
|
let mut v: Vec<System> = Vec::new();
|
||||||
let mut curr_sys = goal_sys;
|
let mut curr_sys = goal_sys;
|
||||||
|
@ -494,54 +550,54 @@ impl Router {
|
||||||
|
|
||||||
pub fn route_greedy(
|
pub fn route_greedy(
|
||||||
&self,
|
&self,
|
||||||
src: &(&String, [f32; 3]),
|
src: &System,
|
||||||
dst: &(&String, [f32; 3]),
|
dst: &System,
|
||||||
range: f32,
|
range: f32,
|
||||||
) -> Result<Vec<System>,String> {
|
) -> Result<Vec<System>, String> {
|
||||||
let (src_name, src) = src;
|
let src_name = src.system.clone();
|
||||||
let (dst_name, dst) = dst;
|
let dst_name = dst.system.clone();
|
||||||
let start_sys = self.closest(src);
|
let start_sys = src;
|
||||||
let goal_sys = self.closest(dst);
|
let goal_sys = dst;
|
||||||
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
||||||
let mut d_rem=d_total;
|
let mut d_rem = d_total;
|
||||||
let mut state=SearchState {
|
let mut state = SearchState {
|
||||||
mode:"Greedy".into(),
|
mode: "Greedy".into(),
|
||||||
depth:0,
|
depth: 0,
|
||||||
queue_size:0,
|
queue_size: 0,
|
||||||
d_rem: d_total,
|
d_rem: d_total,
|
||||||
d_total: d_total,
|
d_total,
|
||||||
prc_done: 0.0,
|
prc_done: 0.0,
|
||||||
n_seen:0,
|
n_seen: 0,
|
||||||
prc_seen: 0.0,
|
prc_seen: 0.0,
|
||||||
body:start_sys.body.clone(),
|
body: start_sys.body.clone(),
|
||||||
system:start_sys.system.clone(),
|
system: start_sys.system.clone(),
|
||||||
};
|
};
|
||||||
let total = self.tree.size() as f32;
|
let total = self.tree.size() as f32;
|
||||||
|
let mut t_last = Instant::now();
|
||||||
let mut prev = FnvHashMap::default();
|
let mut prev = FnvHashMap::default();
|
||||||
let mut seen = FnvHashSet::default();
|
let mut seen = FnvHashSet::default();
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
let mut maxd = 0;
|
|
||||||
let mut queue: Vec<(f32, f32, usize, &System)> = Vec::new();
|
let mut queue: Vec<(f32, f32, usize, &System)> = Vec::new();
|
||||||
queue.push((-goal_sys.mult, start_sys.distp2(goal_sys), 0, &start_sys));
|
queue.push((-goal_sys.mult, start_sys.distp(goal_sys), 0, &start_sys));
|
||||||
seen.insert(start_sys.id);
|
seen.insert(start_sys.id);
|
||||||
while !(queue.is_empty() || found) {
|
while !(queue.is_empty() || found) {
|
||||||
while let Some((_, _, depth, sys)) = queue.pop() {
|
while let Some((_, _, depth, sys)) = queue.pop() {
|
||||||
if (depth+1) > maxd {
|
if t_last.elapsed().as_millis() > 100 {
|
||||||
state.depth=depth;
|
t_last = Instant::now();
|
||||||
state.queue_size=queue.len();
|
state.depth = depth;
|
||||||
state.prc_done=((d_total-d_rem)*100f32) / d_total;
|
state.queue_size = queue.len();
|
||||||
state.d_rem=d_rem;
|
state.prc_done = ((d_total - d_rem) * 100f32) / d_total;
|
||||||
state.n_seen=seen.len();
|
state.d_rem = d_rem;
|
||||||
state.prc_seen=((seen.len()*100) as f32) / total;
|
state.n_seen = seen.len();
|
||||||
state.body=sys.body.clone();
|
state.prc_seen = ((seen.len() * 100) as f32) / total;
|
||||||
state.system=sys.system.clone();
|
state.body = sys.body.clone();
|
||||||
|
state.system = sys.system.clone();
|
||||||
match (self.callback)(&state) {
|
match (self.callback)(&state) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format!("{:?}",e).to_string());
|
return Err(format!("{:?}", e).to_string());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
maxd = depth+1;
|
|
||||||
}
|
}
|
||||||
if sys.id == goal_sys.id {
|
if sys.id == goal_sys.id {
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -549,15 +605,15 @@ impl Router {
|
||||||
}
|
}
|
||||||
queue.extend(
|
queue.extend(
|
||||||
self.neighbours(&sys, range)
|
self.neighbours(&sys, range)
|
||||||
.filter(|&nb| (self.valid(nb) || (nb.id == goal_sys.id)))
|
.filter(|&nb| (self.valid(nb, &src, &dst) || (nb.id == goal_sys.id)))
|
||||||
.filter(|&nb| seen.insert(nb.id))
|
.filter(|&nb| seen.insert(nb.id))
|
||||||
.map(|nb| {
|
.map(|nb| {
|
||||||
prev.insert(nb.id, sys);
|
prev.insert(nb.id, sys);
|
||||||
let dist = dist(&nb.pos, &goal_sys.pos);
|
let d_g=nb.distp(goal_sys);
|
||||||
if dist < d_rem {
|
if d_g<d_rem {
|
||||||
d_rem = dist;
|
d_rem=d_g;
|
||||||
}
|
}
|
||||||
(-nb.mult, nb.distp2(goal_sys), depth + 1, nb)
|
(-nb.mult, d_g, depth + 1, nb)
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
queue.sort_by(|a, b| fcmp(a.0, b.0).then(fcmp(a.1, b.1)));
|
queue.sort_by(|a, b| fcmp(a.0, b.0).then(fcmp(a.1, b.1)));
|
||||||
|
@ -565,7 +621,7 @@ impl Router {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
return Err(format!("No route from {} to {} found!", src_name, dst_name).to_string());
|
return Err(format!("No route from {} to {} found!", src_name, dst_name));
|
||||||
}
|
}
|
||||||
let mut v: Vec<System> = Vec::new();
|
let mut v: Vec<System> = Vec::new();
|
||||||
let mut curr_sys = goal_sys;
|
let mut curr_sys = goal_sys;
|
||||||
|
@ -582,10 +638,7 @@ impl Router {
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn precompute(&mut self, src: &str) -> Result<(),String> {
|
pub fn precompute(&mut self, src: &System) -> Result<(), String> {
|
||||||
let mut sys_l = self.name_to_systems(src)?;
|
|
||||||
sys_l.sort_by_key(|&sys| (sys.mult * 10.0) as u8);
|
|
||||||
let sys = sys_l.last().unwrap();
|
|
||||||
let total = self.tree.size() as f32;
|
let total = self.tree.size() as f32;
|
||||||
let t_start = Instant::now();
|
let t_start = Instant::now();
|
||||||
let mut prev = FnvHashMap::default();
|
let mut prev = FnvHashMap::default();
|
||||||
|
@ -593,8 +646,8 @@ impl Router {
|
||||||
let mut depth = 0;
|
let mut depth = 0;
|
||||||
let mut queue: VecDeque<(usize, &System)> = VecDeque::new();
|
let mut queue: VecDeque<(usize, &System)> = VecDeque::new();
|
||||||
let mut queue_next: VecDeque<(usize, &System)> = VecDeque::new();
|
let mut queue_next: VecDeque<(usize, &System)> = VecDeque::new();
|
||||||
queue.push_front((0, &sys));
|
queue.push_front((0, &src));
|
||||||
seen.insert(sys.id);
|
seen.insert(src.id);
|
||||||
while !queue.is_empty() {
|
while !queue.is_empty() {
|
||||||
print!(
|
print!(
|
||||||
"[{}] Depth: {}, Queue: {}, Seen: {} ({:.02}%) \r",
|
"[{}] Depth: {}, Queue: {}, Seen: {} ({:.02}%) \r",
|
||||||
|
@ -622,7 +675,7 @@ impl Router {
|
||||||
self.route_tree = Some(prev);
|
self.route_tree = Some(prev);
|
||||||
let ofn = format!(
|
let ofn = format!(
|
||||||
"{}_{}{}.router",
|
"{}_{}{}.router",
|
||||||
src.replace("*", "").replace(" ", "_"),
|
src.system.replace("*", "").replace(" ", "_"),
|
||||||
self.range,
|
self.range,
|
||||||
if self.primary_only { "_primary" } else { "" }
|
if self.primary_only { "_primary" } else { "" }
|
||||||
);
|
);
|
||||||
|
@ -634,13 +687,17 @@ impl Router {
|
||||||
String::from(self.path.to_str().unwrap()),
|
String::from(self.path.to_str().unwrap()),
|
||||||
self.route_tree.as_ref().unwrap(),
|
self.route_tree.as_ref().unwrap(),
|
||||||
);
|
);
|
||||||
return match bincode::serialize_into(&mut out_fh, &data) {
|
match bincode::serialize_into(&mut out_fh, &data) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => Err(format!("Error: {}",e).to_string())
|
Err(e) => Err(format!("Error: {}", e).to_string()),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_systems_by_ids(&mut self, path: &PathBuf, ids: &[u32]) -> Result<FnvHashMap<u32, System>,String> {
|
fn get_systems_by_ids(
|
||||||
|
&mut self,
|
||||||
|
path: &PathBuf,
|
||||||
|
ids: &[u32],
|
||||||
|
) -> Result<FnvHashMap<u32, System>, String> {
|
||||||
let mut ret = FnvHashMap::default();
|
let mut ret = FnvHashMap::default();
|
||||||
if let Some(c) = &mut self.cache.as_mut() {
|
if let Some(c) = &mut self.cache.as_mut() {
|
||||||
let mut missing = false;
|
let mut missing = false;
|
||||||
|
@ -659,8 +716,7 @@ impl Router {
|
||||||
return Ok(ret);
|
return Ok(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut reader = match csv::ReaderBuilder::new()
|
let mut reader = match csv::ReaderBuilder::new().from_path(path) {
|
||||||
.from_path(path) {
|
|
||||||
Ok(reader) => reader,
|
Ok(reader) => reader,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e));
|
return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e));
|
||||||
|
@ -674,30 +730,20 @@ impl Router {
|
||||||
ret.insert(sys.id, sys.build());
|
ret.insert(sys.id, sys.build());
|
||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
|
for id in ids {
|
||||||
|
if !ret.contains_key(&id) {
|
||||||
|
return Err(format!("ID {} not found", id));
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_system_by_name(path: &PathBuf, name: &str) -> Result<System,String> {
|
pub fn route_to(
|
||||||
// TODO: Fuzzy search (https://github.com/andylokandy/simsearch-rs)
|
&mut self,
|
||||||
let mut reader = csv::ReaderBuilder::new()
|
dst: &System,
|
||||||
.from_path(path)
|
systems_path: &PathBuf,
|
||||||
.unwrap_or_else(|e| {
|
) -> Result<Vec<System>, String> {
|
||||||
eprintln!("Error opening {}: {}", path.to_str().unwrap(), e);
|
|
||||||
std::process::exit(1);
|
|
||||||
});
|
|
||||||
let sys = reader
|
|
||||||
.deserialize::<SystemSerde>()
|
|
||||||
.map(|res| res.unwrap())
|
|
||||||
.find(|sys| sys.system == name);
|
|
||||||
match sys {
|
|
||||||
Some(system) => Ok(system.build()),
|
|
||||||
None => Err(format!("System {} not found!",name).to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn route_to(&mut self, dst: &str, systems_path: &PathBuf) -> Result<Vec<System>,String> {
|
|
||||||
let prev = self.route_tree.as_ref().unwrap();
|
let prev = self.route_tree.as_ref().unwrap();
|
||||||
let dst = Self::get_system_by_name(&systems_path, dst)?;
|
|
||||||
if !prev.contains_key(&dst.id) {
|
if !prev.contains_key(&dst.id) {
|
||||||
return Err(format!("System-ID {} not found", dst.id).to_string());
|
return Err(format!("System-ID {} not found", dst.id).to_string());
|
||||||
};
|
};
|
||||||
|
@ -719,7 +765,7 @@ impl Router {
|
||||||
let sys = match id_map.get(&sys_id) {
|
let sys = match id_map.get(&sys_id) {
|
||||||
Some(sys) => sys,
|
Some(sys) => sys,
|
||||||
None => {
|
None => {
|
||||||
return Err(format!("System-ID {} not found!",sys_id));
|
return Err(format!("System-ID {} not found!", sys_id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
v.push(sys.clone())
|
v.push(sys.clone())
|
||||||
|
@ -729,29 +775,29 @@ impl Router {
|
||||||
|
|
||||||
pub fn route_bfs(
|
pub fn route_bfs(
|
||||||
&self,
|
&self,
|
||||||
src: &(&String, [f32; 3]),
|
start_sys: &System,
|
||||||
dst: &(&String, [f32; 3]),
|
goal_sys: &System,
|
||||||
range: f32,
|
range: f32,
|
||||||
) -> Result<Vec<System>,String> {
|
) -> Result<Vec<System>, String> {
|
||||||
println!("Running BFS");
|
println!("Running BFS");
|
||||||
let (src_name, src) = src;
|
let src_name = start_sys.system.clone();
|
||||||
let (dst_name, dst) = dst;
|
let dst_name = goal_sys.system.clone();
|
||||||
let start_sys = self.closest(src);
|
|
||||||
let goal_sys = self.closest(dst);
|
|
||||||
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
let d_total = dist(&start_sys.pos, &goal_sys.pos);
|
||||||
let mut state=SearchState {
|
let mut d_rem = d_total;
|
||||||
mode:"BFS".into(),
|
let mut state = SearchState {
|
||||||
depth:0,
|
mode: "BFS".into(),
|
||||||
queue_size:0,
|
depth: 0,
|
||||||
d_rem: d_total,
|
queue_size: 0,
|
||||||
d_total: d_total,
|
d_rem,
|
||||||
|
d_total,
|
||||||
prc_done: 0.0,
|
prc_done: 0.0,
|
||||||
n_seen:0,
|
n_seen: 0,
|
||||||
prc_seen: 0.0,
|
prc_seen: 0.0,
|
||||||
system: start_sys.system.clone(),
|
system: start_sys.system.clone(),
|
||||||
body: start_sys.body.clone()
|
body: start_sys.body.clone(),
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
|
let d = dist(&start_sys.pos, &goal_sys.pos);
|
||||||
println!("Plotting route from {} to {}...", src_name, dst_name);
|
println!("Plotting route from {} to {}...", src_name, dst_name);
|
||||||
println!(
|
println!(
|
||||||
"Jump Range: {} Ly, Distance: {} Ly, Estimated Jumps: {}",
|
"Jump Range: {} Ly, Distance: {} Ly, Estimated Jumps: {}",
|
||||||
|
@ -765,41 +811,47 @@ impl Router {
|
||||||
let mut seen = FnvHashSet::default();
|
let mut seen = FnvHashSet::default();
|
||||||
let mut depth = 0;
|
let mut depth = 0;
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
|
let mut t_last = Instant::now();
|
||||||
let mut queue: VecDeque<(usize, &System)> = VecDeque::new();
|
let mut queue: VecDeque<(usize, &System)> = VecDeque::new();
|
||||||
let mut queue_next: VecDeque<(usize, &System)> = VecDeque::new();
|
let mut queue_next: VecDeque<(usize, &System)> = VecDeque::new();
|
||||||
let mut d_rem = dist(&start_sys.pos, &goal_sys.pos);
|
let mut d_rem = dist(&start_sys.pos, &goal_sys.pos);
|
||||||
queue.push_front((0, &start_sys));
|
queue.push_front((0, &start_sys));
|
||||||
seen.insert(start_sys.id);
|
seen.insert(start_sys.id);
|
||||||
while !(queue.is_empty() || found) {
|
while !(queue.is_empty() || found) {
|
||||||
state.depth=depth;
|
|
||||||
state.queue_size=queue.len();
|
|
||||||
state.prc_done=((d_total-d_rem)*100f32) / d_total;
|
|
||||||
state.d_rem=d_rem;
|
|
||||||
state.n_seen=seen.len();
|
|
||||||
state.prc_seen=((seen.len()*100) as f32) / total;
|
|
||||||
{
|
|
||||||
let s=queue.get(0).unwrap().1;
|
|
||||||
state.system=s.system.clone();
|
|
||||||
state.body=s.body.clone();
|
|
||||||
}
|
|
||||||
match (self.callback)(&state) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!("{:?}",e).to_string());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
while let Some((d, sys)) = queue.pop_front() {
|
while let Some((d, sys)) = queue.pop_front() {
|
||||||
if sys.id == goal_sys.id {
|
if sys.id == goal_sys.id {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if t_last.elapsed().as_millis() > 100 {
|
||||||
|
state.depth = depth;
|
||||||
|
state.queue_size = queue.len();
|
||||||
|
state.prc_done = ((d_total - d_rem) * 100f32) / d_total;
|
||||||
|
state.d_rem = d_rem;
|
||||||
|
state.n_seen = seen.len();
|
||||||
|
state.prc_seen = ((seen.len() * 100) as f32) / total;
|
||||||
|
{
|
||||||
|
let s = queue.get(0).unwrap().1;
|
||||||
|
state.system = s.system.clone();
|
||||||
|
state.body = s.body.clone();
|
||||||
|
}
|
||||||
|
match (self.callback)(&state) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) => {
|
||||||
|
return Err(format!("{:?}", e).to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t_last = Instant::now();
|
||||||
|
}
|
||||||
queue_next.extend(
|
queue_next.extend(
|
||||||
self.neighbours(&sys, range)
|
self.neighbours(&sys, range)
|
||||||
.filter(|&nb| (self.valid(nb) || (nb.id == goal_sys.id)))
|
.filter(|&nb| {
|
||||||
|
(self.valid(nb, &start_sys, &goal_sys) || (nb.id == goal_sys.id))
|
||||||
|
})
|
||||||
.filter(|&nb| seen.insert(nb.id))
|
.filter(|&nb| seen.insert(nb.id))
|
||||||
.map(|nb| {
|
.map(|nb| {
|
||||||
prev.insert(nb.id, sys);
|
prev.insert(nb.id, sys);
|
||||||
let dist = dist(&nb.pos, &goal_sys.pos);
|
let dist = nb.distp(goal_sys);
|
||||||
if dist < d_rem {
|
if dist < d_rem {
|
||||||
d_rem = dist;
|
d_rem = dist;
|
||||||
}
|
}
|
||||||
|
@ -813,7 +865,7 @@ impl Router {
|
||||||
println!();
|
println!();
|
||||||
println!();
|
println!();
|
||||||
if !found {
|
if !found {
|
||||||
return Err(format!("No route from {} to {} found!", src_name, dst_name).to_string());
|
return Err(format!("No route from {} to {} found!", src_name, dst_name));
|
||||||
}
|
}
|
||||||
let mut v: Vec<System> = Vec::new();
|
let mut v: Vec<System> = Vec::new();
|
||||||
let mut curr_sys = goal_sys;
|
let mut curr_sys = goal_sys;
|
||||||
|
@ -830,54 +882,71 @@ impl Router {
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn route(opts: RouteOpts) -> Result<Option<Vec<System>>,String> {
|
pub fn route(opts: RouteOpts) -> Result<Option<Vec<System>>, String> {
|
||||||
|
|
||||||
if opts.systems.is_empty() {
|
if opts.systems.is_empty() {
|
||||||
return if opts.precomp_file.is_some() {
|
if opts.precomp_file.is_some() {
|
||||||
Err("Error: Please specify exatly one system".to_string())
|
return Err("Error: Please specify exatly one system".to_owned());
|
||||||
} else if opts.precompute {
|
} else if opts.precompute {
|
||||||
Err("Error: Please specify at least one system".to_string())
|
return Err("Error: Please specify at least one system".to_owned());
|
||||||
} else {
|
} else {
|
||||||
Err("Error: Please specify at least two systems".to_string())
|
return Err("Error: Please specify at least two systems".to_owned());
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
let mut path = opts.file_path;
|
let mut path = opts.file_path;
|
||||||
let mut router: Router = if opts.precomp_file.is_some() {
|
let mut router: Router = if opts.precomp_file.is_some() {
|
||||||
let (path_,ret) = Router::from_file(&opts.precomp_file.clone().unwrap(),Box::new(opts.callback))?;
|
let (path_, ret) =
|
||||||
path=path_;
|
Router::from_file(&opts.precomp_file.clone().unwrap(), Box::new(opts.callback))?;
|
||||||
|
path = path_;
|
||||||
ret
|
ret
|
||||||
} else if opts.range.is_some() {
|
} else if opts.range.is_some() {
|
||||||
Router::new(&path, opts.range.unwrap(), opts.primary, Box::new(opts.callback))?
|
Router::new(
|
||||||
|
&path,
|
||||||
|
opts.range.unwrap(),
|
||||||
|
opts.radius_mult,
|
||||||
|
opts.primary,
|
||||||
|
Box::new(opts.callback),
|
||||||
|
)?
|
||||||
} else {
|
} else {
|
||||||
return Err("Please specify a jump range!".to_string());
|
Router::new(
|
||||||
|
&path,
|
||||||
|
opts.range.unwrap(),
|
||||||
|
opts.radius_mult,
|
||||||
|
opts.primary,
|
||||||
|
opts.callback,
|
||||||
|
)?
|
||||||
};
|
};
|
||||||
|
let systems: Vec<System> = router
|
||||||
|
.resolve_systems(&opts.systems)?
|
||||||
|
.iter()
|
||||||
|
.map(|sys| sys.clone())
|
||||||
|
.collect();
|
||||||
if opts.precompute {
|
if opts.precompute {
|
||||||
for sys in opts.systems {
|
for sys in systems {
|
||||||
router.route_tree = None;
|
router.route_tree = None;
|
||||||
router.precompute(&sys)?;
|
router.precompute(&sys)?;
|
||||||
}
|
}
|
||||||
return Ok(None)
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let route = if router.route_tree.is_some() {
|
let route = if router.route_tree.is_some() {
|
||||||
router.route_to(opts.systems.first().unwrap(), &path)?
|
router.route_to(systems.first().unwrap(), &path)?
|
||||||
} else if opts.permute {
|
} else if opts.permute {
|
||||||
router.best_name_multiroute(
|
router.best_multiroute(
|
||||||
&opts.systems,
|
&systems,
|
||||||
opts.range.unwrap(),
|
opts.range.unwrap(),
|
||||||
(opts.keep_first,opts.keep_last),
|
(opts.keep_first, opts.keep_last),
|
||||||
opts.mode,
|
opts.mode,
|
||||||
opts.factor.unwrap_or(1.0),
|
opts.factor.unwrap_or(1.0),
|
||||||
)?
|
)?
|
||||||
} else {
|
} else {
|
||||||
router.name_multiroute(
|
router.multiroute(
|
||||||
&opts.systems,
|
&systems,
|
||||||
opts.range.unwrap(),
|
opts.range.unwrap(),
|
||||||
opts.mode,
|
opts.mode,
|
||||||
opts.factor.unwrap_or(1.0),
|
opts.factor.unwrap_or(1.0),
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
if route.is_empty() {
|
if route.is_empty() {
|
||||||
return Err("No route found!".to_string())
|
return Err("No route found!".to_string());
|
||||||
}
|
}
|
||||||
return Ok(Some(route));
|
Ok(Some(route))
|
||||||
}
|
}
|
||||||
|
|
9
setup.py
9
setup.py
|
@ -18,7 +18,14 @@ setup(
|
||||||
],
|
],
|
||||||
packages=["ed_lrr_gui"],
|
packages=["ed_lrr_gui"],
|
||||||
entry_points={"console_scripts": ["ed_lrr_gui=ed_lrr_gui.__main__:main"]},
|
entry_points={"console_scripts": ["ed_lrr_gui=ed_lrr_gui.__main__:main"]},
|
||||||
install_requires=["PyQt5", "appdirs", "PyYAML", "requests", "python-dateutil"],
|
install_requires=[
|
||||||
|
"PyQt5",
|
||||||
|
"appdirs",
|
||||||
|
"PyYAML",
|
||||||
|
"requests",
|
||||||
|
"python-dateutil",
|
||||||
|
"pyperclip",
|
||||||
|
],
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
)
|
)
|
||||||
|
|
4
test.bat
Normal file
4
test.bat
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
python build_gui.py
|
||||||
|
pip uninstall -y ed_lrr_gui
|
||||||
|
pip install -e .
|
||||||
|
ed_lrr_gui
|
Loading…
Add table
Add a link
Reference in a new issue