diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md
new file mode 100644
index 0000000..1f731b6
--- /dev/null
+++ b/.chglog/CHANGELOG.tpl.md
@@ -0,0 +1,40 @@
+{{ if .Versions -}}
+
+## [Unreleased]
+
+{{ if .Unreleased.CommitGroups -}}
+{{ range .Unreleased.CommitGroups -}}
+{{ range .Commits -}}
+- {{ .Header }}
+{{ end }}
+{{ end -}}
+{{ end -}}
+{{ end -}}
+
+{{ range .Versions }}
+
+## {{ 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 -}}
\ No newline at end of file
diff --git a/.chglog/config.yml b/.chglog/config.yml
new file mode 100644
index 0000000..65dde53
--- /dev/null
+++ b/.chglog/config.yml
@@ -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
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index f8b9d2b..cfec1c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,14 @@
-/target
-/dist
-/build
+rust/target
**/*.rs.bk
*.tmp
*.idx
.vscode/**
+*.csv
+*.router
+plot.py
+*.tmp
+*.idx
*.pyd
-build.bat
-test.bat
__pycache__
-DL
*.egg-info
-pip-wheel-metadata
-rust/target/*
\ No newline at end of file
+build
diff --git a/MANIFEST.in b/MANIFEST.in
index 900cc3b..fe1501c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
-include rust/Cargo.toml
+include rust/Cargo.toml
+include rust/.cargo/config
recursive-include rust/src *
\ No newline at end of file
diff --git a/build.bat b/build.bat
new file mode 100644
index 0000000..9487f53
--- /dev/null
+++ b/build.bat
@@ -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 ..
\ No newline at end of file
diff --git a/ed_lrr_gui/__init__.py b/ed_lrr_gui/__init__.py
index 2d1a9d6..9bce23f 100644
--- a/ed_lrr_gui/__init__.py
+++ b/ed_lrr_gui/__init__.py
@@ -1,2 +1,4 @@
from _ed_lrr import *
from . import gui
+from .router import Router
+from .preprocess import Preprocessor
diff --git a/ed_lrr_gui/__main__.py b/ed_lrr_gui/__main__.py
index 71c6b13..c03221f 100644
--- a/ed_lrr_gui/__main__.py
+++ b/ed_lrr_gui/__main__.py
@@ -2,21 +2,28 @@ import sys
import os
import requests as RQ
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 (
QMainWindow,
QApplication,
QFileDialog,
QProgressDialog,
QTreeWidgetItem,
+ QAction,
+ QMessageBox,
)
from urllib.request import Request, urlopen
import gzip
+import pathlib
from PyQt5.QtGui import QPalette, QColor
import ed_lrr_gui
import ed_lrr_gui.config as cfg
from ed_lrr_gui.gui.ed_lrr import Ui_ED_LRR
+from ed_lrr_gui import Router, Preprocessor
import multiprocessing as MP
+import queue
+import csv
+import _ed_lrr
def sizeof_fmt(num, suffix="B"):
@@ -37,6 +44,85 @@ class ProgressDialog(QProgressDialog):
self.setWindowModality(Qt.WindowModal)
+class Job(QObject):
+ progress = pyqtSignal("PyQt_PyObject")
+
+ def __init__(self, app, cls, *args, build_progress=None, **kwargs):
+ super().__init__()
+ self.job = cls(*args, **kwargs)
+ self.timer = QTimer(app)
+ self.app = app
+ self.timer.timeout.connect(self.interval)
+ self.timer.start(100)
+ self.last_val = None
+ self.build_progress = build_progress
+ self.progress_dialog = None
+ self.state = {}
+
+ def start(self):
+ """
+ if self.diag_prog is None:
+ self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window)
+ if self.dl_thread:
+ self.diag_prog.canceled.connect(self.dl_canceled)
+ self.diag_prog.show()
+ t_elapsed = datetime.today() - self.dl_started
+ rate = args["done"] / t_elapsed.total_seconds()
+ remaining = (args["size"] - args["done"]) / rate
+ rate = round(rate, 2)
+ # print(rate, remaining)
+ try:
+ t_rem = timedelta(seconds=remaining)
+ except OverflowError:
+ t_rem = "-"
+ msg = "Downloading {} [{}/{}] ({}/s)\n[{}/{}]".format(
+ filename,
+ sizeof_fmt(args["done"]),
+ sizeof_fmt(args["size"]),
+ sizeof_fmt(rate),
+ t_round(t_elapsed),
+ t_round(t_rem),
+ )
+ self.diag_prog.setLabelText(msg)
+ self.diag_prog.setWindowTitle("Downloading EDSM Dumps")
+ self.diag_prog.setValue((args["done"] * 1000) // args["size"])
+ """
+ self.started = datetime.today()
+ if self.build_progress:
+ self.progress_dialog = ProgressDialog("", "Cancel", 0, 1000, self.app)
+ self.progress_dialog.canceled.connect(self.cancel)
+ self.progress_dialog.show()
+ self.progress.connect(self.__build_progress)
+ else:
+ self.progress.connect(
+ lambda *args, **kwargs: print("PROGRESS:", *args, **kwargs)
+ )
+ return self.job.start()
+
+ def __build_progress(self, *args, **kwargs):
+ kwargs["self"] = self
+ return self.build_progress(*args, **kwargs)
+
+ def cancel(self):
+ self.job.terminate()
+ self.job = None
+
+ def done(self):
+ return (self.job.is_alive() == False) and (self.job.queue.empty())
+
+ def interval(self):
+ while True:
+ try:
+ res = self.job.queue.get(True, 0.1)
+ except queue.Empty:
+ return
+ if res == self.last_val:
+ continue
+ self.state.update(res)
+ self.progress.emit(self.state)
+ self.last_val = res
+
+
class DownloadThread(QThread):
progress = pyqtSignal("PyQt_PyObject")
@@ -79,45 +165,65 @@ class App(QApplication):
def __init__(self):
super().__init__(sys.argv)
self.setStyle("Fusion")
- self.set_pallete()
+ self.setup_styles()
- def set_pallete(self):
- colors = {
- "Window": QColor(53, 53, 53),
- "WindowText": Qt.white,
- "Base": QColor(15, 15, 15),
- "AlternateBase": QColor(53, 53, 53),
- "ToolTipBase": Qt.white,
- "ToolTipText": Qt.white,
- "Text": Qt.white,
- "Button": QColor(53, 53, 53),
- "ButtonText": Qt.white,
- "BrightText": Qt.red,
- "Highlight": QColor(255, 128, 0),
- "HighlightedText": Qt.black,
+ def set_style(self, style):
+ print("LOAD:", style)
+ self.setPalette(self.styles[style])
+
+ def setup_styles(self):
+ self.styles = {}
+ styles = {
+ "Dark": {
+ "Window": QColor(53, 53, 53),
+ "WindowText": Qt.white,
+ "Base": QColor(15, 15, 15),
+ "AlternateBase": QColor(53, 53, 53),
+ "ToolTipBase": Qt.white,
+ "ToolTipText": Qt.white,
+ "Text": Qt.white,
+ "Button": QColor(53, 53, 53),
+ "ButtonText": Qt.white,
+ "BrightText": Qt.red,
+ "Highlight": QColor(255, 128, 0),
+ "HighlightedText": Qt.black,
+ }
}
- palette = QPalette()
- for entry, color in colors.items():
- palette.setColor(getattr(QPalette, entry), color)
- if color == Qt.darkGray:
- palette.setColor(
- QPalette.Disabled, getattr(QPalette, entry), QColor(53, 53, 53)
- )
- else:
- palette.setColor(
- QPalette.Disabled, getattr(QPalette, entry), Qt.darkGray
- )
- self.setPalette(palette)
+ for style, colors in styles.items():
+ palette = QPalette()
+ for entry, color in colors.items():
+ palette.setColor(getattr(QPalette, entry), color)
+ if color == Qt.darkGray:
+ palette.setColor(
+ QPalette.Disabled, getattr(QPalette, entry), QColor(53, 53, 53)
+ )
+ else:
+ palette.setColor(
+ QPalette.Disabled, getattr(QPalette, entry), Qt.darkGray
+ )
+ self.styles[style] = palette
+ self.styles["Light"] = self.style().standardPalette()
class ED_LRR(Ui_ED_LRR):
dl_thread = None
diag_prog = None
dl_started = None
+ system_found = pyqtSignal("PyQt_PyObject")
def __init__(self):
super().__init__()
self.config = cfg.load()
+ self.jobs = {}
+
+ def start_job(self, cls, *args, **kwargs):
+ print("START JOB:", cls, args, kwargs)
+ name = cls.__name__
+ if name in self.jobs and self.jobs[name].done():
+ del self.jobs[name]
+ if not name in self.jobs:
+ self.jobs[name] = Job(self.app, cls, *args, **kwargs)
+ self.jobs[name].start()
def get_open_file(self, filetypes, callback=None):
fileName, _ = QFileDialog.getOpenFileName(
@@ -148,6 +254,8 @@ class ED_LRR(Ui_ED_LRR):
self.config.history_out_path.append(path)
self.inp_sys_lst.addItem(path)
self.inp_out_pp.addItem(path)
+ self.inp_sys_lst.setCurrentText(path)
+ self.inp_out_pp.setCurrentText(path)
def set_bodies_file(self, path):
if path not in self.config.history_bodies_path:
@@ -170,7 +278,7 @@ class ED_LRR(Ui_ED_LRR):
def set_comp_mode(self, _):
if self.rd_comp.isChecked():
comp_mode = "Compute Route"
- self.btn_add.setText("Search+Add")
+ self.btn_add.setText("Add")
if self.rd_precomp.isChecked():
comp_mode = "Precompute Graph"
self.btn_add.setText("Select")
@@ -178,7 +286,7 @@ class ED_LRR(Ui_ED_LRR):
self.lst_sys.setEnabled(self.rd_comp.isChecked())
self.btn_rm.setEnabled(self.rd_comp.isChecked())
self.cmb_mode.setEnabled(self.rd_comp.isChecked())
- self.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_mode.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()
self.lbl_greedyness.setEnabled(mode == "A*-Search")
self.sld_greedyness.setEnabled(mode == "A*-Search")
- self.log("ROUTE_MODE", mode)
def set_greedyness(self, value):
self.lbl_greedyness.setText("Greedyness Factor ({:.0%})".format(value / 100))
+ @property
+ def systems(self):
+ ret = []
+ for n in range(self.lst_sys.topLevelItemCount()):
+ ret.append(self.sys_to_dict(n))
+ return ret
+
def sys_to_dict(self, n):
header = [
self.lst_sys.headerItem().data(c, 0)
@@ -204,34 +318,108 @@ class ED_LRR(Ui_ED_LRR):
self.lst_sys.topLevelItem(n).data(c, 0)
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):
- settings = {}
- settings["permute"] = (
- self.chk_permute_keep_first.checkState(),
- self.chk_permute_keep_last.checkState(),
+ if not all(s["Type"] for s in self.systems):
+ self.error('Not all systens have been resolved, please click "Search All"')
+ return
+ print(self.systems)
+ systems = [str(s["id"]) for s in self.systems]
+ jump_range = self.sb_range.value()
+ mode = self.cmb_mode.currentText()
+ primary = self.chk_primary.isChecked()
+ keep_first = self.chk_permute_keep_first.isChecked()
+ keep_last = self.chk_permute_keep_last.isChecked()
+ permute = self.chk_permute.isChecked()
+ greedyness = (
+ self.sld_greedyness.value() / 100
+ if self.sld_greedyness.isEnabled()
+ else None
)
- settings["range"] = self.sb_range.value()
- settings["systems"] = [
- self.sys_to_dict(i) for i in range(self.lst_sys.topLevelItemCount())
- ]
- print(settings)
- progress = ProgressDialog(
- "(Not actually computing)", "Cancel", 0, 0, self.main_window
+ path = self.get_sys_list()
+ if path is None:
+ return
+ precomp = path.with_suffix(".idx")
+ path = str(path)
+ if not precomp.exists():
+ precomp = None
+ else:
+ precomp = str(precomp)
+ mode = {
+ "Breadth-First Search": "bfs",
+ "A*-Search": "astar",
+ "Greedy-Search": "greedy",
+ }[mode]
+ print(
+ systems,
+ jump_range,
+ mode,
+ primary,
+ permute,
+ (keep_first, keep_last),
+ greedyness,
+ path,
+ precomp,
)
- progress.setWindowTitle("Computing Route")
- progress.setFixedSize(400, 100)
- progress.setRange(0, 0)
- progress.show()
+ self.start_job(
+ Router,
+ systems,
+ jump_range,
+ 0.1,
+ mode,
+ primary,
+ permute,
+ keep_first,
+ keep_last,
+ greedyness,
+ precomp,
+ path,
+ )
+
+ def find_sys_by_names(self, names):
+ t_s = datetime.today()
+ if not self.get_sys_list():
+ return None
+ ret = _ed_lrr.find_sys(names, self.inp_sys_lst.currentText())
+ print("Took:", datetime.today() - t_s)
+ return ret
+
+ def resolve_systems(self):
+ names = []
+ for n in range(self.lst_sys.topLevelItemCount()):
+ names.append(self.sys_to_dict(n)["Name"])
+ systems = self.find_sys_by_names(names)
+ if systems is None:
+ return
+ for i, name in enumerate(names):
+ _, system = systems[name]
+ self.lst_sys.topLevelItem(i).setData(0, 0, system["system"])
+ self.lst_sys.topLevelItem(i).setData(1, 0, system["star_type"])
+ self.lst_sys.topLevelItem(i).__id__ = system["id"]
+ # diff, item = self.find_sys_by_name(name)
+ # print("Found", (diff, item))
def add_system(self):
- n = self.lst_sys.topLevelItemCount() + 1
name = self.inp_sys.text()
- item = QTreeWidgetItem(
- self.lst_sys, [str(n) + ". Name: " + name, "Type: " + name[::-1]]
- )
- item.sys_id = "SYS_ID_HERE"
+ item = QTreeWidgetItem(self.lst_sys, [name, None])
+ item.resolved = False
item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled)
def remove_system(self):
@@ -253,7 +441,7 @@ class ED_LRR(Ui_ED_LRR):
self.diag_prog = None
self.dl_started = None
- def handle_progress(self, args):
+ def handle_dl_progress(self, args):
filename = os.path.split(args["outfile"])[-1]
if self.diag_prog is None:
self.diag_prog = ProgressDialog("", "Cancel", 0, 1000, self.main_window)
@@ -291,10 +479,15 @@ class ED_LRR(Ui_ED_LRR):
self.inp_bodies_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()
print(".")
+ def update_permute_chk(self, state):
+ self.chk_permute_keep_first.setEnabled(state)
+ self.chk_permute_keep_last.setEnabled(state)
+ self.lbl_keep.setEnabled(state)
+
def setup_signals(self):
self.btn_download.clicked.connect(self.run_download)
self.inp_systems_dest_dl.setCurrentText(r"D:\devel\rust\ed_lrr_gui\DL\s.json")
@@ -307,6 +500,8 @@ class ED_LRR(Ui_ED_LRR):
self.btn_go.clicked.connect(self.run)
self.btn_add.clicked.connect(self.add_system)
self.btn_rm.clicked.connect(self.remove_system)
+ self.chk_permute.stateChanged.connect(self.update_permute_chk)
+ self.btn_search.clicked.connect(self.resolve_systems)
self.btn_out_browse_pp.clicked.connect(
lambda: self.get_save_file("CSV File (*.csv)", self.set_sys_lst)
)
@@ -331,6 +526,14 @@ class ED_LRR(Ui_ED_LRR):
cfg.write(self.config)
print("BYEEEEEE!")
+ def setup_styles(self, win, app):
+ for name in app.styles:
+ action = QAction(app)
+ action.setObjectName("action_load_style_" + name)
+ action.setText(name)
+ action.triggered.connect(lambda _, name=name: app.set_style(name))
+ self.menuStyle.addAction(action)
+
def setupUi(self, MainWindow, app):
super().setupUi(MainWindow)
self.update_dropdowns()
@@ -339,6 +542,8 @@ class ED_LRR(Ui_ED_LRR):
self.setup_signals()
self.lst_sys.setHeaderLabels(["Name", "Type"])
self.set_route_mode()
+ self.update_permute_chk(self.chk_permute.isChecked())
+ self.setup_styles(MainWindow, app)
def main():
diff --git a/ed_lrr_gui/gui/ed_lrr.py b/ed_lrr_gui/gui/ed_lrr.py
index 76ba5f8..721546f 100644
--- a/ed_lrr_gui/gui/ed_lrr.py
+++ b/ed_lrr_gui/gui/ed_lrr.py
@@ -26,6 +26,14 @@ class Ui_ED_LRR(object):
ED_LRR.setDocumentMode(False)
ED_LRR.setTabShape(QtWidgets.QTabWidget.Rounded)
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.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
@@ -214,9 +222,12 @@ class Ui_ED_LRR(object):
self.rd_precomp.setObjectName("rd_precomp")
self.gr_mode.addWidget(self.rd_precomp, 0, 2, 1, 1)
self.formLayout_2.setLayout(3, QtWidgets.QFormLayout.FieldRole, self.gr_mode)
+<<<<<<< Updated upstream
self.btn_permute = QtWidgets.QPushButton(self.tab_route)
self.btn_permute.setObjectName("btn_permute")
self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.btn_permute)
+=======
+>>>>>>> Stashed changes
self.lst_sys = QtWidgets.QTreeWidget(self.tab_route)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
@@ -231,6 +242,7 @@ class Ui_ED_LRR(object):
self.lst_sys.setAlternatingRowColors(True)
self.lst_sys.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.lst_sys.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+<<<<<<< Updated upstream
self.lst_sys.setHeaderHidden(True)
self.lst_sys.setObjectName("lst_sys")
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.setObjectName("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.setObjectName("gr_opts")
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.setObjectName("lbl_mode")
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.btn_go = QtWidgets.QPushButton(self.tab_route)
self.btn_go.setFlat(False)
self.btn_go.setObjectName("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.setObjectName("gridLayout_4")
self.chk_permute_keep_last = QtWidgets.QCheckBox(self.tab_route)
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, 3, 1, 1)
+>>>>>>> Stashed changes
self.chk_permute_keep_first = QtWidgets.QCheckBox(self.tab_route)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -286,7 +323,11 @@ class Ui_ED_LRR(object):
self.chk_permute_keep_first.setSizePolicy(sizePolicy)
self.chk_permute_keep_first.setTristate(False)
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, 2, 1, 1)
+>>>>>>> Stashed changes
self.lbl_keep = QtWidgets.QLabel(self.tab_route)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
@@ -294,8 +335,19 @@ class Ui_ED_LRR(object):
sizePolicy.setHeightForWidth(self.lbl_keep.sizePolicy().hasHeightForWidth())
self.lbl_keep.setSizePolicy(sizePolicy)
self.lbl_keep.setObjectName("lbl_keep")
+<<<<<<< Updated upstream
self.gridLayout_4.addWidget(self.lbl_keep, 0, 0, 1, 1)
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.tab_log = QtWidgets.QWidget()
self.tab_log.setObjectName("tab_log")
@@ -317,14 +369,32 @@ class Ui_ED_LRR(object):
self.menu.setObjectName("menu")
self.menu_file = QtWidgets.QMenu(self.menu)
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)
self.bar_status = QtWidgets.QStatusBar(ED_LRR)
self.bar_status.setObjectName("bar_status")
ED_LRR.setStatusBar(self.bar_status)
self.menu_act_quit = QtWidgets.QAction(ED_LRR)
self.menu_act_quit.setObjectName("menu_act_quit")
+<<<<<<< Updated upstream
self.menu_file.addAction(self.menu_act_quit)
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.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.lbl_sys_lst.setText(_translate("ED_LRR", "System List"))
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", "Add"))
+>>>>>>> Stashed changes
self.inp_sys.setPlaceholderText(_translate("ED_LRR", "System Name"))
self.btn_rm.setText(_translate("ED_LRR", "Remove"))
self.rd_comp.setText(_translate("ED_LRR", "Compute Route"))
self.rd_precomp.setText(_translate("ED_LRR", "Precompute Graph"))
+<<<<<<< Updated upstream
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.cmb_mode.setCurrentText(_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_first.setText(_translate("ED_LRR", "First"))
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_log), _translate("ED_LRR", "Log"))
self.menu_file.setTitle(_translate("ED_LRR", "File"))
self.menu_act_quit.setText(_translate("ED_LRR", "Quit"))
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
diff --git a/ed_lrr_gui/gui/ed_lrr.ui b/ed_lrr_gui/gui/ed_lrr.ui
index 7034a30..4685221 100644
--- a/ed_lrr_gui/gui/ed_lrr.ui
+++ b/ed_lrr_gui/gui/ed_lrr.ui
@@ -44,6 +44,15 @@
QTabWidget::Rounded
+<<<<<<< Updated upstream
+=======
+
+
+ 0
+ 0
+
+
+>>>>>>> Stashed changes
-
@@ -363,7 +372,11 @@
-
+<<<<<<< Updated upstream
Search+Add
+=======
+ Add
+>>>>>>> Stashed changes
@@ -402,6 +415,7 @@
+<<<<<<< Updated upstream
-
@@ -409,6 +423,8 @@
+=======
+>>>>>>> Stashed changes
-
@@ -445,26 +461,53 @@
QAbstractItemView::SelectRows
+<<<<<<< Updated upstream
true
1
+=======
+ false
+
+
+ false
+
+
+
+ Name
+
+
+
+
+ Type
+>>>>>>> Stashed changes
+<<<<<<< Updated upstream
-
-
+=======
+
-
+
+
+ -
+>>>>>>> Stashed changes
Jump Range (Ly)
+<<<<<<< Updated upstream
-
+=======
+
-
+>>>>>>> Stashed changes
-
@@ -536,7 +579,11 @@
+<<<<<<< Updated upstream
-
+=======
+
-
+>>>>>>> Stashed changes
GO!
@@ -548,14 +595,22 @@
-
+<<<<<<< Updated upstream
-
+=======
+
-
+>>>>>>> Stashed changes
Last
+<<<<<<< Updated upstream
-
+=======
+
-
+>>>>>>> Stashed changes
@@ -571,7 +626,11 @@
+<<<<<<< Updated upstream
-
+=======
+
-
+>>>>>>> Stashed changes
@@ -586,6 +645,23 @@
+<<<<<<< Updated upstream
+=======
+ -
+
+
+ Permute
+
+
+
+ -
+
+
+ Search All
+
+
+
+>>>>>>> Stashed changes
@@ -633,7 +709,23 @@
+<<<<<<< Updated upstream
+=======
+
+
+
+>>>>>>> Stashed changes
@@ -644,6 +736,19 @@
Ctrl+Q
+<<<<<<< Updated upstream
+=======
+
+
+ A
+
+
+
+
+ B
+
+
+>>>>>>> Stashed changes
rd_comp
diff --git a/ed_lrr_gui/preprocess.py b/ed_lrr_gui/preprocess.py
index b7c8675..f59b2b4 100644
--- a/ed_lrr_gui/preprocess.py
+++ b/ed_lrr_gui/preprocess.py
@@ -14,24 +14,13 @@ class Preprocessor(Process):
self.args = args
self.kwargs = kwargs
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):
self.queue.put({"status": state})
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__":
diff --git a/ed_lrr_gui/router.py b/ed_lrr_gui/router.py
index 773f939..4e5bbfe 100644
--- a/ed_lrr_gui/router.py
+++ b/ed_lrr_gui/router.py
@@ -14,18 +14,6 @@ class Router(Process):
self.args = args
self.kwargs = kwargs
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):
self.queue.put({"status": state})
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index d65855d..4ef4323 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -168,10 +168,19 @@ dependencies = [
"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)",
"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)",
"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)",
"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]]
@@ -205,6 +214,19 @@ dependencies = [
[[package]]
name = "ghost"
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"
dependencies = [
"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"
dependencies = [
"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.2 (registry+https://github.com/rust-lang/crates.io-index)",
+>>>>>>> Stashed changes:Cargo.lock
]
[[package]]
@@ -302,7 +328,11 @@ name = "mashup-impl"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
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.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)",
]
@@ -377,15 +407,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro-hack"
+<<<<<<< Updated upstream:rust/Cargo.lock
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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]]
name = "proc-macro-hack-impl"
+<<<<<<< Updated upstream:rust/Cargo.lock
version = "0.4.1"
+=======
+version = "0.4.2"
+>>>>>>> Stashed changes:Cargo.lock
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -592,7 +633,7 @@ dependencies = [
[[package]]
name = "rstar"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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]]
name = "spin"
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"
[[package]]
@@ -748,6 +807,11 @@ name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "version_check"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "winapi"
version = "0.3.7"
@@ -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 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"
+<<<<<<< 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 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"
@@ -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 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"
+<<<<<<< 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-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 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"
@@ -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-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 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 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"
@@ -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 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"
+<<<<<<< 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 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"
@@ -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-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"
+<<<<<<< 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 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"
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index d97be65..2a579f7 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -11,12 +11,12 @@ license = "WTFPL"
crate-type = ["cdylib"]
[profile.release]
-debug=true
+#debug=true
[dependencies]
csv = "1.1.1"
serde = { version = "1.0", features = ["derive"] }
-rstar = "0.4.0"
+rstar = "0.5.0"
humantime = "1.2.0"
permutohedron = "0.2.4"
serde_json = "1.0.40"
@@ -25,6 +25,7 @@ fnv = "1.0.6"
bincode = "1.1.4"
sha3 = "0.8.2"
byteorder = "1.3.2"
+strsim = "0.9.2"
[dependencies.pyo3]
version = "0.7.0"
diff --git a/rust/src/common.rs b/rust/src/common.rs
index 6e563f4..74d4d1f 100644
--- a/rust/src/common.rs
+++ b/rust/src/common.rs
@@ -27,6 +27,7 @@ impl SystemSerde {
}
}
+
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct System {
pub id: u32,
@@ -37,3 +38,16 @@ pub struct System {
pub distance: u32,
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 {
+ return Some(self.cmp(other));
+ }
+}
+
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index fdc0fb4..ee39dd4 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -1,14 +1,43 @@
+extern crate strsim;
mod common;
mod preprocess;
mod route;
-use pyo3::prelude::*;
-use pyo3::types::{PyDict,PyList};
+use std::collections::HashMap;
use pyo3::exceptions::*;
+use pyo3::prelude::*;
+use pyo3::types::{PyDict, PyList};
use std::path::PathBuf;
+use common::{System,SystemSerde};
+
+fn find_matches(path:&PathBuf,names:Vec) -> Result)>,String> {
+ let mut best: HashMap)> = 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::();
+ 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]
pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
-
/// preprocess(infile_systems, infile_bodies, outfile, callback)
/// --
///
@@ -24,108 +53,139 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> {
use preprocess::*;
let state = 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| {
// println!("SEND: {:?}",state);
- state_dict.set_item("file",state.file.clone())?;
- state_dict.set_item("total",state.total)?;
- state_dict.set_item("done",state.done)?;
- callback.call(py,(state_dict,),None)
+ state_dict.set_item("file", state.file.clone())?;
+ state_dict.set_item("total", state.total)?;
+ state_dict.set_item("count", state.count)?;
+ 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();
- return Ok(state.to_object(py));
+ preprocess_files(
+ &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,sys_list:String) -> PyResult {
+ 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::(e));
+ }
+ }
+ }
+
+ /// route(infile, hops, range, radius_mult, mode,primary, greedyness, precomp, callback)
/// --
///
/// Compute a Route using the suplied parameters
#[pyfn(m, "route")]
+ #[allow(clippy::too_many_arguments)]
fn route(
py: Python<'static>,
hops: Vec,
range: f32,
+ radius_mult: f32,
mode: String,
primary: bool,
permute: bool,
+ keep_first: bool,
+ keep_last: bool,
greedyness: Option,
precomp: Option,
path: String,
callback: PyObject,
) -> PyResult {
use route::*;
- // TODO: Verify Parameters
let mode = match Mode::parse(&mode) {
Ok(val) => val,
Err(e) => {
- return Err(PyErr::new::(e));
+ return Err(PyErr::new::(e));
}
};
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| {
- println!("SEND: {:?}",state);
- state_dict.set_item("mode",state.mode.clone())?;
- state_dict.set_item("system",state.system.clone())?;
- state_dict.set_item("body",state.body.clone())?;
- state_dict.set_item("depth",state.depth)?;
- state_dict.set_item("queue_size",state.queue_size)?;
- state_dict.set_item("d_rem",state.d_rem)?;
- state_dict.set_item("d_total",state.d_total)?;
- state_dict.set_item("prc_done",state.prc_done)?;
- state_dict.set_item("n_seen",state.n_seen)?;
- state_dict.set_item("prc_seen",state.prc_seen)?;
- callback.call(py,(state_dict,),None)
+ state_dict.set_item("mode", state.mode.clone())?;
+ state_dict.set_item("system", state.system.clone())?;
+ state_dict.set_item("body", state.body.clone())?;
+ state_dict.set_item("depth", state.depth)?;
+ state_dict.set_item("queue_size", state.queue_size)?;
+ state_dict.set_item("d_rem", state.d_rem)?;
+ state_dict.set_item("d_total", state.d_total)?;
+ state_dict.set_item("prc_done", state.prc_done)?;
+ state_dict.set_item("n_seen", state.n_seen)?;
+ state_dict.set_item("prc_seen", state.prc_seen)?;
+ callback.call(py, (state_dict,), None)
};
- let opts=RouteOpts{
- systems:hops,
- range:Some(range),
+ let mut systems=Vec::new();
+ for sys in hops {
+ systems.push(route::SysEntry::parse(&sys))
+ }
+ println!("SYSTEMS: {:?}",systems);
+ let opts = RouteOpts {
+ systems,
+ range: Some(range),
file_path: PathBuf::from(path),
precomp_file: precomp.map(PathBuf::from),
callback: Box::new(callback_wrapped),
mode,
factor: greedyness,
precompute: false,
- permute: permute,
- keep_first: true,
- keep_last: true,
- primary
+ permute,
+ keep_first,
+ keep_last,
+ primary,
+ radius_mult
};
- let none=().to_object(py);
+ let none = ().to_object(py);
match route(opts) {
Ok(Some(route)) => {
- let hops=route.iter().map(|hop| {
- let pos=PyList::new(py,hop.pos.iter());
- let elem=PyDict::new(py);
- elem.set_item("star_type",hop.star_type.clone()).unwrap();
- elem.set_item("system",hop.system.clone()).unwrap();
- elem.set_item("body",hop.body.clone()).unwrap();
- elem.set_item("distance",hop.distance).unwrap();
- elem.set_item("pos",pos).unwrap();
- return elem;
+ let hops = route.iter().map(|hop| {
+ let pos = PyList::new(py, hop.pos.iter());
+ let elem = PyDict::new(py);
+ elem.set_item("star_type", hop.star_type.clone()).unwrap();
+ elem.set_item("system", hop.system.clone()).unwrap();
+ elem.set_item("body", hop.body.clone()).unwrap();
+ elem.set_item("distance", hop.distance).unwrap();
+ elem.set_item("pos", pos).unwrap();
+ elem
});
- let lst=PyList::new(py,hops);
- return Ok(lst.to_object(py));
+ let lst = PyList::new(py, hops);
+ Ok(lst.to_object(py))
}
- Ok(None) => {
- return Ok(none);
- },
- Err(e) => {
- return Err(PyErr::new::(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(None) => Ok(none),
+ Err(e) => Err(PyErr::new::(e)),
+ }
}
Ok(())
}
diff --git a/rust/src/route.rs b/rust/src/route.rs
index d206501..9da946b 100644
--- a/rust/src/route.rs
+++ b/rust/src/route.rs
@@ -1,8 +1,10 @@
+use crate::common::{System, SystemSerde};
use core::cmp::Ordering;
use csv::StringRecord;
use fnv::{FnvHashMap, FnvHashSet};
use humantime::format_duration;
use permutohedron::LexicalPermutation;
+use pyo3::prelude::*;
use rstar::{PointDistance, RTree, RTreeObject, AABB};
use sha3::{Digest, Sha3_256};
use std::collections::VecDeque;
@@ -12,8 +14,6 @@ use std::io::Seek;
use std::io::{BufRead, BufReader, BufWriter, Write};
use std::path::PathBuf;
use std::time::Instant;
-use pyo3::prelude::*;
-use crate::common::{System, SystemSerde};
#[derive(Debug)]
pub struct SearchState {
@@ -26,9 +26,23 @@ pub struct SearchState {
pub d_total: f32,
pub prc_done: f32,
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 range: Option,
@@ -41,8 +55,9 @@ pub struct RouteOpts {
pub keep_last: bool,
pub factor: Option,
pub mode: Mode,
- pub systems: Vec,
- pub callback: Box PyResult>
+ pub radius_mult: f32,
+ pub systems: Vec,
+ pub callback: Box PyResult>,
}
#[derive(Debug)]
@@ -52,9 +67,9 @@ pub enum Mode {
AStar,
}
-impl Mode {
+impl Mode {
pub fn parse(s: &str) -> Result {
- let s=s.to_lowercase();
+ let s = s.to_lowercase();
match s.as_ref() {
"bfs" => Ok(Mode::BFS),
"greedy" => Ok(Mode::Greedy),
@@ -160,8 +175,8 @@ impl LineCache {
}
pub fn get(&mut self, id: u32) -> Option {
let pos = self.cache[id as usize];
- self.file.seek(std::io::SeekFrom::Start(pos)).unwrap();
- let rec = Self::read_record(&mut self.file).unwrap();
+ self.file.seek(std::io::SeekFrom::Start(pos)).ok()?;
+ let rec = Self::read_record(&mut self.file)?;
let sys: SystemSerde = rec.deserialize(self.header.as_ref()).unwrap();
Some(sys.build())
}
@@ -175,18 +190,26 @@ pub struct Router {
range: f32,
primary_only: bool,
path: PathBuf,
- callback: Box PyResult>
+ radius_mult: f32,
+ callback: Box PyResult>,
}
impl Router {
- pub fn new(path: &PathBuf, range: f32, primary_only: bool,callback: Box PyResult>) -> Result {
+ pub fn new(
+ path: &PathBuf,
+ range: f32,
+ radius_mult: f32,
+ primary_only: bool,
+ callback: Box PyResult>,
+ ) -> Result {
let mut scoopable = FnvHashSet::default();
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());
+ return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e));
}
};
+ let t_load = Instant::now();
println!("Loading {}...", path.to_str().unwrap());
let systems: Vec = reader
.deserialize::()
@@ -220,25 +243,54 @@ impl Router {
primary_only,
cache: LineCache::new(path),
path: path.clone(),
- callback: callback,
+ callback,
+ radius_mult,
};
+ println!(
+ "{} Systems loaded in {}",
+ ret.tree.size(),
+ format_duration(t_load.elapsed())
+ );
Ok(ret)
}
- pub fn from_file(filename: &PathBuf,callback: Box PyResult>) -> Result<(PathBuf, Self),String> {
- let mut reader = BufReader::new(File::open(&filename).unwrap());
+ pub fn from_file(
+ filename: &PathBuf,
+ callback: Box PyResult>,
+ ) -> 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): (
bool,
f32,
Vec,
String,
FnvHashMap,
- ) = 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);
if hash_file(&path) != file_hash {
return Err("File hash mismatch!".to_string());
}
- let cache = LineCache::new(&path);
+ let cache = LineCache::new(&path).ok();
Ok((
path.clone(),
Self {
@@ -249,14 +301,12 @@ impl Router {
cache,
primary_only: primary,
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- {
self.tree.locate_within_distance(*center, radius * radius)
}
@@ -265,18 +315,23 @@ impl Router {
self.points_in_sphere(&sys.pos, sys.mult * r)
}
- fn valid(&self, sys: &System) -> bool {
- self.scoopable.contains(&sys.id)
+ fn valid(&self, sys: &System, src: &System, dst: &System) -> bool {
+ let scoopable = self.scoopable.contains(&sys.id);
+ if self.radius_mult == 0.0 {
+ return scoopable;
+ }
+ let df = src.distp(dst);
+ return (sys.distp(src) + sys.distp(dst)) < (df * (1.0 + self.radius_mult));
}
- pub fn best_name_multiroute(
+ pub fn best_multiroute(
&self,
- waypoints: &[String],
+ waypoints: &Vec,
range: f32,
- keep: (bool,bool),
+ keep: (bool, bool),
mode: Mode,
factor: f32,
- ) -> Result,String> {
+ ) -> Result, String> {
let mut best_score: f32 = std::f32::MAX;
let mut waypoints = waypoints.to_owned();
let mut best_permutation_waypoints = waypoints.to_owned();
@@ -287,17 +342,12 @@ impl Router {
loop {
let c_first = waypoints.first().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 {
let mut total_d = 0.0;
for pair in waypoints.windows(2) {
match pair {
[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);
}
_ => return Err("Invalid routing parameters!".to_string()),
@@ -313,35 +363,19 @@ impl Router {
}
}
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,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(
&self,
- waypoints: &[(&String, [f32; 3])],
+ waypoints: &Vec,
range: f32,
mode: Mode,
factor: f32,
- ) -> Result,String> {
+ ) -> Result, String> {
let mut route: Vec = Vec::new();
for pair in waypoints.windows(2) {
- match *pair {
+ match pair.clone() {
[src, dst] => {
let block = match mode {
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)
}
- fn name_to_systems(&self, name: &str) -> Result,String> {
+ fn resolve_systems(&self, systems: &[SysEntry]) -> Result, String> {
+ let mut ret = Vec::new();
+ let mut sys_by_id: FnvHashMap = FnvHashMap::default();
+ let mut sys_by_name: FnvHashMap = FnvHashMap::default();
for sys in &self.tree {
- if sys.system == name {
- return Ok(self.neighbours(&sys, 0.0).collect());
+ for ent in systems {
+ match ent {
+ SysEntry::ID(i) => {
+ let i = *i;
+ if sys.id == i {
+ sys_by_id.insert(i, sys);
+ }
+ }
+ SysEntry::Name(n) => {
+ if &sys.body == n || &sys.system == n {
+ sys_by_name.insert(n.to_string(), sys);
+ }
+ }
+ }
}
}
- Err(format!("System not found: \"{}\"", name))
+ 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(
&self,
- src: &(&String, [f32; 3]),
- dst: &(&String, [f32; 3]),
+ src: &System,
+ dst: &System,
range: f32,
factor: f32,
- ) -> Result,String> {
+ ) -> Result, String> {
if factor == 0.0 {
return self.route_bfs(src, dst, range);
}
- let (src_name, src) = src;
- let (dst_name, dst) = dst;
- let start_sys = self.closest(src);
- let goal_sys = self.closest(dst);
- let d_total = dist(&start_sys.pos,&goal_sys.pos);
- let mut d_rem=d_total;
-
- let mut state=SearchState {
- mode:"A-Star".into(),
- depth:0,
- queue_size:0,
+ let src_name = src.system.clone();
+ let dst_name = dst.system.clone();
+ let start_sys = src;
+ let goal_sys = dst;
+ let d_total = dist(&start_sys.pos, &goal_sys.pos);
+ let mut d_rem = d_total;
+
+ let mut state = SearchState {
+ mode: "A-Star".into(),
+ depth: 0,
+ queue_size: 0,
d_rem: d_total,
- d_total: d_total,
+ d_total,
prc_done: 0.0,
- n_seen:0,
+ n_seen: 0,
prc_seen: 0.0,
body: start_sys.body.clone(),
- system: start_sys.system.clone()
+ system: start_sys.system.clone(),
};
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 seen = FnvHashSet::default();
let mut found = false;
- let mut maxd = 0;
let mut queue: Vec<(usize, usize, &System)> = Vec::new();
queue.push((
0, // depth
@@ -417,31 +483,22 @@ impl Router {
seen.insert(start_sys.id);
while !(queue.is_empty() || found) {
while let Some((depth, _, sys)) = queue.pop() {
- if (depth+1) > maxd {
- maxd = depth+1;
- 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;
- state.body=sys.body.clone();
- state.system=sys.system.clone();
+ if t_last.elapsed().as_millis() > 100 {
+ t_last = Instant::now();
+ 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;
+ state.body = sys.body.clone();
+ state.system = sys.system.clone();
match (self.callback)(&state) {
Ok(_) => (),
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 {
found = true;
@@ -449,16 +506,15 @@ impl Router {
}
queue.extend(
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))
.map(|nb| {
prev.insert(nb.id, sys);
- let d_g = (nb.distp(goal_sys) / range) as usize;
- let dist = dist(&nb.pos, &goal_sys.pos);
- if dist < d_rem {
- d_rem = dist;
+ let d_g=nb.distp(goal_sys);
+ if d_g = Vec::new();
let mut curr_sys = goal_sys;
@@ -494,54 +550,54 @@ impl Router {
pub fn route_greedy(
&self,
- src: &(&String, [f32; 3]),
- dst: &(&String, [f32; 3]),
+ src: &System,
+ dst: &System,
range: f32,
- ) -> Result,String> {
- let (src_name, src) = src;
- let (dst_name, dst) = dst;
- let start_sys = self.closest(src);
- let goal_sys = self.closest(dst);
+ ) -> Result, String> {
+ let src_name = src.system.clone();
+ let dst_name = dst.system.clone();
+ let start_sys = src;
+ let goal_sys = dst;
let d_total = dist(&start_sys.pos, &goal_sys.pos);
- let mut d_rem=d_total;
- let mut state=SearchState {
- mode:"Greedy".into(),
- depth:0,
- queue_size:0,
+ let mut d_rem = d_total;
+ let mut state = SearchState {
+ mode: "Greedy".into(),
+ depth: 0,
+ queue_size: 0,
d_rem: d_total,
- d_total: d_total,
+ d_total,
prc_done: 0.0,
- n_seen:0,
+ n_seen: 0,
prc_seen: 0.0,
- body:start_sys.body.clone(),
- system:start_sys.system.clone(),
+ body: start_sys.body.clone(),
+ system: start_sys.system.clone(),
};
let total = self.tree.size() as f32;
+ let mut t_last = Instant::now();
let mut prev = FnvHashMap::default();
let mut seen = FnvHashSet::default();
let mut found = false;
- let mut maxd = 0;
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);
while !(queue.is_empty() || found) {
while let Some((_, _, depth, sys)) = queue.pop() {
- if (depth+1) > maxd {
- 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;
- state.body=sys.body.clone();
- state.system=sys.system.clone();
+ if t_last.elapsed().as_millis() > 100 {
+ t_last = Instant::now();
+ 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;
+ state.body = sys.body.clone();
+ state.system = sys.system.clone();
match (self.callback)(&state) {
Ok(_) => (),
Err(e) => {
- return Err(format!("{:?}",e).to_string());
+ return Err(format!("{:?}", e).to_string());
}
};
- maxd = depth+1;
}
if sys.id == goal_sys.id {
found = true;
@@ -549,15 +605,15 @@ impl Router {
}
queue.extend(
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))
.map(|nb| {
prev.insert(nb.id, sys);
- let dist = dist(&nb.pos, &goal_sys.pos);
- if dist < d_rem {
- d_rem = dist;
+ let d_g=nb.distp(goal_sys);
+ if d_g = Vec::new();
let mut curr_sys = goal_sys;
@@ -582,10 +638,7 @@ impl Router {
Ok(v)
}
- pub fn precompute(&mut self, src: &str) -> 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();
+ pub fn precompute(&mut self, src: &System) -> Result<(), String> {
let total = self.tree.size() as f32;
let t_start = Instant::now();
let mut prev = FnvHashMap::default();
@@ -593,8 +646,8 @@ impl Router {
let mut depth = 0;
let mut queue: VecDeque<(usize, &System)> = VecDeque::new();
let mut queue_next: VecDeque<(usize, &System)> = VecDeque::new();
- queue.push_front((0, &sys));
- seen.insert(sys.id);
+ queue.push_front((0, &src));
+ seen.insert(src.id);
while !queue.is_empty() {
print!(
"[{}] Depth: {}, Queue: {}, Seen: {} ({:.02}%) \r",
@@ -622,7 +675,7 @@ impl Router {
self.route_tree = Some(prev);
let ofn = format!(
"{}_{}{}.router",
- src.replace("*", "").replace(" ", "_"),
+ src.system.replace("*", "").replace(" ", "_"),
self.range,
if self.primary_only { "_primary" } else { "" }
);
@@ -634,13 +687,17 @@ impl Router {
String::from(self.path.to_str().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(()),
- 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,String> {
+ fn get_systems_by_ids(
+ &mut self,
+ path: &PathBuf,
+ ids: &[u32],
+ ) -> Result, String> {
let mut ret = FnvHashMap::default();
if let Some(c) = &mut self.cache.as_mut() {
let mut missing = false;
@@ -659,13 +716,12 @@ impl Router {
return Ok(ret);
}
}
- let mut reader = match csv::ReaderBuilder::new()
- .from_path(path) {
- Ok(reader) => reader,
- Err(e) => {
- return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e));
- }
- };
+ let mut reader = match csv::ReaderBuilder::new().from_path(path) {
+ Ok(reader) => reader,
+ Err(e) => {
+ return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e));
+ }
+ };
reader
.deserialize::()
.map(|res| res.unwrap())
@@ -674,30 +730,20 @@ impl Router {
ret.insert(sys.id, sys.build());
})
.count();
+ for id in ids {
+ if !ret.contains_key(&id) {
+ return Err(format!("ID {} not found", id));
+ }
+ }
Ok(ret)
}
- fn get_system_by_name(path: &PathBuf, name: &str) -> Result {
- // TODO: Fuzzy search (https://github.com/andylokandy/simsearch-rs)
- let mut reader = csv::ReaderBuilder::new()
- .from_path(path)
- .unwrap_or_else(|e| {
- eprintln!("Error opening {}: {}", path.to_str().unwrap(), e);
- std::process::exit(1);
- });
- let sys = reader
- .deserialize::()
- .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,String> {
+ pub fn route_to(
+ &mut self,
+ dst: &System,
+ systems_path: &PathBuf,
+ ) -> Result, String> {
let prev = self.route_tree.as_ref().unwrap();
- let dst = Self::get_system_by_name(&systems_path, dst)?;
if !prev.contains_key(&dst.id) {
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) {
Some(sys) => sys,
None => {
- return Err(format!("System-ID {} not found!",sys_id));
+ return Err(format!("System-ID {} not found!", sys_id));
}
};
v.push(sys.clone())
@@ -729,29 +775,29 @@ impl Router {
pub fn route_bfs(
&self,
- src: &(&String, [f32; 3]),
- dst: &(&String, [f32; 3]),
+ start_sys: &System,
+ goal_sys: &System,
range: f32,
- ) -> Result,String> {
+ ) -> Result, String> {
println!("Running BFS");
- let (src_name, src) = src;
- let (dst_name, dst) = dst;
- let start_sys = self.closest(src);
- let goal_sys = self.closest(dst);
+ let src_name = start_sys.system.clone();
+ let dst_name = goal_sys.system.clone();
let d_total = dist(&start_sys.pos, &goal_sys.pos);
- let mut state=SearchState {
- mode:"BFS".into(),
- depth:0,
- queue_size:0,
- d_rem: d_total,
- d_total: d_total,
+ let mut d_rem = d_total;
+ let mut state = SearchState {
+ mode: "BFS".into(),
+ depth: 0,
+ queue_size: 0,
+ d_rem,
+ d_total,
prc_done: 0.0,
- n_seen:0,
+ n_seen: 0,
prc_seen: 0.0,
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!(
"Jump Range: {} Ly, Distance: {} Ly, Estimated Jumps: {}",
@@ -765,41 +811,47 @@ impl Router {
let mut seen = FnvHashSet::default();
let mut depth = 0;
let mut found = false;
+ let mut t_last = Instant::now();
let mut queue: 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);
queue.push_front((0, &start_sys));
seen.insert(start_sys.id);
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() {
if sys.id == goal_sys.id {
found = true;
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(
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))
.map(|nb| {
prev.insert(nb.id, sys);
- let dist = dist(&nb.pos, &goal_sys.pos);
+ let dist = nb.distp(goal_sys);
if dist < d_rem {
d_rem = dist;
}
@@ -813,7 +865,7 @@ impl Router {
println!();
println!();
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 = Vec::new();
let mut curr_sys = goal_sys;
@@ -830,54 +882,71 @@ impl Router {
Ok(v)
}
}
-pub fn route(opts: RouteOpts) -> Result