11 Commits
1.1 ... 1.3

Author SHA1 Message Date
28a54d14f0 Added simple config editor
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-08-22 10:26:50 +07:00
34f38b5a59 Update
* Updated build.spec for PyInstaller build
* Some code and typo fixes

Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-08-22 10:25:34 +07:00
33ce4d1148 Typo fixes
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-08-05 18:46:02 +07:00
4dcfe37c5b Added version.cfg
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-08-02 17:54:16 +07:00
8a304075a1 Update
* Added validator for ADR (module 'main')
* Added window for choice configs (module 'choice')
* Added sync configs from github (this repo, module 'parsing')
* Updated setup.py for correct project build
* Small code fixes

Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-08-02 13:30:06 +07:00
b313dcaa52 Updated ATS configs (Added DLC 'Idaho')
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-08-01 23:28:51 +07:00
950ed7678f Small update of second form
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-07-11 16:00:54 +07:00
Lev
ba0c03f051 Update README.md
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-07-11 16:00:53 +07:00
JDM170
d7b1e4322e Update
* Added .gitignore
* Added build.spec for compiling project with PyInstaller
* Updated font on all window elements
* Recoded functions:
** purchased_garages
** add_garage
** add_all_garages
* Typo fixes

Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-07-11 16:00:53 +07:00
JDM170
d58996bd2f Cosmetic code changes, fix crash when applying changes
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-07-11 16:00:53 +07:00
JDM170
e3e91d9665 Added dealers and agencies from 'Beyond the Baltic Sea', 'Road to the Black Sea'
Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com>
2020-07-11 16:00:52 +07:00
54 changed files with 1887 additions and 752 deletions

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
## Ignoring PyCharm settings
/.idea
## Ignoring Python complied files
/__pycache__
/parsing/__pycache__
/choice/__pycache__
/choice/form.py
/main/__pycache__
/main/form.py
/second/__pycache__
/second/form.py
/config_editor/__pycache__
/config_editor/form.py
## Ignoring UPX
/upx
## Ignoring build from cx_Freeze
/prog_build
## Ignoring build files from PyInstaller
/build
/dist

View File

@@ -6,10 +6,6 @@
***
The program allows you to edit ETS2 and ATS saves, just place 'dlc.json', 'dealers.json' and 'agencies.json' files next to the executable SaveWizard.exe.
***
Features:
1. Decrypt file, if save file crypted
2. Check for DLC to the save file
@@ -21,9 +17,11 @@ Features:
***
Requirments:
Python 3.5.4,
PyQt 5.6.0
Requirments to build project:
* Python >=3.5.4
* PyQt5 >=5.6.0
* requests >=2.24.0
* cx_Freeze >=6.0 (or PyInstaller >=3.6)
***

View File

@@ -1,11 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
if __name__ == '__main__':
from sys import argv, exit
from PyQt5.QtWidgets import QApplication
from main.script import MainWindow
app = QApplication(argv)
win = MainWindow()
win.show()
exit(app.exec_())

View File

@@ -1,9 +0,0 @@
{
"base": ["bakersfield", "fresno", "los_angeles", "oxnard", "redding", "san_diego",
"san_rafael", "santa_cruz", "stockton", "carson_city", "las_vegas"],
"arizona": ["phoenix", "sierra_vista", "tucson"],
"new_mexico": ["carlsbad_nm", "farmington", "roswell", "santa_fe"],
"oregon": ["bend", "eugene", "ontario", "salem"],
"washington": ["bellingham", "olympia", "seattle", "wenatchee", "yakima"],
"utah": ["moab", "salt_lake_city", "st_george"]
}

View File

@@ -1,8 +0,0 @@
{
"base": ["bakersfield", "los_angeles", "sacramento", "santa_cruz", "san_diego", "san_francisco"],
"arizona": ["flagstaff", "phoenix", "tucson", "yuma"],
"new_mexico": ["alamogordo", "albuquerque", "farmington", "hobbs"],
"oregon": ["eugene", "medford", "pendleton", "portland", "salem"],
"washington": ["bellingham", "seattle", "spokane", "tacoma", "yakima"],
"utah": ["ogden", "price", "provo", "salina", "salt_lake_city", "vernal"]
}

View File

@@ -1,7 +0,0 @@
{
"arizona": "company.volatile.aport_phx.phoenix",
"new_mexico": "company.volatile.aport_abq.albuquerque",
"oregon": "company.volatile.aport_pcc.portland",
"washington": "company.volatile.port_sea.seattle",
"utah": "company.volatile.gal_oil_sit.price"
}

62
build.spec Normal file
View File

@@ -0,0 +1,62 @@
# -*- mode: python ; coding: utf-8 -*-
app = Analysis(
['init_main_program.py'],
pathex=['.'],
datas=[
('configs/ats', 'configs/ats'),
('configs/ets2', 'configs/ets2')
]
)
cfg = Analysis(
['init_config_editor.py'],
pathex=['.']
)
MERGE(
(app, 'SaveWizard', 'SaveWizard'),
(cfg, 'SaveWizard_Config_Editor', 'SaveWizard_Config_Editor')
)
app_pyz = PYZ(app.pure, app.zipped_data)
cfg_pyz = PYZ(cfg.pure, cfg.zipped_data)
app_exe = EXE(
app_pyz,
app.scripts,
[],
exclude_binaries=True,
name='SaveWizard',
debug=False,
bootloader_ignore_signals=False,
strip=False,
console=False
)
app_coll = COLLECT(
app_exe,
app.binaries,
app.zipfiles,
app.datas,
strip=False,
name='app_build'
)
cfg_exe = EXE(
cfg_pyz,
cfg.scripts,
[],
exclude_binaries=True,
name='SaveWizard_Config_Editor',
debug=False,
bootloader_ignore_signals=False,
strip=False,
console=False
)
cfg_coll = COLLECT(
cfg_exe,
cfg.binaries,
cfg.zipfiles,
cfg.datas,
strip=False,
name='cfg_build'
)

1
choice/__init__.py Normal file
View File

@@ -0,0 +1 @@
# initialize module 'choice'

107
choice/form.ui Normal file
View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>JDM170</author>
<class>Choice</class>
<widget class="QDialog" name="Choice">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>490</width>
<height>130</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>490</width>
<height>130</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>490</width>
<height>130</height>
</size>
</property>
<property name="windowTitle">
<string>Select game</string>
</property>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>471</width>
<height>111</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QPushButton" name="ets2_button">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>ETS2</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="ats_button">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>ATS</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>18</pointsize>
</font>
</property>
<property name="text">
<string>Select the configs you want to use:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>DON'T USE CONFIGS FROM ANOTHER GAME INTENTIONALLY,
YOU CAN DAMAGE THE GAME'S SAVE.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<tabstops>
<tabstop>ats_button</tabstop>
<tabstop>ets2_button</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

58
choice/script.py Normal file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QMessageBox
from ast import literal_eval
from .form import Ui_Choice
from main.script import MainWindow
from parsing.script import check_remote_hashes, update_configs
from statics import update_config_name
class ChoiceWindow(QDialog, Ui_Choice):
def __init__(self, parent=None):
# Setup UI
QDialog.__init__(self, parent, flags=Qt.Window)
Ui_Choice.__init__(self)
self.ui = Ui_Choice()
self.ui.setupUi(self)
self.ui.ats_button.clicked.connect(self.button_clicked)
self.ui.ets2_button.clicked.connect(self.button_clicked)
remember_data = {"answer_updates": True, "update_on_start": False}
try:
with open(update_config_name) as f:
remember_data = literal_eval(f.read())
except FileNotFoundError:
with open(update_config_name, "w") as f:
f.write(str(remember_data))
upd_list = check_remote_hashes()
if upd_list and len(upd_list) > 0:
answer = remember_data.get("answer_updates")
if answer:
box = QMessageBox(QMessageBox.Information, "Info",
"Some configs have been updated. Do you want to update the local configs?")
box.addButton("Yes", QMessageBox.YesRole) # 0
box.addButton("Yes, remember that", QMessageBox.YesRole) # 1
box.addButton("No", QMessageBox.NoRole) # 2
box.addButton("No, remember that", QMessageBox.NoRole) # 3
update_configs(box.exec(), upd_list)
return
upd_on_start = remember_data.get("update_on_start")
if upd_on_start:
update_configs(1, upd_list)
def button_clicked(self):
sender = self.sender()
if sender == self.ui.ats_button:
selected = "ats"
elif sender == self.ui.ets2_button:
selected = "ets2"
else:
return
self.close()
win = MainWindow(selected)
win.exec()

1
compile_cx-freeze.bat Normal file
View File

@@ -0,0 +1 @@
python setup.py build

1
compile_pyinstaller.bat Normal file
View File

@@ -0,0 +1 @@
pyinstaller build.spec --noupx

View File

@@ -1 +0,0 @@
python setup.py build

View File

@@ -0,0 +1 @@
# initializing module 'config_editor'

133
config_editor/form.ui Normal file
View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>JDM170</author>
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>504</width>
<height>374</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>SaveWizard config editor</string>
</property>
<property name="dockOptions">
<set>QMainWindow::AllowTabbedDocks</set>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>501</width>
<height>351</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Verdana</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>504</width>
<height>21</height>
</rect>
</property>
<property name="defaultUp">
<bool>true</bool>
</property>
<property name="nativeMenuBar">
<bool>false</bool>
</property>
<widget class="QMenu" name="menuOptions">
<property name="title">
<string>Options</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
<addaction name="actionSave_As"/>
<addaction name="separator"/>
<addaction name="actionMD5"/>
<addaction name="separator"/>
<addaction name="actionCloseFile"/>
<addaction name="actionExit"/>
</widget>
<addaction name="menuOptions"/>
</widget>
<action name="actionOpen">
<property name="text">
<string>Open</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionSave">
<property name="text">
<string>Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionSave_As">
<property name="text">
<string>Save As</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="actionCloseFile">
<property name="text">
<string>Close file</string>
</property>
<property name="toolTip">
<string>Closing current file</string>
</property>
<property name="shortcut">
<string>Ctrl+W</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="actionMD5">
<property name="text">
<string>Copy MD5</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

113
config_editor/script.py Normal file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QResizeEvent, QCloseEvent, QClipboard
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QApplication
from ast import literal_eval
from .form import Ui_MainWindow
from dataIO import dataIO
from util import generate_md5
class EditorWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent, flags=Qt.Window)
Ui_MainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.file_path = ""
self.win_title = self.tr("{}".format(self.windowTitle()))
self.ui.textEdit.document().contentsChanged.connect(self.content_changed)
for action, method in {
self.ui.actionOpen: self.open_file,
self.ui.actionSave: self.save_file,
self.ui.actionSave_As: self.save_as,
self.ui.actionMD5: self.copy_hash,
self.ui.actionCloseFile: self.close_file,
self.ui.actionExit: self.exit
}.items():
action.triggered.connect(method)
def resizeEvent(self, event: QResizeEvent):
window = self.ui.centralwidget.geometry().getCoords()
edit = self.ui.textEdit.geometry().getCoords()
self.ui.textEdit.setGeometry(edit[0], edit[1],
window[2], window[3]-(self.ui.menubar.size().height()-1))
def closeEvent(self, event: QCloseEvent):
if self.maybe_save():
event.accept()
else:
event.ignore()
def content_changed(self):
self.setWindowModified(self.ui.textEdit.document().isModified())
def open_file(self):
file_path, file_name = QFileDialog.getOpenFileName(parent=self,
caption=self.tr("Choose config..."),
filter=self.tr("*.json"))
if file_path != "":
self.file_path = file_path
with open(file_path) as f:
self.ui.textEdit.setPlainText(f.read())
self.setWindowTitle(self.tr("[*]{} - {}".format(file_path, self.win_title)))
self.ui.textEdit.document().setModified(False)
self.setWindowModified(False)
def save_file(self):
if self.file_path != "":
data = literal_eval(self.ui.textEdit.toPlainText())
ret = dataIO.save_json(self.file_path, data)
if ret:
self.ui.textEdit.document().setModified(False)
self.setWindowModified(False)
return ret
def save_as(self):
file_path, file_name = QFileDialog.getSaveFileName(parent=self,
caption=self.tr("Select position"),
filter=self.tr("*.json"))
file_data = literal_eval(self.ui.textEdit.toPlainText())
ret = dataIO.save_json(file_path, file_data)
if ret:
self.file_path = file_path
self.setWindowTitle(self.tr("[*]{} - {}".format(file_path, self.win_title)))
self.ui.textEdit.document().setModified(False)
self.setWindowModified(False)
def copy_hash(self):
if self.maybe_save():
result = generate_md5(self.file_path)
clip = QApplication.clipboard()
QClipboard.setText(clip, result)
box = QMessageBox(QMessageBox.Information, "Information", "Hash successfully copied into your clipboard.")
box.exec()
def close_file(self):
if self.maybe_save():
self.setWindowTitle(self.win_title)
self.ui.textEdit.clear()
self.file_path = ""
def exit(self):
self.close()
def maybe_save(self):
if not self.ui.textEdit.document().isModified():
return True
box = QMessageBox.warning(self,
self.tr("App"),
self.tr("The document has been modified.\nDo you want to save your changes?"),
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
if box == QMessageBox.Save:
return self.save_file()
elif box == QMessageBox.Discard:
return True
elif box == QMessageBox.Cancel:
return False
return True

50
configs/ats/agencies.json Normal file
View File

@@ -0,0 +1,50 @@
{
"arizona" : [
"phoenix",
"sierra_vista",
"tucson"
],
"base" : [
"bakersfield",
"fresno",
"los_angeles",
"oxnard",
"redding",
"san_diego",
"san_rafael",
"santa_cruz",
"stockton",
"carson_city",
"las_vegas"
],
"idaho" : [
"boise",
"coeur_dalene",
"idaho_falls",
"twin_falls"
],
"new_mexico" : [
"carlsbad_nm",
"farmington",
"roswell",
"santa_fe"
],
"oregon" : [
"bend",
"eugene",
"ontario",
"salem"
],
"utah" : [
"moab",
"salt_lake_city",
"st_george"
],
"washington" : [
"bellingham",
"olympia",
"seattle",
"wenatchee",
"yakima"
]
}

49
configs/ats/dealers.json Normal file
View File

@@ -0,0 +1,49 @@
{
"arizona" : [
"flagstaff",
"phoenix",
"tucson",
"yuma"
],
"base" : [
"bakersfield",
"los_angeles",
"sacramento",
"santa_cruz",
"san_diego",
"san_francisco"
],
"idaho" : [
"boise",
"idaho_falls",
"twin_falls"
],
"new_mexico" : [
"alamogordo",
"albuquerque",
"farmington",
"hobbs"
],
"oregon" : [
"eugene",
"medford",
"pendleton",
"portland",
"salem"
],
"utah" : [
"ogden",
"price",
"provo",
"salina",
"salt_lake_city",
"vernal"
],
"washington" : [
"bellingham",
"seattle",
"spokane",
"tacoma",
"yakima"
]
}

8
configs/ats/dlc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"arizona" : "company.volatile.aport_phx.phoenix",
"idaho" : "company.volatile.du_farm.nampa",
"new_mexico" : "company.volatile.aport_abq.albuquerque",
"oregon" : "company.volatile.aport_pcc.portland",
"utah" : "company.volatile.gal_oil_sit.price",
"washington" : "company.volatile.port_sea.seattle"
}

117
configs/ets2/agencies.json Normal file
View File

@@ -0,0 +1,117 @@
{
"balticsea" : [
"daugavpils",
"helsinki",
"kaliningrad",
"kaunas",
"klaipeda",
"kouvola",
"lahti",
"parnu",
"pori",
"pskov",
"riga",
"tallinn",
"turku",
"vilnius"
],
"base" : [
"aberdeen",
"berlin",
"bialystok",
"birmingham",
"bremen",
"brno",
"brussel",
"calais",
"debrecen",
"dortmund",
"dover",
"dresden",
"edinburgh",
"frankfurt",
"glasgow",
"graz",
"grohningen",
"hamburg",
"hannover",
"innsbruck",
"kassel",
"klagenfurt",
"koln",
"kosice",
"leipzig",
"liege",
"linz",
"liverpool",
"lodz",
"london",
"luxembourg",
"manchester",
"mannheim",
"munchen",
"newcastle",
"nurnberg",
"ostrava",
"pecs",
"plymouth",
"poznan",
"prague",
"sheffield",
"southampton",
"stuttgart",
"swansea",
"szczecin",
"wien",
"zurich"
],
"blacksea" : [
"bucuresti",
"cluj_napoca",
"iasi",
"istanbul",
"plovdiv",
"sofia"
],
"east" : [
"budapest",
"gdansk",
"krakow",
"szeged",
"warszava"
],
"france" : [
"bordeaux",
"clermont",
"geneve",
"larochelle",
"lyon",
"marseille",
"metz",
"paris",
"reims",
"rennes",
"toulouse"
],
"italy" : [
"bologna",
"catania",
"milano",
"napoli",
"pescara",
"roma",
"taranto",
"venezia"
],
"scandinavia" : [
"aalborg",
"bergen",
"helsingborg",
"kobenhavn",
"malmo",
"odense",
"oslo",
"stavanger",
"stockholm"
]
}

114
configs/ets2/dealers.json Normal file
View File

@@ -0,0 +1,114 @@
{
"balticsea" : [
"helsinki",
"kaliningrad",
"kaunas",
"klaipeda",
"lahti",
"petersburg",
"riga",
"tallinn",
"tartu",
"turku",
"vilnius"
],
"base" : [
"aberdeen",
"amsterdam",
"berlin",
"bern",
"birmingham",
"bratislava",
"bremen",
"brussel",
"calais",
"cardiff",
"dortmund",
"dortmund",
"dresden",
"dusseldorf",
"edinburgh",
"felixstowe",
"frankfurt",
"glasgow",
"graz",
"grimsby",
"hamburg",
"hannover",
"leipzig",
"lille",
"london",
"luxembourg",
"manchester",
"munchen",
"newcastle",
"nurnberg",
"osnabruck",
"plymouth",
"prague",
"rostock",
"rotterdam",
"salzburg",
"strasbourg",
"stuttgart",
"szczecin",
"wien",
"wroclaw",
"zurich"
],
"blacksea" : [
"brasov",
"bucuresti",
"cluj_napoca",
"constanta",
"edirne",
"galati",
"iasi",
"istanbul",
"pitesti",
"plovdiv",
"sofia",
"veliko_tarnovo"
],
"east" : [
"budapest",
"gdansk",
"krakow",
"szeged",
"warszawa"
],
"france" : [
"bordeaux",
"bourges",
"brest",
"geneve",
"lemans",
"limoges",
"lyon",
"marseille",
"nantes",
"paris",
"toulouse"
],
"italy" : [
"bologna",
"catania",
"firenze",
"milano",
"napoli",
"palermo",
"roma",
"taranto",
"torino",
"verona"
],
"scandinavia" : [
"bergen",
"goteborg",
"kalmar",
"kobenhavn",
"linkoping",
"oslo",
"stockholm"
]
}

8
configs/ets2/dlc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"balticsea" : "company.volatile.polarislines.tallinn",
"blacksea" : "company.volatile.bhv.galati",
"east" : "company.volatile.quarry.katowice",
"france" : "company.volatile.lisette_log.roscoff",
"italy" : "company.volatile.marina_it.ancona",
"scandinavia" : "company.volatile.sag_tre.oslo"
}

8
configs/version.cfg Normal file
View File

@@ -0,0 +1,8 @@
{
"ats_dlc": "c07eea9c3358aaea310ebf4808244082",
"ats_agencies": "21a34efef91f93e3dde2eadb692d2e54",
"ats_dealers": "88bc97c2276b198f80c885052b8ac1ab",
"ets2_dlc": "efa15bc58f98eadbcae350f3eb583040",
"ets2_agencies": "3d44d5c82db5e9c98adb61e36e6698fd",
"ets2_dealers": "446d5a4f984c87aa8a99fa1d78431f26"
}

View File

@@ -1,26 +1,16 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from json import decoder, load, dump
from os import replace
from os.path import splitext
from random import randint
class InvalidFileIO(Exception):
pass
class DataIO:
@staticmethod
def _read_json(filename):
with open(filename, encoding="utf-8", mode="r") as f:
with open(filename, encoding="utf-8") as f:
data = load(f)
return data
@staticmethod
def _save_json(filename, data):
with open(filename, encoding="utf-8", mode="w") as f:
dump(data, f, indent=4, sort_keys=True, separators=(",", " : "))
return data
def is_valid_json(self, filename):
"""Verifies if json file exists / is readable"""
try:
@@ -37,41 +27,13 @@ class DataIO:
def save_json(self, filename, data):
"""Atomically saves json file"""
rnd = randint(1000, 9999)
path, ext = splitext(filename)
tmp_file = "{}-{}.tmp".format(path, rnd)
self._save_json(tmp_file, data)
with open(filename, encoding="utf-8", mode="w") as f:
dump(data, f, indent=4, separators=(",", " : "))
try:
self._read_json(tmp_file)
self._read_json(filename)
except decoder.JSONDecodeError:
return False
replace(tmp_file, filename)
return True
def _legacy_fileio(self, filename, IO, data=None):
"""Old fileIO provided for backwards compatibility"""
if (IO == "save") and data is not None:
return self.save_json(filename, data)
elif (IO == "load") and data is None:
return self.load_json(filename)
elif (IO == "check") and data is None:
return self.is_valid_json(filename)
else:
raise InvalidFileIO("FileIO was called with invalid parameters")
def get_value(filename, key):
with open(filename, encoding="utf-8", mode="r") as f:
data = load(f)
return data[key]
def set_value(filename, key, value):
data = fileIO(filename, "load")
data[key] = value
fileIO(filename, "save", data)
return True
dataIO = DataIO()
fileIO = dataIO._legacy_fileio # backwards compatibility

BIN
dlls/imageformats/qgif.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qicns.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qico.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qjpeg.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qsvg.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qtga.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qtiff.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qwbmp.dll Normal file

Binary file not shown.

BIN
dlls/imageformats/qwebp.dll Normal file

Binary file not shown.

BIN
dlls/platforms/qminimal.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
dlls/platforms/qwebgl.dll Normal file

Binary file not shown.

BIN
dlls/platforms/qwindows.dll Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -1,14 +0,0 @@
{
"base": ["aberdeen", "berlin", "bialystok", "birmingham", "bremen", "brno", "brussel", "calais",
"debrecen", "dortmund", "dover", "dresden", "edinburgh", "frankfurt", "glasgow", "graz", "grohningen",
"hamburg", "hannover", "innsbruck", "kassel", "klagenfurt", "koln", "kosice", "leipzig", "liege",
"linz", "liverpool", "lodz", "london", "luxembourg", "manchester", "mannheim", "munchen", "newcastle",
"nurnberg", "ostrava", "pecs", "plymouth", "poznan", "prague", "sheffield", "southampton", "stuttgart",
"swansea", "szczecin", "wien", "zurich"],
"east": ["budapest", "gdansk", "krakow", "szeged", "warszava"],
"scandinavia": ["aalborg", "bergen", "helsingborg", "kobenhavn", "malmo", "odense", "oslo", "stavanger",
"stockholm"],
"france": ["bordeaux", "clermont", "geneve", "larochelle", "lyon", "marseille", "metz", "paris", "reims", "rennes",
"toulouse"],
"italy": ["bologna", "catania", "milano", "napoli", "pescara", "roma", "taranto", "venezia"]
}

View File

@@ -1,12 +0,0 @@
{
"base": ["aberdeen", "amsterdam", "berlin", "bern", "birmingham", "bratislava", "bremen", "brussel", "calais",
"cardiff", "dortmund", "dortmund", "dresden", "dusseldorf", "edinburgh", "felixstowe", "frankfurt", "glasgow",
"graz", "grimsby", "hamburg", "hannover", "leipzig", "lille", "london", "luxembourg", "manchester", "munchen",
"newcastle", "nurnberg", "osnabruck", "plymouth", "prague", "rostock", "rotterdam", "salzburg", "strasbourg",
"stuttgart", "szczecin", "wien", "wroclaw", "zurich"],
"east": ["budapest", "gdansk", "krakow", "szeged", "warszawa"],
"scandinavia": ["bergen", "goteborg", "kalmar", "kobenhavn", "linkoping", "oslo", "stockholm"],
"france": ["bordeaux", "bourges", "brest", "geneve", "lemans", "limoges", "lyon", "marseille", "nantes", "paris",
"toulouse"],
"italy": ["bologna", "catania", "firenze", "milano", "napoli", "palermo", "roma", "taranto", "torino", "verona"]
}

View File

@@ -1,8 +0,0 @@
{
"east": "company.volatile.quarry.katowice",
"scandinavia": "company.volatile.sag_tre.oslo",
"france": "company.volatile.lisette_log.roscoff",
"italy": "company.volatile.marina_it.ancona",
"balticsea": "company.volatile.polarislines.tallinn",
"blacksea": "company.volatile.bhv.galati"
}

12
init_config_editor.py Normal file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from sys import argv, exit
from PyQt5.QtWidgets import QApplication
from config_editor.script import EditorWindow
if __name__ == '__main__':
app = QApplication(argv)
win = EditorWindow()
win.show()
exit(app.exec())

12
init_main_program.py Normal file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from sys import argv, exit
from PyQt5.QtWidgets import QApplication
from choice.script import ChoiceWindow
if __name__ == '__main__':
app = QApplication(argv)
win = ChoiceWindow()
win.show()
exit(app.exec())

View File

@@ -1,2 +1 @@
# initialize module 'main' for compile program
import main.script
# initialize module 'main'

View File

@@ -1,361 +1,516 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>JDM170</author>
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<widget class="QDialog" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>370</height>
<height>350</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>370</height>
<height>350</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>360</width>
<height>370</height>
<height>350</height>
</size>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="windowTitle">
<string>SaveWizard</string>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="apply">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>210</x>
<y>330</y>
<width>141</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Apply changes</string>
</property>
</widget>
<widget class="QPushButton" name="backup">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>10</x>
<y>330</y>
<width>141</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Recover backup</string>
</property>
</widget>
<widget class="QPushButton" name="path_button">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>161</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Choose save file...</string>
</property>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>14</x>
<y>50</y>
<width>331</width>
<height>81</height>
</rect>
</property>
<layout class="QGridLayout" name="basic_inf_layout">
<item row="0" column="1">
<widget class="QLineEdit" name="money_edit"/>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="money_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="xp_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Experience:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="xp_edit"/>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="xp_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="loan_limit_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Loan limit:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="loan_limit_edit"/>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="loan_limit_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="money_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Money:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="gridLayoutWidget_3">
<property name="geometry">
<rect>
<x>14</x>
<y>138</y>
<width>331</width>
<height>161</height>
</rect>
</property>
<layout class="QGridLayout" name="skills_layout">
<item row="1" column="1">
<widget class="QLineEdit" name="long_distance_edit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="urgent_delivery_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Urgent delivery:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="ecodriving_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="adr_edit"/>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="urgent_delivery_edit"/>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="fragile_cargo_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="ecodriving_edit"/>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="high_value_cargo_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="fragile_cargo_edit"/>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="adr_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="long_distance_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="high_value_cargo_edit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="high_value_cargo_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>High value cargo:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="fragile_cargo_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Fragile cargo:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ecodriving_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Ecodriving:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="urgent_delivery_dont_change">
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="long_distance_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Long distance:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="adr_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>ADR:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QToolButton" name="second_window">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>160</x>
<y>340</y>
<width>41</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
<widget class="QCheckBox" name="dont_change_all_inf">
<property name="geometry">
<rect>
<x>90</x>
<y>300</y>
<width>181</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>Don't save all changes in this form</string>
</property>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>341</width>
<height>81</height>
</rect>
</property>
<layout class="QGridLayout" name="basic_inf_layout">
<item row="0" column="1">
<widget class="QLineEdit" name="money_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="money_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="xp_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Experience:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="xp_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="xp_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="loan_limit_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Loan limit:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="loan_limit_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="loan_limit_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="money_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Money:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QPushButton" name="path_button">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>161</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Choose save file...</string>
</property>
</widget>
<widget class="QPushButton" name="backup">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>10</x>
<y>310</y>
<width>141</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Recover backup</string>
</property>
</widget>
<widget class="QCheckBox" name="dont_change_all_inf">
<property name="geometry">
<rect>
<x>80</x>
<y>350</y>
<width>211</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't save all changes in this form</string>
</property>
</widget>
<widget class="QWidget" name="gridLayoutWidget_3">
<property name="geometry">
<rect>
<x>10</x>
<y>140</y>
<width>341</width>
<height>161</height>
</rect>
</property>
<layout class="QGridLayout" name="skills_layout">
<item row="1" column="1">
<widget class="QLineEdit" name="long_distance_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="urgent_delivery_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Urgent delivery:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="ecodriving_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="adr_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="urgent_delivery_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="fragile_cargo_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="ecodriving_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="high_value_cargo_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="fragile_cargo_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="adr_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="long_distance_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="high_value_cargo_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="high_value_cargo_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>High value cargo:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="fragile_cargo_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Fragile cargo:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ecodriving_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Ecodriving:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="urgent_delivery_dont_change">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Don't change</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="long_distance_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Long distance:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="adr_label">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>ADR:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QPushButton" name="apply">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>210</x>
<y>310</y>
<width>141</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Apply changes</string>
</property>
</widget>
<widget class="QToolButton" name="second_window">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>160</x>
<y>320</y>
<width>41</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
<widget class="QLabel" name="chosen_cfgs">
<property name="geometry">
<rect>
<x>210</x>
<y>10</y>
<width>141</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>Chosen configs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QPushButton" name="cfg_button">
<property name="geometry">
<rect>
<x>180</x>
<y>20</y>
<width>21</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</widget>
<tabstops>
<tabstop>path_button</tabstop>
<tabstop>cfg_button</tabstop>
<tabstop>money_edit</tabstop>
<tabstop>money_dont_change</tabstop>
<tabstop>xp_edit</tabstop>
@@ -374,10 +529,10 @@
<tabstop>urgent_delivery_dont_change</tabstop>
<tabstop>ecodriving_edit</tabstop>
<tabstop>ecodriving_dont_change</tabstop>
<tabstop>dont_change_all_inf</tabstop>
<tabstop>backup</tabstop>
<tabstop>second_window</tabstop>
<tabstop>apply</tabstop>
<tabstop>dont_change_all_inf</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@@ -1,16 +1,20 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QMainWindow
from os import system, remove
from PyQt5.QtCore import Qt, QRegExp
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtWidgets import QDialog, QFileDialog
from .form import Ui_MainWindow
from util import *
from dataIO import dataIO
from second.script import SecondWindow
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
from PyQt5.QtCore import Qt
QMainWindow.__init__(self, parent, flags=Qt.Window)
class MainWindow(QDialog, Ui_MainWindow):
def __init__(self, selected_game, parent=None):
# Setup UI
QDialog.__init__(self, parent, flags=Qt.Window)
Ui_MainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
@@ -18,13 +22,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.file_path = ""
self.old_file = ""
if dataIO.is_valid_json("dlc.json") is False:
self.owns = False
show_message("Error", "'dlc.json' not found, functionality has been limited")
else:
self.owns = {}
self.dlc = dataIO.load_json("dlc.json")
self.selected_game = selected_game
self.owns = {}
self.dlc = {}
# Editing label to show what configs chosen
self.chosen_cfg_text = self.ui.chosen_cfgs.text()
self.ui.chosen_cfgs.setText("{} {}".format(self.chosen_cfg_text, selected_game.upper()))
# Storing edits with his checkboxes and file-lines
self.basic_edits = {
self.ui.money_edit: [self.ui.money_dont_change, "money_account:"],
self.ui.xp_edit: [self.ui.xp_dont_change, "experience_points:"],
@@ -38,24 +44,31 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.ecodriving_edit: [self.ui.ecodriving_dont_change, "mechanical:"],
}
from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QRegExpValidator
validator_inf = QRegExpValidator(QRegExp("[0-9]{1,9}"))
# Setting up validators for edits
basic_validator = QRegExpValidator(QRegExp("[0-9]{,9}"))
for key in self.basic_edits.keys():
key.setValidator(validator_inf)
key.setValidator(basic_validator)
key.textEdited.connect(self.text_edited)
self.ui.adr_edit.textEdited.connect(self.text_edited) # TODO: Validator for ADR
validator_skill = QRegExpValidator(QRegExp("[0-6]{1,1}"))
adr_validator_text = ""
for i in range(6):
adr_validator_text += r"\d[., ]?" if i != 5 else r"\d"
self.ui.adr_edit.textEdited.connect(self.text_edited)
self.ui.adr_edit.setValidator(QRegExpValidator(QRegExp(adr_validator_text)))
skills_validator = QRegExpValidator(QRegExp("[0-6]{,1}"))
for key in self.skill_edits.keys():
key.setValidator(validator_skill)
key.setValidator(skills_validator)
key.textEdited.connect(self.text_edited)
self.ui.path_button.clicked.connect(self.open_save)
self.ui.apply.clicked.connect(self.apply_changes)
# Connecting buttons
self.ui.path_button.clicked.connect(self.open_file_dialog)
self.ui.cfg_button.clicked.connect(self.change_configs)
self.ui.backup.clicked.connect(self.recover_backup)
self.ui.second_window.clicked.connect(self.open_second_win)
self.ui.apply.clicked.connect(self.apply_changes)
self.check_config()
self.clear_fields()
def text_edited(self):
sender = self.sender()
@@ -82,10 +95,20 @@ class MainWindow(QMainWindow, Ui_MainWindow):
adr_list.remove(i)
return adr_list
def reopen_file(self):
def check_config(self):
cfg_path = "configs/{}/dlc.json".format(self.selected_game)
if dataIO.is_valid_json(cfg_path) is False:
self.owns = False
show_message(QMessageBox.Warning, "Warning", "'dlc.json' from '{}' have errors or not found, "
"functionality has been limited".format(self.selected_game))
else:
self.owns = {}
self.dlc = dataIO.load_json(cfg_path)
def clear_fields(self):
self.file_path = ""
self.old_file = ""
set_lines("")
set_lines([])
if self.owns is not False:
self.owns = {}
@@ -103,33 +126,34 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.apply.setEnabled(False)
self.ui.backup.setEnabled(False)
self.ui.second_window.setEnabled(False)
# return
def check_save_file(self, file):
def get_file_data(self, file):
try:
with open(file, "r") as f:
with open(file) as f:
self.old_file = f.read()
except UnicodeDecodeError:
try:
from os import system
system("SII_Decrypt.exe --on_file -i \"{}\"".format(file))
with open(file, "r") as f:
with open(file) as f:
self.old_file = f.read()
show_message("Success", "File successfully decrypted.")
show_message(QMessageBox.Information, "Success", "File successfully decrypted.")
except UnicodeDecodeError:
show_message("Error", "Error to decrypt and open file. Try again.")
show_message(QMessageBox.Critical, "Error", "Error to decrypt and open file. "
"Try again.\nIf you still get error on this step,"
"try to change \"uset g_save_format\" to 2, resave game "
"and try again.")
return
set_lines(self.old_file.split("\n"))
if self.owns is not False:
self.owns["base"] = True
for i in get_array_items(search_line("companies:")):
for key, value in self.dlc.items():
if value in i:
self.owns[key] = True
companies = get_array_items(search_line("companies:"))
for key, value in self.dlc.items():
if value in companies:
self.owns[key] = True
for key, value in self.basic_edits.items():
key.setText(str(get_value(search_line(value[1]))))
key.setText(get_value(search_line(value[1])))
adr = self.get_adr(get_value(search_line("adr:")))
adr_list = ""
@@ -138,68 +162,74 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.adr_edit.setText(adr_list)
for key, value in self.skill_edits.items():
key.setText(str(get_value(search_line(value[1]))))
key.setText(get_value(search_line(value[1])))
self.ui.apply.setEnabled(True)
self.ui.backup.setEnabled(True)
self.ui.second_window.setEnabled(True)
def open_save(self):
from PyQt5.QtWidgets import QFileDialog
file, _ = QFileDialog.getOpenFileName(parent=self,
caption=self.tr("Choose your save file..."),
filter=self.tr("game.sii"))
self.reopen_file()
if file != "":
self.file_path = file
self.check_save_file(self.file_path)
def open_file_dialog(self):
file_path, file_name = QFileDialog.getOpenFileName(parent=self,
caption=self.tr("Choose your save file..."),
filter=self.tr("game.sii"))
self.clear_fields()
if file_path != "":
self.file_path = file_path
self.get_file_data(file_path)
else:
return
def change_configs(self):
box = QMessageBox(QMessageBox.Warning, "Warning", "Do you really want to load other configs?\n"
"Your current changes won't be saved.")
box.addButton("Yes", QMessageBox.YesRole)
box.addButton("No", QMessageBox.NoRole)
if box.exec() == 0:
self.clear_fields()
self.selected_game = "ets2" if self.selected_game == "ats" else "ats"
self.ui.chosen_cfgs.setText("{} {}".format(self.chosen_cfg_text, self.selected_game.upper()))
self.check_config()
def recover_backup(self):
try:
backup = self.file_path + ".swbak"
f = open(backup)
with open(self.file_path, "w") as g:
g.write(f.read())
f.close()
remove(backup)
show_message(QMessageBox.Information, "Success", "Backup successfully recovered.")
self.get_file_data(self.file_path)
except IOError:
show_message(QMessageBox.Critical, "Error", "Backup not found.")
def open_second_win(self):
second_win = SecondWindow(self.selected_game, self.owns, self)
second_win.exec()
def apply_changes(self):
if not self.ui.dont_change_all_inf.isChecked():
for key, value in self.basic_edits.items():
if not value[0].isChecked():
if value[0].isChecked() is False:
set_value(search_line(value[1]), key.text())
value[1].setChecked(False)
if not self.ui.adr_dont_change.isChecked():
value[0].setChecked(True)
if self.ui.adr_dont_change.isChecked() is False:
adr_set = self.get_adr_from_line()
if len(adr_set) < 6:
show_message("Error", "ADR can't have less than 6 elements.")
show_message(QMessageBox.Critical, "Error", "ADR can't have less than 6 elements.")
elif len(adr_set) > 6:
show_message("Error", "ADR can't have more than 6 elements.")
show_message(QMessageBox.Critical, "Error", "ADR can't have more than 6 elements.")
else:
adr_new = int("".join(adr_set), 2)
set_value(search_line("adr:"), str(adr_new))
for key, value in self.skill_edits.items():
if not value[0].isChecked():
if value[0].isChecked() is False:
set_value(search_line(value[1]), key.text())
value[1].setChecked(False)
value[0].setChecked(True)
backup = self.file_path + ".swbak"
with open(backup, "w") as f:
f.write(self.old_file)
with open(self.file_path, "w") as f:
f.write("\n".join(get_lines()))
show_message("Success", "Changes successfully applied!")
self.check_save_file(self.file_path)
return
def recover_backup(self):
try:
backup = self.file_path + ".swbak"
f = open(backup, "r")
with open(self.file_path, "w") as g:
g.write(f.read())
f.close()
from os import remove
remove(backup)
show_message("Success", "Backup successfully recovered.")
self.check_save_file(self.file_path)
except IOError:
show_message("Error", "Backup not found.")
return
def open_second_win(self):
from second.script import SecondWindow
second_win = SecondWindow(self.owns, self)
second_win.show()
show_message(QMessageBox.Information, "Success", "Changes successfully applied!")
self.get_file_data(self.file_path)

1
parsing/__init__.py Normal file
View File

@@ -0,0 +1 @@
# initialize module 'parsing'

55
parsing/script.py Normal file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from requests import get
from ast import literal_eval
import os
from statics import github_link, update_config_name
from dataIO import dataIO
from util import generate_md5
def get_response_result(url):
response = get(url)
return response.status_code == 200, response
def check_path(path):
current_path = os.getcwd()
for item in path.split("/"):
current_path = os.path.join(current_path, item)
if not os.path.exists(current_path):
if item.find(".json") > 0:
open(current_path, "w").close()
else:
os.mkdir(current_path)
def check_remote_hashes():
response_status, response = get_response_result(github_link + "configs/version.cfg")
if response_status:
remote_cfg = literal_eval(response.text)
need_update = []
for key, value in remote_cfg.items():
path = key.split("_")
path = "configs/{}/{}.json".format(path[0], path[1])
if generate_md5(path) != value:
need_update.append(path)
return need_update
return False
def update_configs(is_save, cfg_list):
if is_save in (0, 1):
for cfg in cfg_list:
check_path(cfg)
response_status, response = get_response_result(github_link + cfg)
if response_status:
remote_cfg = literal_eval(response.text)
if dataIO.is_valid_json(cfg) or os.path.exists(cfg):
dataIO.save_json(cfg, remote_cfg)
if is_save in (1, 3):
text = str({"answer_updates": is_save == 3,
"update_on_start": is_save == 1})
with open(update_config_name, "w") as f:
f.write(text)

View File

@@ -1,2 +1 @@
# initialize module 'second' for compile program
from second import script
# initialize module 'second'

View File

@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>JDM170</author>
<class>SecondWindow</class>
<widget class="QDialog" name="SecondWindow">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
@@ -41,19 +39,6 @@
</rect>
</property>
<layout class="QGridLayout" name="garages_layout">
<item row="1" column="0">
<widget class="QTextBrowser" name="garages_text">
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="openLinks">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="garages_label">
<property name="font">
@@ -65,6 +50,9 @@
<property name="text">
<string>Owned garages:</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
@@ -83,6 +71,25 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QTextEdit" name="garages_text">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="gridLayoutWidget_5">
@@ -112,15 +119,21 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QTextBrowser" name="cities_text">
<widget class="QTextEdit" name="cities_text">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="openLinks">
<bool>false</bool>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
@@ -153,15 +166,21 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QTextBrowser" name="dealerships_text">
<widget class="QTextEdit" name="dealerships_text">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="openLinks">
<bool>false</bool>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
@@ -194,15 +213,21 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QTextBrowser" name="agencies_text">
<widget class="QTextEdit" name="agencies_text">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="openLinks">
<bool>false</bool>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
@@ -240,7 +265,7 @@
<x>150</x>
<y>10</y>
<width>171</width>
<height>133</height>
<height>135</height>
</rect>
</property>
<layout class="QGridLayout" name="add_garage">
@@ -258,7 +283,14 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="garage_edit"/>
<widget class="QLineEdit" name="garage_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="garage_add_all">
@@ -290,7 +322,14 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QComboBox" name="garage_size"/>
<widget class="QComboBox" name="garage_size">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
</layout>
</widget>
@@ -300,7 +339,7 @@
<x>480</x>
<y>60</y>
<width>171</width>
<height>107</height>
<height>110</height>
</rect>
</property>
<layout class="QGridLayout" name="add_city">
@@ -318,7 +357,14 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="city_edit"/>
<widget class="QLineEdit" name="city_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="city_label">
@@ -357,7 +403,7 @@
<x>150</x>
<y>290</y>
<width>171</width>
<height>107</height>
<height>108</height>
</rect>
</property>
<layout class="QGridLayout" name="add_dealer">
@@ -375,7 +421,14 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="dealer_edit"/>
<widget class="QLineEdit" name="dealer_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="dealer_label">
@@ -414,7 +467,7 @@
<x>480</x>
<y>290</y>
<width>171</width>
<height>107</height>
<height>108</height>
</rect>
</property>
<layout class="QGridLayout" name="add_agency">
@@ -461,7 +514,14 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="agency_edit"/>
<widget class="QLineEdit" name="agency_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
</layout>
</widget>
@@ -492,7 +552,14 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="headquarter_edit"/>
<widget class="QLineEdit" name="headquarter_edit">
<property name="font">
<font>
<family>Times New Roman</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="headquarter_change">

View File

@@ -1,15 +1,22 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog
from .form import Ui_SecondWindow
from util import *
from dataIO import dataIO
garages_stat = {
"Small": [1, 1],
"Medium": [2, 3],
"Big": [3, 5]
}
class SecondWindow(QDialog, Ui_SecondWindow):
def __init__(self, owns_list, parent=None):
from PyQt5.QtCore import Qt
def __init__(self, selected_game, owns_list, parent=None):
# Setup UI
QDialog.__init__(self, parent, flags=Qt.Window)
Ui_SecondWindow.__init__(self)
self.ui = Ui_SecondWindow()
@@ -17,42 +24,60 @@ class SecondWindow(QDialog, Ui_SecondWindow):
self.owns = owns_list # From main window
if dataIO.is_valid_json("dealers.json") is False:
# Checking files
cfg_path = "configs/{}".format(selected_game)
dealers_path = "{}/dealers.json".format(cfg_path)
agencies_path = "{}/agencies.json".format(cfg_path)
if dataIO.is_valid_json(dealers_path) is False:
self.dealers = False
self.ui.dealer_edit.setEnabled(False)
self.ui.dealer_add.setEnabled(False)
self.ui.dealer_add_all.setEnabled(False)
show_message("Error", "'dealers.json' not found, dealers editing has been disabled")
show_message(QMessageBox.Warning, "Warning", "'dealers.json' from '{}' have errors or not found, dealers "
"editing has been disabled".format(selected_game))
else:
self.dealers = []
self.dealers_file = dataIO.load_json("dealers.json")
self.dealers_file = dataIO.load_json(dealers_path)
if dataIO.is_valid_json("agencies.json") is False:
if dataIO.is_valid_json(agencies_path) is False:
self.agencies = False
self.ui.agency_edit.setEnabled(False)
self.ui.agency_add.setEnabled(False)
self.ui.agency_add_all.setEnabled(False)
show_message("Error", "'agencies.json' not found, agencies editing has been disabled")
show_message(QMessageBox.Warning, "Warning", "'agencies.json' from '{}' have errors or not found, agencies "
"editing has been disabled".format(selected_game))
else:
self.agencies = []
self.agencies_file = dataIO.load_json("agencies.json")
self.agencies_file = dataIO.load_json(agencies_path)
self.ui.garage_size.addItem("Small")
self.ui.garage_size.addItem("Medium")
self.ui.garage_size.addItem("Big")
# Dealers and agencies properties
self.da_array = {
self.ui.dealer_add: [self.ui.dealer_edit, "unlocked_dealers:", "Dealership", self.dealers,
self.check_dealers],
self.ui.agency_add: [self.ui.agency_edit, "unlocked_recruitments:", "Recruitment agency",
self.agencies, self.check_agencies],
}
# Connecting buttons
self.ui.garages_analyze.clicked.connect(self.check_garages)
self.ui.garage_add.clicked.connect(self.add_garage)
self.ui.garage_add_all.clicked.connect(self.add_all_garages)
self.ui.headquarter_change.clicked.connect(self.change_headquarter)
self.ui.city_add.clicked.connect(self.add_city)
self.ui.city_add_all.clicked.connect(self.add_all_cities)
self.ui.dealer_add.clicked.connect(self.add_dealer)
self.ui.dealer_add.clicked.connect(self.da_clicked)
self.ui.dealer_add_all.clicked.connect(self.add_all_dealers)
self.ui.agency_add.clicked.connect(self.add_agency)
self.ui.agency_add.clicked.connect(self.da_clicked)
self.ui.agency_add_all.clicked.connect(self.add_all_agencies)
self.initialize_arrays()
if self.owns:
self.fill_list(self.dealers, self.dealers_file)
self.fill_list(self.agencies, self.agencies_file)
# Checking save-file
self.check_cities()
self.check_dealers()
self.check_agencies()
@@ -60,196 +85,178 @@ class SecondWindow(QDialog, Ui_SecondWindow):
@staticmethod
def purchased_garages():
garages = []
i = 0
try:
local_lines = get_lines()
while True:
while "garage : " not in local_lines[i]:
i += 1
city = match(r"garage : garage.(.+) {$", local_lines[i]).group(1)
while "status:" not in local_lines[i]:
i += 1
if "0" not in local_lines[i]:
garages.append(city)
except:
pass
for index in search_all_lines("garage : garage."):
city = match(r"garage : garage.(.+) {$", get_lines(index)).group(1)
if get_value(search_line("status:", start=index)) != "0":
garages.append(city)
return garages
@staticmethod
def cities():
def all_cities():
cities = []
line = search_line(r"companies\[")
local_lines = get_lines()
while "companies[" in local_lines[line]:
city = match(r" companies\[[0-9]+\]: company.volatile.[a-z0-9_]+[.]([a-z_]+)", local_lines[line]).group(1)
for line in get_array_items(search_line("companies:")):
city = match(r"company.volatile.[a-z0-9_]+[.]([a-z_]+)", line).group(1)
if city not in cities:
cities.append(city)
line += 1
return cities
def initialize_arrays(self):
if self.owns is False:
def fill_list(self, array, file):
if array is False:
return
for key in self.owns.keys():
if self.dealers is not False and key in self.dealers_file:
for value in self.dealers_file[key]:
self.dealers.append(value)
if self.agencies is not False and key in self.agencies_file:
for value in self.agencies_file[key]:
self.agencies.append(value)
if key not in file:
continue
for value in file[key]:
array.append(value)
def check_garage_size(self):
text = self.ui.garage_size.currentText()
garage_size = 0
garage_status = 0
if text == "Small":
garage_size = 1
garage_status = 1
elif text == "Medium":
garage_size = 3
garage_status = 2
elif text == "Big":
garage_size = 5
garage_status = 3
return garage_size, str(garage_status)
stat = garages_stat[self.ui.garage_size.currentText()]
return str(stat[0]), stat[1]
def check_garages(self):
self.ui.garages_text.clear()
for garage in self.purchased_garages():
garages = self.purchased_garages()
for garage in garages:
self.ui.garages_text.append(garage)
hq = get_value(search_line("hq_city:"))
self.ui.headquarter_edit.setText(hq)
self.ui.garages_text.scrollToAnchor(garages[0])
def add_garage(self):
garage = self.ui.garage_edit.text().lower()
if garage is "":
show_message("Error", "Enter a name for the city.")
show_message(QMessageBox.Critical, "Error", "Enter city name!")
return
garage_size, garage_status = self.check_garage_size()
self.ui.garage_edit.setText("")
if get_value(search_line_in_unit("status:", "garage." + garage)) != "0":
show_message("Error", "Garage in \"{}\" already unlocked.".format(garage))
reg_garage = "garage." + garage
current_status = search_line_in_unit("status:", reg_garage)
if get_value(current_status) == "0":
new_status, size = self.check_garage_size()
set_value(current_status, new_status)
vehicles_array = search_line_in_unit("vehicles:", reg_garage)
drivers_array = search_line_in_unit("drivers:", reg_garage)
for i in range(1, size+1):
add_array_value(vehicles_array, "null")
add_array_value(drivers_array+i, "null")
show_message(QMessageBox.Information, "Success", "Garage in \"{}\" successfully unlocked.".format(garage))
else:
set_value(search_line_in_unit("status:", "garage." + garage), garage_status)
for i in range(garage_size):
add_array_value(search_line_in_unit("vehicles:", "garage." + garage), "null")
add_array_value(search_line_in_unit("drivers:", "garage." + garage), "null")
show_message("Success", "Garage in \"{}\" successfully unlocked.".format(garage))
self.check_garages()
show_message(QMessageBox.Critical, "Error", "Garage in \"{}\" already unlocked.".format(garage))
def add_all_garages(self):
garage_size, garage_status = self.check_garage_size()
line = 0
try:
while True:
line = search_line("garage : garage.", start=line)
if get_value(search_line_in_unit("status:", get_unit_name(line))) == "0":
set_value(search_line_in_unit("status:", get_unit_name(line)), garage_status)
for i in range(garage_size):
add_array_value(search_line_in_unit("vehicles:", get_unit_name(line)), "null")
add_array_value(search_line_in_unit("drivers:", get_unit_name(line)), "null")
line += 1
except:
pass
show_message("Success", "All garages successfully unlocked.")
self.check_garages()
new_status, size = self.check_garage_size()
for item in get_array_items(search_line("garages:")):
item = match(r"garage.(.+)$", item).group(1)
current_garage = search_line("garage : garage."+item+" {")
current_status = search_line("status:", start=current_garage)
if get_value(current_status) == "0":
set_value(current_status, new_status)
vehicles_array = search_line("vehicles:", start=current_garage)
drivers_array = search_line("drivers:", start=current_garage)
for i in range(1, size+1):
add_array_value(vehicles_array, "null")
add_array_value(drivers_array+i, "null")
show_message(QMessageBox.Information, "Success", "All garages successfully unlocked.")
def change_headquarter(self):
hq = self.ui.headquarter_edit.text().lower()
if hq is "":
show_message("Error", "Enter a name for the city.")
show_message(QMessageBox.Critical, "Error", "Enter city name!")
return
if get_value(search_line("hq_city:")) == hq:
show_message("Error", "Your headquarter is already in this city")
show_message(QMessageBox.Information, "Info", "Your headquarter is already in this city.")
elif hq not in self.purchased_garages():
show_message("Error", "You need to own the garage in this city.")
show_message(QMessageBox.Critical, "Error", "You need a garage in \"{}\" to set headquarter.".format(hq))
else:
set_value(search_line("hq_city:"), hq)
show_message("Success", "Headquarter successfully set to \"{}\".".format(hq))
show_message(QMessageBox.Information, "Success", "Headquarter successfully set to \"{}\".".format(hq))
def check_cities(self):
self.ui.headquarter_edit.setText(get_value(search_line("hq_city:")))
self.ui.cities_text.clear()
for city in get_array_items(search_line("visited_cities:")):
self.ui.cities_text.append(city)
if not get_array_items(search_line("visited_cities:")):
visited_cities = get_array_items(search_line("visited_cities:"))
if not visited_cities:
self.ui.cities_text.append("No cities visited yet.")
return
for city in visited_cities:
self.ui.cities_text.append(city)
self.ui.cities_text.scrollToAnchor(visited_cities[0])
def add_city(self):
city = self.ui.city_edit.text().lower()
if city is "":
show_message("Error", "Enter a name for the city.")
show_message(QMessageBox.Critical, "Error", "Enter city name!")
return
self.ui.city_edit.setText("")
if city not in get_array_items(search_line("visited_cities:")):
add_array_value(search_line("visited_cities:"), city)
add_array_value(search_line("visited_cities_count:"), "1")
show_message("Success", "City \"{}\" successfully visited.".format(city))
show_message(QMessageBox.Information, "Success", "City \"{}\" successfully visited.".format(city))
self.check_cities()
else:
show_message("Error", "You already visited \"{}\".".format(city))
show_message(QMessageBox.Critical, "Error", "You've already visited \"{}\".".format(city))
def add_all_cities(self):
for city in self.cities():
if city not in get_array_items(search_line("visited_cities:")):
visited_cities = get_array_items(search_line("visited_cities:"))
for city in self.all_cities():
if city not in visited_cities:
add_array_value(search_line("visited_cities:"), city)
add_array_value(search_line("visited_cities_count:"), "1")
show_message("Success", "All cities successfully visited.")
show_message(QMessageBox.Information, "Success", "All cities successfully visited.")
self.check_cities()
def check_dealers(self):
self.ui.dealerships_text.clear()
for dealer in get_array_items(search_line("unlocked_dealers:")):
self.ui.dealerships_text.append(dealer)
if not get_array_items(search_line("unlocked_dealers:")):
visited_dealers = get_array_items(search_line("unlocked_dealers:"))
if not visited_dealers:
self.ui.dealerships_text.append("No dealerships unlocked yet.")
def add_dealer(self):
dealer = self.ui.dealer_edit.text().lower()
if dealer is "":
show_message("Error", "Enter a name for the city.")
return
self.ui.dealer_edit.setText("")
if dealer not in self.dealers:
show_message("Error", "There is no dealership in that city.")
elif dealer in get_array_items(search_line("unlocked_dealers:")):
show_message("Error", "This dealership already unlocked.")
else:
add_array_value(search_line("unlocked_dealers:"), dealer)
show_message("Success", "Dealership in \"{}\" successfully unlocked.".format(dealer))
self.check_dealers()
for dealer in visited_dealers:
self.ui.dealerships_text.append(dealer)
self.ui.dealerships_text.scrollToAnchor(visited_dealers[0])
def add_all_dealers(self):
all_cities = self.all_cities()
visited_dealers = get_array_items(search_line("unlocked_dealers:"))
for dealer in self.dealers:
if dealer in self.cities() and dealer not in get_array_items(search_line("unlocked_dealers:")):
if dealer in all_cities and dealer not in visited_dealers:
add_array_value(search_line("unlocked_dealers:"), dealer)
show_message("Success", "All dealerships unlocked.")
show_message(QMessageBox.Information, "Success", "All dealerships unlocked.")
self.check_dealers()
def check_agencies(self):
self.ui.agencies_text.clear()
for agency in get_array_items(search_line("unlocked_recruitments:")):
self.ui.agencies_text.append(agency)
if not get_array_items(search_line("unlocked_recruitments:")):
visited_agencies = get_array_items(search_line("unlocked_recruitments:"))
if not visited_agencies:
self.ui.agencies_text.append("No recruitment agencies unlocked yet.")
def add_agency(self):
agency = self.ui.agency_edit.text().lower()
if agency is "":
show_message("Error", "Enter a name for the city.")
return
self.ui.agency_edit.setText("")
if agency not in self.agencies:
show_message("Error", "There is no recruitment agency in that city.")
elif agency in get_array_items(search_line("unlocked_recruitments:")):
show_message("Error", "Recruitment agency is already unlocked.")
else:
add_array_value(search_line("unlocked_recruitments:"), agency)
show_message("Success", "Recruitment agency in \"{}\" successfully unlocked.".format(agency))
self.check_agencies()
for agency in visited_agencies:
self.ui.agencies_text.append(agency)
self.ui.agencies_text.scrollToAnchor(visited_agencies[0])
def add_all_agencies(self):
all_cities = self.all_cities()
visited_agencies = get_array_items(search_line("unlocked_recruitments:"))
for agency in self.agencies:
if agency in self.cities() and agency not in get_array_items(search_line("unlocked_recruitments:")):
if agency in all_cities and agency not in visited_agencies:
add_array_value(search_line("unlocked_recruitments:"), agency)
show_message("Success", "All recruitment agencies unlocked.")
show_message(QMessageBox.Information, "Success", "All recruitment agencies unlocked.")
self.check_agencies()
def da_clicked(self):
da_arr = self.da_array.get(self.sender())
if da_arr is None:
return
edit, file_var, message_var = da_arr[0], da_arr[1], da_arr[2]
city_element = edit.text().lower()
if not city_element:
show_message(QMessageBox.Critical, "Error", "Enter city name!")
return
edit.setText("")
if city_element not in da_arr[3]:
show_message(QMessageBox.Critical, "Error", "There is no {} in that city.".format(message_var.lower()))
elif city_element in get_array_items(search_line(file_var)):
show_message(QMessageBox.Information, "Info",
"{} in \"{}\" is already unlocked.".format(message_var, city_element))
else:
add_array_value(search_line(file_var), city_element)
show_message(QMessageBox.Information, "Success",
"{} in \"{}\" successfully unlocked.".format(message_var, city_element))
da_arr[4]()

View File

@@ -1,20 +1,50 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from sys import platform
from cx_Freeze import setup, Executable
executables = [Executable('__init__.py', targetName='SaveWizard.exe', base='Win32GUI')]
excludes = ['email', 'html', 'http', 'logging', 'pydoc_data', 'unittest', 'urllib', 'xml', 'tempfile', 'select', 'pwd',
'datetime', 'shlex', 'shutil', 'socket', 'platform', 'webbrowser', 'pydoc', 'selectors', 'tty', 'inspect',
'doctest', 'plistlib', 'calendar', 'subprocess', 'copy', 'bz2', 'stringprep', 'posixpath', '_strptime',
'dummy_threading']
zip_include_packages = ['collections', 'encodings', 'importlib', 'json', 'hashlib', 'PyQt5', 'sip', 'main', 'second']
include_files = ['SII_Decrypt.exe', 'dlc.json', 'dealers.json', 'agencies.json']
base = None
if platform == 'win32':
base = 'Win32GUI'
executables = [
Executable('init_main_program.py', targetName='SaveWizard.exe', base=base),
Executable('init_config_editor.py', targetName='SaveWizard_Config_Editor.exe', base=base)
]
excludes = ['html', 'pydoc_data', 'unittest', 'xml', 'pwd', 'shlex', 'platform', 'webbrowser', 'pydoc', 'tty',
'inspect', 'doctest', 'plistlib', 'subprocess', 'bz2', '_strptime', 'dummy_threading']
includes = ['pkgutil', 'enum', 'queue', 'PyQt5.sip']
zip_include_packages = [
# Stock modules
'collections', 'encodings', 'importlib', 'json', 'hashlib', 'selectors', 'select', 'http', 'email', 'datetime',
'calendar', 'urllib', 'posixpath', 'tempfile', 'shutil', 'copy', 'stringprep', 'socket', 'ast',
# PyQt5
'PyQt5',
# Modules for parsing cfg's
'requests', 'logging', 'certifi', 'chardet', 'idna', 'urllib3',
# Self-written modules
'parsing', 'choice', 'main', 'second', 'config_editor'
]
include_files = [
'dlls/imageformats',
'dlls/platforms',
'dlls/styles',
'SII_Decrypt.exe',
('configs/ats', 'configs/ats'),
('configs/ets2', 'configs/ets2')
]
options = {
'build_exe': {
'excludes': excludes,
'includes': includes,
'include_msvcr': True,
'build_exe': 'stable_build',
'build_exe': 'prog_build',
'include_files': include_files,
'zip_include_packages': zip_include_packages,
}
@@ -22,9 +52,9 @@ options = {
setup(
name='SaveWizard',
version='1.1',
version='1.3',
description='For editing ETS2 sii files',
executables=executables,
options=options,
requires=['PyQt5']
requires=['PyQt5', 'requests'],
)

6
statics.py Normal file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
update_config_name = "update.cfg"
github_link = "https://raw.githubusercontent.com/JDM170/SaveWizard/master/"
hash_chunk_size = 4096

105
util.py
View File

@@ -1,28 +1,45 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# from re import search, match, sub
from re import search, match
from PyQt5.QtWidgets import QMessageBox
from re import search, match, sub
lines = ''
from hashlib import md5
from statics import hash_chunk_size
lines = []
def set_lines(from_other):
# Custom functions
def set_lines(new_lines):
global lines
lines = from_other
lines = new_lines
def get_lines():
def get_lines(index=None):
global lines
if index is not None:
return lines[index]
return lines
def show_message(title, text):
box = QMessageBox()
box.setWindowTitle(title)
box.setText(text)
box.exec_()
def show_message(icon, title, text):
box = QMessageBox(icon, title, text, QMessageBox.Ok)
box.exec()
def generate_md5(fn):
try:
hash_md5 = md5()
with open(fn, "rb") as f:
for chunk in iter(lambda: f.read(hash_chunk_size), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
except FileNotFoundError:
return False
# Stock functions
def search_line(term, start=0, cancel=r"this_string_must_not_exist"):
global lines
if search(term, lines[start]):
@@ -46,10 +63,10 @@ def search_line_in_unit(term, unit):
def search_all_lines(term):
global lines
matches = []
start = 0
while search_line(term, start=start + 1):
start = search_line(term, start=start + 1)
matches.append(start)
line = 0
while search_line(term, start=line + 1):
line = search_line(term, start=line + 1)
matches.append(line)
if matches is None:
return None
return matches
@@ -66,9 +83,9 @@ def set_value(line, value):
lines[line] = name + ": " + value
def get_unit_name(line):
global lines
return search(r" : (.+) {$", lines[line]).group(1)
# def get_unit_name(line):
# global lines
# return search(r" : (.+) {$", lines[line]).group(1)
def get_array_length(line):
@@ -76,19 +93,19 @@ def get_array_length(line):
return int(search(r": ([0-9]+)$", lines[line]).group(1))
def get_array_value_by_index(line, index):
global lines
return search(r": (.+)$", lines[line + index + 1]).group(1)
def get_array_index_by_value(line, value):
global lines
count = 0
for i in range(get_array_length(line)):
if get_value(line + count + 1) == value:
return count
count += 1
return None
# def get_array_value_by_index(line, index):
# global lines
# return search(r": (.+)$", lines[line + index + 1]).group(1)
#
#
# def get_array_index_by_value(line, value):
# global lines
# count = 0
# for i in range(get_array_length(line)):
# if get_value(line + count + 1) == value:
# return count
# count += 1
# return None
def get_array_items(line):
@@ -109,17 +126,17 @@ def add_array_value(line, value):
lines.insert(line + count + 1, name + "[" + str(count) + "]: " + value)
def remove_array_value(line, value):
global lines
name = match(r"(.+):", lines[line]).group(1)
del lines[line + 1 + get_array_index_by_value(line, value)]
count = get_array_length(line)
lines[line] = name + ": " + str(count - 1)
for i in range(count):
lines[line + i + 1] = sub(r"\[[0-9]+\]", "[" + str(i) + "]", lines[line + i + 1])
def change_array_value(line, index, value):
global lines
line += index + 1
set_value(line, value)
# def remove_array_value(line, value):
# global lines
# name = match(r"(.+):", lines[line]).group(1)
# del lines[line + 1 + get_array_index_by_value(line, value)]
# count = get_array_length(line)
# lines[line] = name + ": " + str(count - 1)
# for i in range(count):
# lines[line + i + 1] = sub(r"\[[0-9]+]", "[" + str(i) + "]", lines[line + i + 1])
#
#
# def change_array_value(line, index, value):
# global lines
# line += index + 1
# set_value(line, value)