Last Updates

This commit is contained in:
FlightControl
2016-09-12 12:29:20 +02:00
parent dac29f6356
commit cd4d4af559
241 changed files with 6314 additions and 1827 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
--- Provides a logging of statistics in a running DCS Mission.
-- @script eStatHandler
--Handler table
local eStatHandler = {}
local _StatRunID
--Neccessary tables for string instead of integers
SETCoalition =
{
[1] = "red",
[2] = "blue",
}
SETGroupCat =
{
[1] = "AIRPLANE",
[2] = "HELICOPTER",
[3] = "GROUND",
[4] = "SHIP",
[5] = "STRUCTURE",
}
SETWeaponCatName =
{
[0] = "SHELL",
[1] = "MISSILE",
[2] = "ROCKET",
[3] = "BOMB",
}
wEvent = {
"S_EVENT_SHOT",
"S_EVENT_HIT",
"S_EVENT_TAKEOFF",
"S_EVENT_LAND",
"S_EVENT_CRASH",
"S_EVENT_EJECTION",
"S_EVENT_REFUELING",
"S_EVENT_DEAD",
"S_EVENT_PILOT_DEAD",
"S_EVENT_BASE_CAPTURED",
"S_EVENT_MISSION_START",
"S_EVENT_MISSION_END",
"S_EVENT_TOOK_CONTROL",
"S_EVENT_REFUELING_STOP",
"S_EVENT_BIRTH",
"S_EVENT_HUMAN_FAILURE",
"S_EVENT_ENGINE_STARTUP",
"S_EVENT_ENGINE_SHUTDOWN",
"S_EVENT_PLAYER_ENTER_UNIT",
"S_EVENT_PLAYER_LEAVE_UNIT",
"S_EVENT_PLAYER_COMMENT",
"S_EVENT_SHOOTING_START",
"S_EVENT_SHOOTING_END",
"S_EVENT_MAX",
}
statEventsTable = {}
function SecondsToClock(sSeconds)
local nSeconds = sSeconds
if nSeconds == 0 then
--return nil;
return "00:00:00";
else
nHours = string.format("%02.f", math.floor(nSeconds/3600));
nMins = string.format("%02.f", math.floor(nSeconds/60 - (nHours*60)));
nSecs = string.format("%02.f", math.floor(nSeconds - nHours*3600 - nMins *60));
return nHours..":"..nMins..":"..nSecs
end
end
function eStatHandler:onEvent(e)
local InitID_ = ""
local InitName = ""
local WorldEvent = wEvent[e.id]
local InitCoa = ""
local InitGroupCat = ""
local InitType = ""
local InitPlayer = ""
local eWeaponCat = ""
local eWeaponName = ""
local TargID_ = ""
local TargName = ""
local TargType = ""
local TargPlayer = ""
local TargCoa = ""
local TargGroupCat = ""
if e.initiator and Object.getCategory(e.initiator) == Object.Category.UNIT then
--Initiator variables
local InitGroup = e.initiator:getGroup()
InitID_ = e.initiator.id_
if e.initiator:getName() then
InitName = e.initiator:getName()
end
if InitGroup:getCoalition() then
InitCoa = SETCoalition[InitGroup:getCoalition()]
end
if InitGroup:getCategory() then
InitGroupCat = SETGroupCat[InitGroup:getCategory() + 1]
end
InitType = e.initiator:getTypeName()
--Get initiator player name or AI if NIL
if e.initiator:getPlayerName() == nil then
InitPlayer = "AI"
else
InitPlayer = e.initiator:getPlayerName()
end
else
if e.initiator then
local InitGroup = e.initiator:getGroup()
InitID_ = e.initiator.id_
if e.initiator:getName() then
InitName = e.initiator:getName()
end
InitCoa = SETCoalition[InitGroup:getCoalition()]
InitGroupCat = SETGroupCat[InitGroup:getCategory() + 1]
InitType = e.initiator:getTypeName()
--Get initiator player name or AI if NIL
if e.initiator:getPlayerName() == nil then
InitPlayer = "AI"
else
InitPlayer = e.initiator:getPlayerName()
end
end
end
--Weapon variables
if e.weapon == nil then
eWeaponCat = ""
eWeaponName = ""
else
local eWeaponDesc = e.weapon:getDesc()
eWeaponCat = SETWeaponCatName[eWeaponDesc.category]
eWeaponName = eWeaponDesc.displayName
end
--Target variables
if e.target == nil then
TargID_ = ""
TargName = ""
TargType = ""
TargPlayer = ""
TargCoa = ""
TargGroupCat = ""
elseif Object.getCategory(e.target) == Object.Category.UNIT then
local TargGroup = e.target:getGroup()
TargID_ = e.target.id_
if e.target:getName() then
TargName = e.target:getName()
end
TargType = e.target:getTypeName()
TargCoa = SETCoalition[TargGroup:getCoalition()]
TargGroupCat = SETGroupCat[TargGroup:getCategory() + 1]
--Get target player name or AI if NIL
if not e.target:getPlayerName() then
TargPlayer = "AI"
else
TargPlayer = e.target:getPlayerName()
end
else
TargType = e.target:getTypeName()
TargID_ = ""
TargName = ""
TargPlayer = ""
TargCoa = ""
TargGroupCat = ""
end
--write events to table
statEventsTable[#statEventsTable + 1] =
{
[1] = _StatRunID,
[2] = SecondsToClock(timer.getTime()),
[3] = WorldEvent,
[4] = InitID_,
[5] = InitName,
[6] = InitCoa,
[7] = InitGroupCat,
[8] = InitType,
[9] = InitPlayer,
[10] = eWeaponCat,
[11] = eWeaponName,
[12] = TargID_,
[13] = TargName,
[14] = TargCoa,
[15] = TargGroupCat,
[16] = TargType,
[17] = TargPlayer,
}
env.info( 'Event: ' .. _StatRunID .. '~ ' .. SecondsToClock(timer.getTime()) .. '~ ' .. WorldEvent .. '~ ' .. InitID_ .. '~ ' .. InitName .. '~ ' .. InitCoa .. '~ ' .. InitGroupCat .. '~ ' .. InitType .. '~ ' .. InitPlayer ..
'~ ' .. eWeaponCat .. '~ ' .. eWeaponName .. '~ ' .. TargID_ .. '~ ' .. TargName .. '~ ' .. TargCoa .. '~ ' .. TargGroupCat .. '~ ' .. TargType .. '~ ' .. TargPlayer )
end
do
local StatFile,err
function StatOpen()
local fdir = lfs.writedir() .. [[Logs\]] .. "Events_" .. os.date( "%Y-%m-%d_%H-%M-%S" ) .. ".csv"
StatFile,err = io.open(fdir,"w+")
if not StatFile then
local errmsg = 'Error: No Logs folder found in the User\\Saved Games\\DCS\\Logs directory...' .. 'Save_stat . sample: C:\\Users\\youname\\Saved Games\\DCS\\Logs'
trigger.action.outText(errmsg, 10)
return print(err)
end
StatFile:write("RunID~Time~Event~Initiator ID~Initiator Name~Initiator Coalition~Initiator Group Category~Initiator Type~Initiator Player~Weapon Category~Weapon Name~Target ID~Target Name~Target Coalition~Target Group Category~Target Type~Target Player\n")
_StatRunID = os.date("%y-%m-%d_%H-%M-%S")
routines.scheduleFunction( StatSave, { }, timer.getTime() + 1, 1)
end
function StatSave()
--write statistic information to file
for Index, eDetails in ipairs(statEventsTable) do
for eInfoName, eInfoData in ipairs(eDetails) do
StatFile:write(eInfoData.."~")
end
StatFile:write("\n")
end
statEventsTable = {}
end
function StatClose()
StatFile:close()
end
end
world.addEventHandler(eStatHandler)
StatOpen()

View File

@@ -0,0 +1,295 @@
--- This module contains derived utilities taken from the MIST framework,
-- which are excellent tools to be reused in an OO environment!.
--
-- ### Authors:
--
-- * Grimes : Design & Programming of the MIST framework.
--
-- ### Contributions:
--
-- * FlightControl : Rework to OO framework
--
-- @module Utils
--- @type SMOKECOLOR
-- @field Green
-- @field Red
-- @field White
-- @field Orange
-- @field Blue
SMOKECOLOR = trigger.smokeColor -- #SMOKECOLOR
--- @type FLARECOLOR
-- @field Green
-- @field Red
-- @field White
-- @field Yellow
FLARECOLOR = trigger.flareColor -- #FLARECOLOR
--- Utilities static class.
-- @type UTILS
UTILS = {}
--from http://lua-users.org/wiki/CopyTable
UTILS.DeepCopy = function(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
local objectreturn = _copy(object)
return objectreturn
end
-- porting in Slmod's serialize_slmod2
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
lookup_table = {}
local function _Serialize( tbl )
if type(tbl) == 'table' then --function only works for tables!
if lookup_table[tbl] then
return lookup_table[object]
end
local tbl_str = {}
lookup_table[tbl] = tbl_str
tbl_str[#tbl_str + 1] = '{'
for ind,val in pairs(tbl) do -- serialize its fields
local ind_str = {}
if type(ind) == "number" then
ind_str[#ind_str + 1] = '['
ind_str[#ind_str + 1] = tostring(ind)
ind_str[#ind_str + 1] = ']='
else --must be a string
ind_str[#ind_str + 1] = '['
ind_str[#ind_str + 1] = routines.utils.basicSerialize(ind)
ind_str[#ind_str + 1] = ']='
end
local val_str = {}
if ((type(val) == 'number') or (type(val) == 'boolean')) then
val_str[#val_str + 1] = tostring(val)
val_str[#val_str + 1] = ','
tbl_str[#tbl_str + 1] = table.concat(ind_str)
tbl_str[#tbl_str + 1] = table.concat(val_str)
elseif type(val) == 'string' then
val_str[#val_str + 1] = routines.utils.basicSerialize(val)
val_str[#val_str + 1] = ','
tbl_str[#tbl_str + 1] = table.concat(ind_str)
tbl_str[#tbl_str + 1] = table.concat(val_str)
elseif type(val) == 'nil' then -- won't ever happen, right?
val_str[#val_str + 1] = 'nil,'
tbl_str[#tbl_str + 1] = table.concat(ind_str)
tbl_str[#tbl_str + 1] = table.concat(val_str)
elseif type(val) == 'table' then
if ind == "__index" then
-- tbl_str[#tbl_str + 1] = "__index"
-- tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
else
val_str[#val_str + 1] = _Serialize(val)
val_str[#val_str + 1] = ',' --I think this is right, I just added it
tbl_str[#tbl_str + 1] = table.concat(ind_str)
tbl_str[#tbl_str + 1] = table.concat(val_str)
end
elseif type(val) == 'function' then
-- tbl_str[#tbl_str + 1] = "function " .. tostring(ind)
-- tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
else
-- env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind))
-- env.info( debug.traceback() )
end
end
tbl_str[#tbl_str + 1] = '}'
return table.concat(tbl_str)
else
return tostring(tbl)
end
end
local objectreturn = _Serialize(tbl)
return objectreturn
end
--porting in Slmod's "safestring" basic serialize
UTILS.BasicSerialize = function(s)
if s == nil then
return "\"\""
else
if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then
return tostring(s)
elseif type(s) == 'string' then
s = string.format('%q', s)
return s
end
end
end
UTILS.ToDegree = function(angle)
return angle*180/math.pi
end
UTILS.ToRadian = function(angle)
return angle*math.pi/180
end
UTILS.MetersToNM = function(meters)
return meters/1852
end
UTILS.MetersToFeet = function(meters)
return meters/0.3048
end
UTILS.NMToMeters = function(NM)
return NM*1852
end
UTILS.FeetToMeters = function(feet)
return feet*0.3048
end
UTILS.MpsToKnots = function(mps)
return mps*3600/1852
end
UTILS.MpsToKmph = function(mps)
return mps*3.6
end
UTILS.KnotsToMps = function(knots)
return knots*1852/3600
end
UTILS.KmphToMps = function(kmph)
return kmph/3.6
end
--[[acc:
in DM: decimal point of minutes.
In DMS: decimal point of seconds.
position after the decimal of the least significant digit:
So:
42.32 - acc of 2.
]]
UTILS.tostringLL = function( lat, lon, acc, DMS)
local latHemi, lonHemi
if lat > 0 then
latHemi = 'N'
else
latHemi = 'S'
end
if lon > 0 then
lonHemi = 'E'
else
lonHemi = 'W'
end
lat = math.abs(lat)
lon = math.abs(lon)
local latDeg = math.floor(lat)
local latMin = (lat - latDeg)*60
local lonDeg = math.floor(lon)
local lonMin = (lon - lonDeg)*60
if DMS then -- degrees, minutes, and seconds.
local oldLatMin = latMin
latMin = math.floor(latMin)
local latSec = UTILS.Round((oldLatMin - latMin)*60, acc)
local oldLonMin = lonMin
lonMin = math.floor(lonMin)
local lonSec = UTILS.Round((oldLonMin - lonMin)*60, acc)
if latSec == 60 then
latSec = 0
latMin = latMin + 1
end
if lonSec == 60 then
lonSec = 0
lonMin = lonMin + 1
end
local secFrmtStr -- create the formatting string for the seconds place
if acc <= 0 then -- no decimal place.
secFrmtStr = '%02d'
else
local width = 3 + acc -- 01.310 - that's a width of 6, for example.
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
end
return string.format('%02d', latDeg) .. ' ' .. string.format('%02d', latMin) .. '\' ' .. string.format(secFrmtStr, latSec) .. '"' .. latHemi .. ' '
.. string.format('%02d', lonDeg) .. ' ' .. string.format('%02d', lonMin) .. '\' ' .. string.format(secFrmtStr, lonSec) .. '"' .. lonHemi
else -- degrees, decimal minutes.
latMin = UTILS.Round(latMin, acc)
lonMin = UTILS.Round(lonMin, acc)
if latMin == 60 then
latMin = 0
latDeg = latDeg + 1
end
if lonMin == 60 then
lonMin = 0
lonDeg = lonDeg + 1
end
local minFrmtStr -- create the formatting string for the minutes place
if acc <= 0 then -- no decimal place.
minFrmtStr = '%02d'
else
local width = 3 + acc -- 01.310 - that's a width of 6, for example.
minFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
end
return string.format('%02d', latDeg) .. ' ' .. string.format(minFrmtStr, latMin) .. '\'' .. latHemi .. ' '
.. string.format('%02d', lonDeg) .. ' ' .. string.format(minFrmtStr, lonMin) .. '\'' .. lonHemi
end
end
--- From http://lua-users.org/wiki/SimpleRound
-- use negative idp for rounding ahead of decimal place, positive for rounding after decimal place
function UTILS.Round( num, idp )
local mult = 10 ^ ( idp or 0 )
return math.floor( num * mult + 0.5 ) / mult
end
-- porting in Slmod's dostring
function UTILS.DoString( s )
local f, err = loadstring( s )
if f then
return true, f()
else
return false, err
end
end