RuseCristian / Track-Sectors-Assetto-Corsa-App

1 stars 0 forks source link

[Improvement] Automatically mark sectors #1

Open Arkemenes opened 5 months ago

Arkemenes commented 5 months ago

Hi! I'm really enjoying the app, but I've encountered an issue. Manually marking sectors on multiple maps can be quite laborious.

I noticed that most maps include a sections.ini file, which identifies the main sections of the map.

With this in mind, I've created a Python script that reads all the sections.ini files in the tracks folder, extracts the sectors, and generates a data.json file following a similar pattern to the existing track sectors.

Currently, the script isn't integrated with the track sectors, and the code is quite basic (it was developed in just a couple of hours). However, I believe this could potentially be a valuable feature to consider for a future pull request.

One specific approach I implemented was to calculate the average between two consecutive sectors. If they are close, I use only the midpoint to avoid creating excessively small sectors. If the sectors are significantly apart (I used the average distance of each sector, which may not be the best method but seemed more appropriate than a fixed value), I retain both the end of the previous sector and the start of the new one, because it probably forms a straight line.

Here is the initial version of the code:

from statistics import mean
import configparser
from pathlib import Path
import json

config = configparser.ConfigParser()

directory_in_str = 'D:/SteamLibrary/steamapps/common/assettocorsa/content/tracks' 

def fix_straights(sectors):
    if len(sectors) < 3:
       return [x for xs in sectors for x in xs ]

    sectors = [[float(s[0]),float(s[1])] for s in sectors]
    avg = mean([s[1]-s[0] for s in sectors])

    new_sectors = [sectors[0][0]]

    for i in range(len(sectors)-1):
        sector = sectors[i]
        sector_1 = sectors[i+1]

        if sector_1[0] - sector[1] < avg:
           new_sectors.append(mean([sector_1[0],sector[1]]))
        else:
           new_sectors.append(sector[1])
           new_sectors.append(sector_1[0])

    if 1 + sectors[0][0] - sectors[-1][1] > avg:
       new_sectors.append(sectors[-1][1])

    new_sectors.sort()

    return new_sectors

output = {}

pathlist = Path(directory_in_str).glob('**/sections.ini')
for path in pathlist:
    path_in_str = str(path)
    config = configparser.ConfigParser()
    config.read(path_in_str, encoding="cp1251")

    sectors = [[config.items(s)[0][1],config.items(s)[1][1]]  for s in config.sections()]
    sectors = fix_straights(sectors)
    d = {path_in_str.split('\\')[-3] : { "sector_checkpoints" : {f'sector_{i+1}' : sector for i, sector in enumerate(sectors)}, "sector_count" : len(sectors)}}

    if path_in_str.split('\\')[-4] == 'tracks': 
        output.update(d)
    else:
        if not path_in_str.split('\\')[-4] in output.keys():
            output[path_in_str.split('\\')[-4]] = {}
        output[path_in_str.split('\\')[-4]].update(d)

with open('data.json', 'w') as f:
    json.dump(output, f)

If you are interested in a pull request, please let me know so I can contribute further (I don't have experience with Assetto Corsa apps, but I'm eager to learn).

Feel free to highlight any issues or suggest any modifications you think might improve the functionality.

RuseCristian commented 4 months ago

I was tinkering with the idea of having something like a central hub for sharing configurations for various tracks, but this is a bit far-fetched or at least quite a future endeavor. Your idea seems quite a good compromise to what I had in mind with the hub.

This way everybody could have the same configuration, and it would also be calculated by the app instead of me plastering around relatively big data files. We can talk about implementing something similar to this, but unfortunately this will be in maybe a few weeks at the earliest, I'm really caught up with IRL stuff at the moment.

Arkemenes commented 4 months ago

I'm glad you liked the idea!

I'm considering running the code I wrote at startup, opening your data.json, and using something like output.update(data.json) to automatically fetch all sectors while preserving any data previously saved manually. What do you think?

I'll try to submit a PR in the next few days with an upgraded version of my code (it needs significant improvements) that integrates with the track sectors, if you're okay with it :)