Branch data Line data Source code
1 : : #include "VehicleUtils.h"
2 : : #include <algorithm>
3 : : #include <string>
4 : :
5 : : // Helper: Parse car class from strings (v0.7.44 Refactor)
6 : : // Returns a ParsedVehicleClass enum for internal logic and categorization
7 : 1386 : ParsedVehicleClass ParseVehicleClass(const char* className, const char* vehicleName) {
8 [ + + + - ]: 2772 : std::string cls = className ? className : "";
9 [ + + + - ]: 1386 : std::string name = vehicleName ? vehicleName : "";
10 : :
11 : : // Normalize for case-insensitive matching
12 : 1386 : std::transform(cls.begin(), cls.end(), cls.begin(), ::toupper);
13 : 1386 : std::transform(name.begin(), name.end(), name.begin(), ::toupper);
14 : :
15 : : // 1. Primary Identification via Class Name (Hierarchical)
16 [ + + + + : 1386 : if (cls.find("HYPERCAR") != std::string::npos || cls.find("LMH") != std::string::npos || cls.find("LMDH") != std::string::npos) {
+ + + + ]
17 : 18 : return ParsedVehicleClass::HYPERCAR;
18 : : }
19 : :
20 [ + + ]: 1368 : if (cls.find("LMP2") != std::string::npos) {
21 [ + + + + : 22 : if (cls.find("ELMS") != std::string::npos || name.find("DERESTRICTED") != std::string::npos) { return ParsedVehicleClass::LMP2_UNRESTRICTED; }
+ + ]
22 : : // Issue #225: "LMP2" in LMU refers to the restricted WEC spec.
23 : 16 : return ParsedVehicleClass::LMP2_RESTRICTED;
24 : : }
25 : :
26 [ + + ]: 1346 : if (cls.find("LMP3") != std::string::npos) return ParsedVehicleClass::LMP3;
27 [ + + ]: 1345 : if (cls.find("GTE") != std::string::npos) return ParsedVehicleClass::GTE;
28 : : // NOTE: LMGT3 check is redundant here as GT3 would match it first.
29 [ + + - + : 1336 : if (cls.find("GT3") != std::string::npos || cls.find("LMGT3") != std::string::npos) return ParsedVehicleClass::GT3;
+ + ]
30 : :
31 : : // 2. Secondary Identification via Vehicle Name Keywords (Fallback)
32 [ + + ]: 51 : if (!name.empty()) {
33 : : // Hypercars
34 [ + + + + ]: 136 : if (name.find("499P") != std::string::npos || name.find("GR010") != std::string::npos ||
35 [ + + + + ]: 129 : name.find("963") != std::string::npos || name.find("9X8") != std::string::npos ||
36 [ + + + + ]: 123 : name.find("V-SERIES.R") != std::string::npos || name.find("SCG 007") != std::string::npos ||
37 [ + + + + ]: 117 : name.find("GLICKENHAUS") != std::string::npos || name.find("VANWALL") != std::string::npos ||
38 [ + + + + ]: 111 : name.find("A424") != std::string::npos || name.find("SC63") != std::string::npos ||
39 [ + + + + ]: 105 : name.find("VALKYRIE") != std::string::npos || name.find("M HYBRID") != std::string::npos ||
40 [ + + + + : 126 : name.find("TIPO 6") != std::string::npos || name.find("680") != std::string::npos) {
+ + ]
41 : 15 : return ParsedVehicleClass::HYPERCAR;
42 : : }
43 : :
44 : : // LMP2
45 [ + + + + : 32 : if (name.find("ORECA") != std::string::npos || name.find("07") != std::string::npos) {
+ + ]
46 : 3 : return ParsedVehicleClass::LMP2_UNSPECIFIED;
47 : : }
48 : :
49 : : // LMP3
50 [ + + + + ]: 82 : if (name.find("LIGIER") != std::string::npos || name.find("GINETTA") != std::string::npos ||
51 [ + + + + ]: 75 : name.find("DUQUEINE") != std::string::npos || name.find("P320") != std::string::npos ||
52 [ + + + + : 102 : name.find("P325") != std::string::npos || name.find("G61") != std::string::npos ||
+ + + + ]
53 : 22 : name.find("D09") != std::string::npos) {
54 : 8 : return ParsedVehicleClass::LMP3;
55 : : }
56 : :
57 : : // GTE
58 [ + + + + ]: 60 : if (name.find("RSR-19") != std::string::npos || name.find("488 GTE") != std::string::npos ||
59 [ + + + + : 60 : name.find("C8.R") != std::string::npos || name.find("VANTAGE AMR") != std::string::npos) {
+ + ]
60 : 4 : return ParsedVehicleClass::GTE;
61 : : }
62 : :
63 : : // GT3
64 [ + + + + ]: 48 : if (name.find("LMGT3") != std::string::npos || name.find("296 GT3") != std::string::npos ||
65 [ + + + + ]: 42 : name.find("M4 GT3") != std::string::npos || name.find("Z06 GT3") != std::string::npos ||
66 [ + + + + ]: 36 : name.find("HURACAN") != std::string::npos || name.find("RC F") != std::string::npos ||
67 [ + + + + : 44 : name.find("720S") != std::string::npos || name.find("MUSTANG") != std::string::npos) {
+ + ]
68 : 8 : return ParsedVehicleClass::GT3;
69 : : }
70 : : }
71 : :
72 : 13 : return ParsedVehicleClass::UNKNOWN;
73 : 1386 : }
74 : :
75 : : // Lookup table: Map ParsedVehicleClass to Seed Load (Newtons)
76 : 1339 : double GetDefaultLoadForClass(ParsedVehicleClass vclass) {
77 [ + + + + : 1339 : switch (vclass) {
+ + + + ]
78 : 16 : case ParsedVehicleClass::HYPERCAR: return 9500.0;
79 : 4 : case ParsedVehicleClass::LMP2_UNRESTRICTED: return 8500.0;
80 : 13 : case ParsedVehicleClass::LMP2_RESTRICTED: return 7500.0;
81 : 1 : case ParsedVehicleClass::LMP2_UNSPECIFIED: return 8000.0;
82 : 2 : case ParsedVehicleClass::LMP3: return 5800.0;
83 : 9 : case ParsedVehicleClass::GTE: return 5500.0;
84 : 1281 : case ParsedVehicleClass::GT3: return 4800.0;
85 : 13 : default: return 4500.0;
86 : : }
87 : : }
88 : :
89 : : // Helper: String representation of parsed class for logging and UI
90 : 673 : const char* VehicleClassToString(ParsedVehicleClass vclass) {
91 [ + + + + : 673 : switch (vclass) {
+ + + + ]
92 : 9 : case ParsedVehicleClass::HYPERCAR: return "Hypercar";
93 : 3 : case ParsedVehicleClass::LMP2_UNRESTRICTED: return "LMP2 Unrestricted";
94 : 7 : case ParsedVehicleClass::LMP2_RESTRICTED: return "LMP2 Restricted";
95 : 1 : case ParsedVehicleClass::LMP2_UNSPECIFIED: return "LMP2 Unspecified";
96 : 2 : case ParsedVehicleClass::LMP3: return "LMP3";
97 : 6 : case ParsedVehicleClass::GTE: return "GTE";
98 : 640 : case ParsedVehicleClass::GT3: return "GT3";
99 : 5 : default: return "Unknown";
100 : : }
101 : : }
|