diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index 6c235ce20..1fc035c8c 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -429,6 +429,11 @@ RANGE.TargetType = { -- @field #string airframe Aircraft type of player. -- @field #number time Time via timer.getAbsTime() in seconds of impact. -- @field #string date OS date. +-- @field #number attackHdg Attack heading in degrees. +-- @field #number attackVel Attack velocity in knots. +-- @field #number attackAlt Attack altitude in feet. +-- @field #string clock Time of the run. +-- @field #string rangename Name of the range. --- Strafe result. -- @type RANGE.StrafeResult @@ -436,6 +441,13 @@ RANGE.TargetType = { -- @field #string airframe Aircraft type of player. -- @field #number time Time via timer.getAbsTime() in seconds of impact. -- @field #string date OS date. +-- @field #string name Name of the target pit. +-- @field #number roundsFired Number of rounds fired. +-- @field #number roundsHit Number of rounds that hit the target. +-- @field #number strafeAccuracy Accuracy of the run in percent. +-- @field #string clock Time of the run. +-- @field #string rangename Name of the range. +-- @field #boolean invalid Invalid pass. --- Sound file data. -- @type RANGE.Soundfile @@ -949,6 +961,19 @@ function RANGE:SetTargetSheet( path, prefix ) return self end +--- Set FunkMan socket. Bombing and strafing results will be send to your Discord bot. +-- **Requires running FunkMan program**. +-- @param #RANGE self +-- @param #number Port Port. Default `10042`. +-- @param #string Host Host. Default "127.0.0.1". +-- @return #RANGE self +function RANGE:SetFunkManOn(Port, Host) + + self.funkmanSocket=SOCKET:New(Port, Host) + + return self +end + --- Set messages to examiner. The examiner will receive messages from all clients. -- @param #RANGE self -- @param #string examinergroupname Name of the group of the examiner. @@ -1727,7 +1752,6 @@ function RANGE:OnEventHit( EventData ) self:_DisplayMessageToGroup( _unit, text ) self:T2( self.id .. text ) _currentTarget.pastfoulline = true - invalidStrafe = true -- Rangeboss Edit end end @@ -1938,7 +1962,7 @@ function RANGE:OnEventShot( EventData ) local _results = self.bombPlayerResults[_playername] local result = {} -- #RANGE.BombResult - result.type = "Bomb Result" + result.dataType = "Bomb Result" result.name = _closetTarget.name or "unknown" result.distance = _distance result.radial = _closeCoord:HeadingTo( impactcoord ) @@ -1946,7 +1970,9 @@ function RANGE:OnEventShot( EventData ) result.quality = _hitquality result.player = playerData.playername result.time = timer.getAbsTime() - result.clock = UTILS.SecondsToClock(result.time) + result.clock = UTILS.SecondsToClock(result.time, true) + result.midate = UTILS.GetDCSMissionDate() + result.theatre = env.mission.theatre result.airframe = playerData.airframe result.roundsFired = 0 -- Rangeboss Edit result.roundsHit = 0 -- Rangeboss Edit @@ -2140,6 +2166,26 @@ function RANGE:onafterImpact( From, Event, To, result, player ) if self.autosave then self:Save() end + + -- Send result to FunkMan, which creates fancy MatLab figures and sends them to Discord via a bot. + if self.funkmanSocket then + self.funkmanSocket:SendTable(result) + end + +end + +--- Function called after strafing run. +-- @param #RANGE self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +-- @param #RANGE.PlayerData player Player data table. +-- @param #RANGE.StrafeResult result Result of run. +function RANGE:onafterStrafeResult( From, Event, To, player, result) + + if self.funkmanSocket then + self.funkmanSocket:SendTable(result) + end end @@ -2195,7 +2241,7 @@ function RANGE:onafterSave( From, Event, To ) local target = result.name local radial = result.radial local quality = result.quality - local time = UTILS.SecondsToClock( result.time ) + local time = UTILS.SecondsToClock(result.time, true) local airframe = result.airframe local date = "n/a" if os then @@ -3065,11 +3111,13 @@ function RANGE:_CheckInZone( _unitName ) -- Strafe result. local result = {} -- #RANGE.StrafeResult - result.type="Strafe Result" + result.dataType="Strafe Result" result.player=_playername result.name=_result.zone.name or "unknown" result.time = timer.getAbsTime() result.clock = UTILS.SecondsToClock(result.time) + result.midate = UTILS.GetDCSMissionDate() + result.theatre = env.mission.theatre result.roundsFired = shots result.roundsHit = _result.hits result.roundsQuality = resulttext diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 2ed31685d..dd28da530 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -3361,6 +3361,20 @@ function AIRBOSS:SetDebugModeOFF() return self end + +--- Set FunkMan socket. LSO grades and trap sheets will be send to your Discord bot. +-- **Requires running FunkMan program**. +-- @param #AIRBOSS self +-- @param #number Port Port. Default `10042`. +-- @param #string Host Host. Default `"127.0.0.1"`. +-- @return #AIRBOSS self +function AIRBOSS:SetFunkManOn(Port, Host) + + self.funkmanSocket=SOCKET:New(Port, Host) + + return self +end + --- Get next time the carrier will start recovering aircraft. -- @param #AIRBOSS self -- @param #boolean InSeconds If true, abs. mission time seconds is returned. Default is a clock #string. @@ -12781,19 +12795,23 @@ function AIRBOSS:_Debrief( playerData ) end mygrade.case = playerData.case local windondeck = self:GetWindOnDeck() - mygrade.wind = tostring( UTILS.Round( UTILS.MpsToKnots( windondeck ), 1 ) ) + mygrade.wind = UTILS.Round( UTILS.MpsToKnots( windondeck ), 1 ) mygrade.modex = playerData.onboard mygrade.airframe = playerData.actype mygrade.carriertype = self.carriertype mygrade.carriername = self.alias + mygrade.carrierrwy = self.carrierparam.rwyangle mygrade.theatre = self.theatre - mygrade.mitime = UTILS.SecondsToClock( timer.getAbsTime() ) + mygrade.mitime = UTILS.SecondsToClock( timer.getAbsTime(), true ) mygrade.midate = UTILS.GetDCSMissionDate() mygrade.osdate = "n/a" if os then mygrade.osdate = os.date() -- os.date("%d.%m.%Y") end + -- Add last grade to playerdata for FunkMan. + playerData.grade=mygrade + -- Save trap sheet. if playerData.trapon and self.trapsheet then self:_SaveTrapSheet( playerData, mygrade ) @@ -17909,6 +17927,58 @@ function AIRBOSS:onafterLoad( From, Event, To, path, filename ) end +--- On after "LSOGrade" event. +-- @param #AIRBOSS self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +-- @param #AIRBOSS.PlayerData playerData Player Data. +-- @param #AIRBOSS.LSOgrade grade LSO grade. +function AIRBOSS:onafterLSOGrade(From, Event, To, playerData, grade) + + if self.funkmanSocket then + + -- Extract used info for FunkMan. We need to be careful with the amount of data send via UDP socket. + local trapsheet={} ; trapsheet.X={} ; trapsheet.Z={} ; trapsheet.AoA={} ; trapsheet.Alt={} + + -- Loop over trapsheet and extract used values. + for i = 1, #playerData.trapsheet do + local ts=playerData.trapsheet[i] --#AIRBOSS.GrooveData + table.insert(trapsheet.X, ts.X) + table.insert(trapsheet.Z, ts.Z) + table.insert(trapsheet.AoA, ts.AoA) + table.insert(trapsheet.Alt, ts.Alt) + end + + local result={} + result.dataType="Trap Sheet" + result.name=playerData.name + result.trapsheet=trapsheet + result.airframe=grade.airframe + result.mitime=grade.mitime + result.midate=grade.midate + result.wind=grade.wind + result.carriertype=grade.carriertype + result.carriername=grade.carriername + result.carrierrwy=grade.carrierrwy + result.theatre=grade.theatre + result.case=playerData.case + result.Tgroove=grade.Tgroove + result.wire=grade.wire + result.grade=grade.grade + result.points=grade.points + result.details=grade.details + + -- Debug info. + env.info("FF result onafterLSOGrade") + self:I(result) + + -- Send result. + self.funkmanSocket:SendTable(result) + end + +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/Moose Development/Moose/Utilities/Socket.lua b/Moose Development/Moose/Utilities/Socket.lua index dbb2b114a..fc3eba8a1 100644 --- a/Moose Development/Moose/Utilities/Socket.lua +++ b/Moose Development/Moose/Utilities/Socket.lua @@ -30,6 +30,8 @@ -- # The SOCKET Concept -- -- Create a UDP socket server. It enables you to send messages to discord servers via discord bots. +-- +-- **Note** that you have to **de-sanitize** `require` and `package` in your `MissionScripting.lua` file, which is in your `DCS/Scripts` folder. -- -- -- @field #SOCKET @@ -39,9 +41,24 @@ SOCKET = { lid = nil, } +--- Data type. +-- @field #string TEXT Plain text. +-- @field #string BOMB Range bombing. +-- @field #string STRAFE Range strafeing result. +-- @field #string LSOGRADE Airboss LSO grade. +-- @field #string TRAPSHEET Airboss trap sheet. +SOCKET.DataType={ + TEXT="Text", + RANGEBOMB="Bomb Result", + RANGESTRAFE="Strafe Run", + LSOGRADE="LSO Grade", + TRAPSHEET="Trapsheet", +} + + --- SOCKET class version. -- @field #string version -SOCKET.version="0.0.1" +SOCKET.version="0.1.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -57,7 +74,7 @@ SOCKET.version="0.0.1" --- Create a new SOCKET object. -- @param #SOCKET self --- @param #number Port UDP port. Default `10123`. +-- @param #number Port UDP port. Default `10042`. -- @param #string Host Host. Default `"127.0.0.1"`. -- @return #SOCKET self function SOCKET:New(Port, Host) @@ -70,7 +87,7 @@ function SOCKET:New(Port, Host) self.socket = require("socket") - self.port=Port or 10123 + self.port=Port or 10042 self.host=Host or "127.0.0.1" self.json=loadfile("Scripts\\JSON.lua")() @@ -81,18 +98,37 @@ function SOCKET:New(Port, Host) return self end +--- Set port. +-- @param #SOCKET self +-- @param #number Port Port. Default 10042. +-- @return #SOCKET self +function SOCKET:SetPort(Port) + self.port=Port or 10042 +end + +--- Set host. +-- @param #SOCKET self +-- @param #string Host Host. Default `"127.0.0.1"`. +-- @return #SOCKET self +function SOCKET:SetHost(Host) + self.host=Host or "127.0.0.1" +end + + --- Send a table. -- @param #SOCKET self -- @param #table Table Table to send. --- @param #number Port Port. -- @return #SOCKET self -function SOCKET:SendTable(Table, Port) +function SOCKET:SendTable(Table) - local tbl_json_txt = self.json:encode(Table) - - Port=Port or self.port - - self.socket.try(self.UDPSendSocket:sendto(tbl_json_txt, self.host, Port)) + local json= self.json:encode(Table) + + -- Debug info. + self:T("Json table:") + self:T(json) + + -- Send data. + self.socket.try(self.UDPSendSocket:sendto(json, self.host, self.port)) return self end @@ -100,16 +136,15 @@ end --- Send a text message. -- @param #SOCKET self -- @param #string Text Test message. --- @param #number Port Port. -- @return #SOCKET self -function SOCKET:SendText(Text, Port) +function SOCKET:SendText(Text) local message={} - message.messageType = 1 - message.messageString = Text + message.dataType = "Text Message" + message.text = Text - self:SendTable(message, Port) + self:SendTable(message) return self end