Skip to content

Commit

Permalink
refine GUI and config version (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
Juice-XIJ authored Apr 26, 2022
1 parent a2df3a6 commit 860633f
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=forza_motorsport/*
# exit-zero treats all errors as warnings. The GitHub editor is 255 chars wide
flake8 . --count --max-complexity=10 --max-line-length=255 --statistics --exclude=forza_motorsport/* --ignore=E402
flake8 . --count --max-complexity=10 --max-line-length=255 --statistics --exclude=forza_motorsport/* --ignore=E402,C901
- name: Test with pytest
run: |
pytest
Expand Down
5 changes: 4 additions & 1 deletion car_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ def __init__(self):
"""initialization
"""
# === Car information ===
self.ordinal = ''
self.ordinal = -1
self.car_perf = 0
self.car_class = -1
self.car_drivetrain = -1
self.minGear = 1
self.maxGear = 5

Expand Down
34 changes: 34 additions & 0 deletions constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import enum
import os
from pynput.keyboard import Key


# config version
class ConfigVersion(enum.Enum):
v1 = 1,
v2 = 2


default_config_version = ConfigVersion.v2

# repo path
root_path = os.path.dirname(os.path.abspath(__file__))

Expand All @@ -20,6 +30,22 @@
# === UI settings ===
background_color = "#1a181a"
text_color = "#a1a1a1"
perf_sticker_background = "#FFFFFF"

# car info relx, rely
car_info_leftbound_relx = 0.08
car_info_rightbound_relx = 0.9
car_info_topbound_rely = 0.195
car_info_bottombound_rely = 0.815
car_info_line_gap = 0.065

# car drivetrain
car_drivetrain_list = [
('FWD', '前驱'),
('RWD', '后驱'),
('AWD', '四驱'),
('N', 'N')
]

# tire canvas info: Position: [start_x1_factor, start_y1_factor, s radius]
x_padding_left = 0.025
Expand All @@ -42,6 +68,10 @@
"RR": [x_padding_left + width + x_dis, y_padding_top + height + y_dis, x_padding_left + width * 2 + x_dis, y_padding_top + height * 2 + y_dis, radius]
}

# car class mapping
car_class_list = ['D', 'C', 'B', 'A', 'S1', 'S2', 'X', "N"]
car_class_color = ['#3dafd1', '#edc786', '#f28240', '#e22b2a', '#8729e2', '#3256ba', '#46ce67', text_color]

# === short-cut ===
stop = Key.pause # stop program
close = Key.end # close program
Expand Down Expand Up @@ -82,6 +112,10 @@
clutch_txt = ['Enable Clutch', '开启离合']
farm_txt = ['Enable Farm', '开启刷图']
offroad_rally_txt = ['Offroad, Rally', '越野,拉力']
car_id = ['Car ID:', '车辆序号:']
car_class = ['Car Class:', '车辆等级:']
car_perf = ['Car Performance:', '车辆性能:']
car_drivetrain = ['Car Drivetrain:', '车辆传动:']
tire_information_txt = ['Tire Information', '轮胎信息']
accel_txt = ['Acceleration', '加速']
brake_txt = ['Brake', '刹车']
Expand Down
100 changes: 81 additions & 19 deletions forza.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from fdp import ForzaDataPacket

import constants
from constants import ConfigVersion
import gear_helper
import helper
import keyboard_helper
Expand Down Expand Up @@ -81,6 +82,8 @@ def test_gear(self, update_car_gui_func=None):
if fdp is None:
continue

self.__update_forza_info(fdp)

if fdp.speed > 0.1:
if update_car_gui_func is not None:
update_car_gui_func(fdp)
Expand All @@ -93,14 +96,10 @@ def test_gear(self, update_car_gui_func=None):
'clutch': fdp.clutch,
'power': fdp.power / 1000.0,
'torque': fdp.torque,
'car_ordinal': str(fdp.car_ordinal),
'speed/rpm': fdp.speed * 3.6 / fdp.current_engine_rpm
}
self.records.append(info)
self.logger.debug(info)

if len(self.records) > 0:
self.ordinal = self.records[0]['car_ordinal']
except BaseException as e:
self.logger.exception(e)
finally:
Expand Down Expand Up @@ -146,6 +145,18 @@ def analyze(self, performance_profile: bool = True, is_gui: bool = False):
finally:
self.logger.debug(f'{self.analyze.__name__} ended')

def __update_forza_info(self, fdp: ForzaDataPacket):
"""update forza info while running
Args:
fdp (ForzaDataPacket): datapackage
"""
if self.ordinal != fdp.car_ordinal or self.car_perf != fdp.car_performance_index or self.car_class != fdp.car_class or self.car_drivetrain != fdp.drivetrain_type:
self.ordinal = fdp.car_ordinal
self.car_perf = fdp.car_performance_index
self.car_class = fdp.car_class
self.car_drivetrain = fdp.drivetrain_type

def __try_auto_load_config(self, fdp: ForzaDataPacket):
"""auto load config while driving
Expand All @@ -157,25 +168,73 @@ def __try_auto_load_config(self, fdp: ForzaDataPacket):
"""
try:
self.logger.debug(f'{self.__try_auto_load_config.__name__} started')
# config name pattern: xxx_xxx_{car_ordinal}_xxx
config = [f for f in listdir(self.config_folder) if (isfile(join(self.config_folder, f)) and str(fdp.car_ordinal) in os.path.splitext(f)[0].split('_'))]
if len(config) <= 0:
configs = [f for f in listdir(self.config_folder) if (isfile(join(self.config_folder, f)) and str(fdp.car_ordinal) in f)]
if len(configs) <= 0:
self.logger.warning(f'config ({fdp.car_ordinal}) is not found at folder {self.config_folder}. Please run gear test ({constants.collect_data}) and/or analysis ({constants.analysis}) first!!')
return False
elif len(config) > 1:
self.logger.warning(f'multiple configs ({fdp.car_ordinal}) are found at folder {self.config_folder}: {config}. The car ordinal should be unique')
elif len(configs) > 0:
self.logger.info(f'found ({fdp.car_ordinal}) config(s): {configs}')

# latest config version: ordinal-perf-drivetrain.json, v2
filename = helper.get_config_name(self)
if filename in configs:
if self.__try_loading_config(filename):
# remove legacy config if necessary
if len(configs) > 1:
self.__cleanup_legacy_config(configs, filename)

return True
else:
return False

# if latest config version not existed. like only ordinal.json, v1
filename = helper.get_config_name(self, ConfigVersion.v1)
if filename in configs:
if self.__try_loading_config(filename):
self.car_perf = fdp.car_performance_index
self.car_class = fdp.car_class
self.car_drivetrain = fdp.drivetrain_type

# dump to latest config version
helper.dump_config(self)
self.__cleanup_legacy_config(configs, '')
return True
else:
return False

# unknown config
self.logger.warning(f'unknown ({fdp.car_ordinal}) config(s) {self.config_folder}: {configs}')
return False
else:
self.logger.info(f'loading config {config}')
helper.load_config(self, os.path.join(self.config_folder, config[0]))
if len(self.shift_point) <= 0:
self.logger.warning(f'Config is invalid. Please run gear test ({constants.collect_data}) and/or analysis ({constants.analysis}) to create a new one!!')
return False
self.logger.info(f'loaded config {config}')
return True
finally:
self.logger.debug(f'{self.__try_auto_load_config.__name__} ended')

def __cleanup_legacy_config(self, configs, exclude_config):
for config in configs:
if config != exclude_config:
try:
self.logger.warning(f'removing legacy config {config}')
path = os.path.join(self.config_folder, config)
os.remove(path)
except Exception as e:
self.logger.warning(f'failed to remove legacy config {config}: {e}')

def __try_loading_config(self, config):
"""try to load config
Args:
config (str): config file name
Returns:
bool: success or failure
"""
self.logger.info(f'loading config {config}')
helper.load_config(self, os.path.join(self.config_folder, config))
if len(self.shift_point) <= 0:
self.logger.warning(f'Config is invalid. Please run gear test ({constants.collect_data}) and/or analysis ({constants.analysis}) to create a new one!!')
return False
self.logger.info(f'loaded config {config}')
return True

def shifting(self, iteration, fdp):
"""shifting func
Expand All @@ -194,6 +253,7 @@ def shifting(self, iteration, fdp):
if self.farming and iteration % 800 == 0:
self.threadPool.submit(keyboard_helper.press_brake, self)

# prepare shifting params
slip = (fdp.tire_slip_ratio_RL + fdp.tire_slip_ratio_RR) / 2
speed = fdp.speed * 3.6
rpm = fdp.current_engine_rpm
Expand All @@ -210,7 +270,7 @@ def shifting(self, iteration, fdp):
if not fired and gear > self.minGear:
lower_gear = gear - 1 if gear - 1 <= len(self.shift_point) else len(self.shift_point) - 1
target_down_speed = self.shift_point[lower_gear]['speed'] * self.shift_point_factor
if speed + 5 < target_down_speed and slip < 1:
if speed < target_down_speed * 0.95 and slip < 1:
self.logger.debug(f'[{iteration}] down shift triggerred. speed < target down speed ({speed} < {target_down_speed}), fired {fired}')
gear_helper.down_shift_handle(gear, self)

Expand Down Expand Up @@ -242,13 +302,15 @@ def run(self, update_tree_func=lambda *args: None, update_car_gui_func=lambda *a
# 1. self.shift_point is empty
# or
# 2. fdp.car_ordinal is different from self.ordinal => means car switched
if len(self.shift_point) <= 0 or self.ordinal != str(fdp.car_ordinal):
if len(self.shift_point) <= 0 or self.ordinal != fdp.car_ordinal:
self.__update_forza_info(fdp)
if self.__try_auto_load_config(fdp):
update_tree_func()
continue
else:
return

self.__update_forza_info(fdp)
if iteration == -1:
update_tree_func()

Expand Down
Loading

0 comments on commit 860633f

Please sign in to comment.