Hey Leute,
ich habe vor 3 Jahren dieses Script geschrieben und irgendwie überkam mir diese Woche das Bedürfnis das mal richtig/ordentlich/gut zu machen und einfach mal wieder was zu scripten.
Um ehrlich zu sein hatte ich vor etwas längerer Zeit die Idee das mit einer dll zu lösen... hatte ich aber keine lust drauf xD
Ich wollt mir mal eure Meinung zum Code einholen... bzgl. Performance und Optimierung, etc..
Kurz erklärt was es macht:
Anhand von Messwerten eine geschätzte Reichweite für den verleibenden Tank berechnen und anzeigen.
Meine Umsetzung in kurz:
Alle 5 sec. Spielerposition und tankstand speichern, Distanz zwischen den Messpunkten und Differenz vom Tank stand nehmen, und dies in eine temporäre liste speichern, welche alle 50 Durchläufe zusammengefasst und mit der vorigen Zusammenfassung verrechnet wird. Danach wird ein wenig Mathematik und Physik angewendet um die korrekten Ergebnisse und Einheiten zu bekommen.
Das ganze wird dann auf dem HUD angezeigt.
Ablauf:
Beim einsteigen wird das Script gestartet über einen EVH, zusammengefasste Daten, falls vorhanden, werden geladen.
Beim Aussteigen o.Ä. wird es beendet und die zusammengefassten Daten auf dem Object gespeichert.
Das HUD:
Von Links nach Rechts, von oben nach Unten:
- Reichweite bei aktuellem Tankfüllstand und Verbrauch (siehe zweiter Punkt),
- Arithmetisches Mittel des Verbrauchs, kann ich km pro l oder l pro 100 km angezeigt werden,
- Aktueller Tankfüllstand in Prozent,
- Gefahrene Distanz seit Aufzeichnung.
Da mein Git nur lokal läuft habe ich den sqf Part mal als Code eingefügt.
waitUntil {(!isNull player) && (player == player)};
player addEventHandler["GetInMan", {_this call data_fnc_init}];
player addEventHandler["GetOutMan", {"data_show" cutFadeOut 0}];
data_var_preventStart = false;
data_var_literPerKm = false; // option to translate into x l/100km
if (isNull objectParent player) exitWith { diag_log "Error1.0"; };
private _veh = param [2, objNull, [objNull]];
if (isNull _veh) exitWith { diag_log "Error1.1"; };
private _role = param [1, "", [""]];
if !(_role isEqualTo "driver") exitWith { diag_log "Error1.2"; };
if (data_var_preventStart) exitWith { diag_log "Error1.3"; };
data_var_preventStart = true;
(_veh getVariable ["data_trip",[]]) params [["_dist", 0, [0]],["_avg", 0, [0]]];
[_veh, _dist, _avg] spawn data_fnc_main;
Alles anzeigen
params [["_veh", objNull, [vehicle player]],["_var_data_dist", 0, [0]],["_var_data_avg", 0, [0]]];
if (isNull _veh) exitWith { diag_log "Error2.0"; };
private _var_tmp_list = [];
private _lastTank = 0;
private _lastGpsPos = [];
private _n = 0;
private _cap = getNumber(configFile >> "CfgVehicles" >> typeOf(vehicle player) >> "fuelCapacity");
disableSerialization;
"data_show" cutRsc["vehInfo","PLAIN"];
((uiNamespace getVariable "vehInfo") displayCtrl 1100)ctrlSetText format["%1",getText ( configFile >> "CfgVehicles" >> typeOf(_veh) >> "displayName")];
// Load known data into ui
[_veh, _cap , _var_tmp_list, _var_data_dist, _var_data_avg] spawn data_fnc_calculate;
while { !isNull objectParent player } do {
private _t = diag_tickTime;
private _curTank = fuel (vehicle player);
private _curGpsPos = getPosATL player;
if (_lastTank isEqualTo 0) then {
_lastTank = _curTank;
};
// refuelling does not count as fuel consumption
if (_lastTank < _curTank) then {
_lastTank = _curTank;
};
if (_lastGpsPos isEqualTo []) then {
_lastGpsPos = _curGpsPos;
};
// if no change in fuel and driven distance -> new data will be ignored
if !(_lastGpsPos isEqualTo _curGpsPos && _lastTank isEqualTo _curTank) then {
private _dist = _lastGpsPos distance _curGpsPos;
_var_data_dist = _var_data_dist + _dist;
_var_tmp_list set[_n, [(_lastTank - _curTank), _dist]];
if (_n isEqualTo 49) then { // => Dataset size is 50, indexes 0 to 49
private _fuel = 0;
private _dist = 0;
{
_fuel = _fuel + (_x select 0);
_dist = _dist + (_x select 1);
} count _var_tmp_list; // Add up collected data
// Count and select : 0.0467, without calling a function: 0.0416 ms => Build in faster then?
try {
// Create average based on new collected data and older summerized data
// Because _dist can be 0, we use a try in case it is acutally 0
if (_var_data_avg isEqualTo 0) then {
_var_data_avg = _dist / (_fuel * _cap);
} else {
_var_data_avg = (_var_data_avg + (_dist / (_fuel * _cap))) / 2;
};
} catch {
// Idea: _n-1 to stay in the current loop and try to save the new dataset
// This will overwrite the dataset on n=49
};
_n = -1;
};
_lastTank = _curTank;
_lastGpsPos = _curGpsPos;
_n = _n + 1;
diag_log (diag_tickTime - _t);
[_veh, _cap, _var_tmp_list, _var_data_dist, _var_data_avg] spawn data_fnc_calculate;
};
uiSleep 5;
};
if !(isNull _veh) then {
_veh setVariable ["data_trip",[_var_data_dist, _var_data_avg],true];
};
data_var_preventStart = false;
Alles anzeigen
#define roundc(VAR) round (((VAR) / 1000) * (10 ^ 1)) / (10 ^ 1)
#define roundx(VAR) round ((VAR) * (10 ^ 1)) / (10 ^ 1)
params [["_veh", objNull, [objNull]],["_fuelCapacity", 1, [0]],["_data_list", []],["_dist", 0, [0]],["_avg", 0, [0]]];
if (isNull _veh) exitWith { diag_log "Error2"; };
private _sumFuel = 0;
private _sumDist = 0;
{
_sumFuel = _sumFuel + (_x select 0);
_sumDist = _sumDist + (_x select 1);
} count _data_list; // Add up collected data
if !(_sumDist isEqualTo 0 || _sumFuel isEqualTo 0) then {
// meter pro % -> m/% e.g. m/s -> transladted into km/l
// Calculate average fuel consumption based on new collected data and older summerized data
if (_avg isEqualTo 0) then {
_avg = _sumDist / (_sumFuel * _fuelCapacity);
} else {
_avg = (_avg + _sumDist / (_sumFuel * _fuelCapacity)) / 2;
};
};
private _fuelPct = fuel _veh;
private _ui = uiNamespace getVariable "vehInfo";
(_ui displayCtrl 1101)ctrlSetText format["%1 %2",roundx((_fuelPct * 100)),"%"];
(_ui displayCtrl 1003)ctrlSetText format["%1 km",roundc(_dist)];
if (_avg isEqualTo 0) exitWith {};
(_ui displayCtrl 1000)ctrlSetText format["%1 km",roundc(_avg * (_fuelPct * _fuelCapacity))];
if (data_var_literPerKm) then {
(_ui displayCtrl 1001)ctrlSetText format["%1 l/100km",roundx((100 / (_avg / 1000)))];
} else {
(_ui displayCtrl 1001)ctrlSetText format["%1 km/l",roundc(_avg)];
};
Alles anzeigen
Ich bin mir bewusst, dass der Name 'calculate' nicht mehr ganz passt xD
Über feedback und wie gesagt Verbesserungsvorschläge würde ich mich sehr freuen, dafür war der Beitrag hier ja auch gedacht
VG Leon
(Falls das der Falsche Bereich ist, bitte moven - hat sich hier bisschen was verändert seit meiner Aktivität haha)