mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-10 17:59:24 +00:00
Ops
This commit is contained in:
@@ -618,7 +618,7 @@ end
|
||||
function AIRWING:onafterMissionRequest(From, Event, To, Mission)
|
||||
|
||||
-- Set mission status to ASSIGNED.
|
||||
Mission:Assign()
|
||||
Mission:Requested()
|
||||
|
||||
-- Some assets might already be spawned and even on a different mission (orbit).
|
||||
-- Need to dived to set into spawned and instock assets and handle the other
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
-- @field #string type Mission type.
|
||||
-- @field #string status Mission status.
|
||||
-- @field #table flightstatus Status of flight missions.
|
||||
-- @field #table flightgroups Flight groups of this mission.
|
||||
-- @field #table flightdata Flight specific data.
|
||||
-- @field #string name Mission name.
|
||||
-- @field #number prio Mission priority.
|
||||
-- @field #boolean urgent Mission is urgent. Running missions with lower prio might be cancelled.
|
||||
@@ -96,7 +98,9 @@ AUFTRAG = {
|
||||
Debug = false,
|
||||
lid = nil,
|
||||
auftragsnummer = nil,
|
||||
flightgroups = {},
|
||||
flightstatus = {},
|
||||
flightdata = {},
|
||||
}
|
||||
|
||||
--- Global mission counter.
|
||||
@@ -144,9 +148,10 @@ AUFTRAG.Type={
|
||||
-- @type AUFTRAG.Status
|
||||
-- @field #string PLANNED Mission is at the early planning stage.
|
||||
-- @field #string QUEUED Mission is queued at an airwing.
|
||||
-- @field #string REQUESTED Mission assets were requested from the warehouse.
|
||||
-- @field #string ASSIGNED Mission was assigned to somebody.
|
||||
-- @field #string SCHEDULED Mission is scheduled in a FLIGHGROUP queue waiting to be started.
|
||||
-- @field #string STARTED Mission started but is not executed yet.
|
||||
-- @field #string STARTED Mission has started but is not executed yet.
|
||||
-- @field #string EXECUTING Mission is being executed.
|
||||
-- @field #string DONE Mission is over.
|
||||
-- @field #string CANCELLED Mission was cancelled.
|
||||
@@ -179,6 +184,14 @@ AUFTRAG.FlightStatus={
|
||||
DONE="done",
|
||||
}
|
||||
|
||||
--- Flight specific data.
|
||||
-- @type AUFTRAG.FlightData
|
||||
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
-- @field Core.Point#COORDINATE waypointcoordinate Waypoint coordinate.
|
||||
-- @field #number waypointindex Waypoint index.
|
||||
-- @field Ops.FlightGroup#FLIGHTGROUP.Task waypointtask Waypoint task.
|
||||
-- @field #string status Flight mission status.
|
||||
|
||||
|
||||
--- AUFTRAG class version.
|
||||
-- @field #string version
|
||||
@@ -228,7 +241,7 @@ function AUFTRAG:New(Type)
|
||||
-- FMS start state is PLANNED.
|
||||
self:SetStartState(self.status)
|
||||
|
||||
-- PLANNED --> (QUEUED) --> (ASSIGNED) --> SCHEDULED --> STARTED --> EXECUTING --> DONE
|
||||
-- PLANNED --> (QUEUED) --> (REQUESTED) --> SCHEDULED --> STARTED --> EXECUTING --> DONE
|
||||
|
||||
self:AddTransition(AUFTRAG.Status.PLANNED, "Queued", AUFTRAG.Status.QUEUED) -- Mission is in queue of an AIRWING.
|
||||
self:AddTransition(AUFTRAG.Status.QUEUED, "Requested", AUFTRAG.Status.REQUESTED) -- Mission assets have been requested from the warehouse.
|
||||
@@ -242,8 +255,8 @@ function AUFTRAG:New(Type)
|
||||
self:AddTransition("*", "Done", AUFTRAG.Status.DONE) -- All assets have reported that mission is done.
|
||||
self:AddTransition("*", "Cancel", AUFTRAG.Status.CANCELLED) -- Command to cancel the mission.
|
||||
|
||||
self:AddTransition("*", "Accomplished", "Success")
|
||||
self:AddTransition("*", "Failed", "Failure")
|
||||
self:AddTransition("*", "Accomplished", AUFTRAG.Status.SUCCESS)
|
||||
self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED)
|
||||
|
||||
self:AddTransition("*", "Status", "*")
|
||||
|
||||
@@ -486,6 +499,23 @@ function AUFTRAG:SetROE(roe)
|
||||
end
|
||||
|
||||
|
||||
--- Add a flight group to the mission.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FLIGHTGROUP object.
|
||||
function AUFTRAG:AddFlightGroup(FlightGroup)
|
||||
self:I(self.lid..string.format("Adding flight group %s", FlightGroup.groupname))
|
||||
|
||||
--table.insert(self.flightgroups, FlightGroup)
|
||||
|
||||
local flightdata={} --#AUFTRAG.FlightData
|
||||
flightdata.flightgroup=FlightGroup
|
||||
flightdata.status=AUFTRAG.FlightStatus.SCHEDULED
|
||||
flightdata.waypointcoordinate=nil
|
||||
|
||||
self.flightdata[FlightGroup.groupname]=flightdata
|
||||
|
||||
end
|
||||
|
||||
--- Check if mission is executing.
|
||||
-- @param #AUFTRAG self
|
||||
-- @return #boolean If true, mission is currently executing.
|
||||
@@ -515,40 +545,61 @@ function AUFTRAG:onafterStatus(From, Event, To)
|
||||
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
self:I(self.lid..string.format("FSM status %s, mission status=%s", fsmstate, self.status))
|
||||
self:I(self.lid..string.format("FSM status %s, mission status=%s, flightgroups=%d", fsmstate, self.status, #self.flightdata))
|
||||
|
||||
self:__Status(-30)
|
||||
end
|
||||
|
||||
--- On after "Cancel" event. Cancells the mission.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AUFTRAG:onafterCancel(From, Event, To)
|
||||
|
||||
for _,_asset in pairs(self.assets or {}) do
|
||||
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
|
||||
asset.flightgroup:MissionCancel(self)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Set flightgroup mission status.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
-- @param #string state New state.
|
||||
function AUFTRAG:SetFlightStatus(flightgroup, state)
|
||||
self.flightstatus[flightgroup.groupname]=state
|
||||
-- @param #string status New status.
|
||||
function AUFTRAG:SetFlightStatus(flightgroup, status)
|
||||
self.flightdata[flightgroup.groupname].status=status
|
||||
end
|
||||
|
||||
--- Get flightgroup mission status.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
function AUFTRAG:GetFlightStatus(flightgroup)
|
||||
return self.flightstatus[flightgroup.groupname]
|
||||
return self.flightdata[flightgroup.groupname].status
|
||||
end
|
||||
|
||||
|
||||
--- Set flightgroup waypoint coordinate.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
-- @param Core.Point#COORDINATE coordinate Waypoint Coordinate.
|
||||
function AUFTRAG:SetFlightWaypointCoordinate(flightgroup, coordinate)
|
||||
self.flightdata[flightgroup.groupname].waypointcoordinate=coordinate
|
||||
end
|
||||
|
||||
--- Get flightgroup waypoint coordinate.
|
||||
-- @param #AUFTRAG self
|
||||
-- @return Core.Point#COORDINATE Waypoint Coordinate.
|
||||
function AUFTRAG:GetFlightWaypointCoordinate(flightgroup)
|
||||
return self.flightdata[flightgroup.groupname].waypointcoordinate
|
||||
end
|
||||
|
||||
|
||||
--- Set flightgroup waypoint task.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP.Task task Waypoint task.
|
||||
function AUFTRAG:SetFlightWaypointTask(flightgroup, task)
|
||||
self:I(self.lid..string.format("Setting waypoint task %s", task and task.description or "WTF"))
|
||||
self.flightdata[flightgroup.groupname].waypointtask=task
|
||||
end
|
||||
|
||||
--- Get flightgroup waypoint task.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
-- @return Ops.FlightGroup#FLIGHTGROUP.Task task Waypoint task. Waypoint task.
|
||||
function AUFTRAG:GetFlightWaypointTask(flightgroup)
|
||||
return self.flightdata[flightgroup.groupname].waypointtask
|
||||
end
|
||||
|
||||
|
||||
--- Get flightgroup mission status.
|
||||
-- @param #AUFTRAG self
|
||||
-- @return #boolean If true, all flights are done with the mission.
|
||||
@@ -617,7 +668,7 @@ end
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AUFTRAG:onafterStart(From, Event, To)
|
||||
function AUFTRAG:onafterStarted(From, Event, To)
|
||||
self.status=AUFTRAG.Status.STARTED
|
||||
self:I(self.lid..string.format("New mission status=%s", self.status))
|
||||
end
|
||||
@@ -627,7 +678,7 @@ end
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AUFTRAG:onafterExecute(From, Event, To)
|
||||
function AUFTRAG:onafterExecuting(From, Event, To)
|
||||
self.status=AUFTRAG.Status.EXECUTING
|
||||
self:I(self.lid..string.format("New mission status=%s", self.status))
|
||||
end
|
||||
@@ -642,15 +693,28 @@ function AUFTRAG:onafterDone(From, Event, To)
|
||||
self:I(self.lid..string.format("New mission status=%s", self.status))
|
||||
end
|
||||
|
||||
|
||||
--- On after "Cancel" event.
|
||||
--- On after "Cancel" event. Cancells the mission.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AUFTRAG:onafterCancel(From, Event, To)
|
||||
self.status=AUFTRAG.Status.DONE
|
||||
|
||||
self.status=AUFTRAG.Status.CANCELLED
|
||||
self:I(self.lid..string.format("New mission status=%s", self.status))
|
||||
|
||||
--[[
|
||||
for _,_asset in pairs(self.assets or {}) do
|
||||
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
|
||||
asset.flightgroup:MissionCancel(self)
|
||||
end
|
||||
]]
|
||||
|
||||
for _,_flightdata in pairs(self.flightdata) do
|
||||
local flightdata=_flightdata --#AUFTRAG.FlightData
|
||||
flightdata.flightgroup:MissionCancel(self)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -659,20 +659,23 @@ end
|
||||
-- @param Core.Point#COORDINATE WaypointCoordinate Coordinate of the mission waypoint
|
||||
-- @param #number WaypointIndex The waypoint number. Default is after all current air waypoints.
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:AddMission(Mission, WaypointCoordinate, WaypointIndex)
|
||||
function FLIGHTGROUP:AddMission(Mission, WaypointCoordinate)
|
||||
|
||||
Mission.waypointcoord=WaypointCoordinate
|
||||
Mission.waypointindex=WaypointIndex
|
||||
|
||||
-- Add flight group to mission.
|
||||
Mission:AddFlightGroup(self)
|
||||
|
||||
-- Set status to scheduled.
|
||||
Mission:SetFlightStatus(self, AUFTRAG.FlightStatus.SCHEDULED)
|
||||
Mission:Scheduled()
|
||||
|
||||
-- Add mission to queue.
|
||||
table.insert(self.missionqueue, Mission)
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("Added %s mission %s at waypoint #%s. Starting at %s. Stopping at %s",
|
||||
tostring(Mission.type), tostring(Mission.name), tostring(Mission.waypointindex), UTILS.SecondsToClock(Mission.Tstart, true), Mission.Tstop and UTILS.SecondsToClock(Mission.Tstop, true) or "N/A")
|
||||
local text=string.format("Added %s mission %s starting at %s, stopping at %s",
|
||||
tostring(Mission.type), tostring(Mission.name), UTILS.SecondsToClock(Mission.Tstart, true), Mission.Tstop and UTILS.SecondsToClock(Mission.Tstop, true) or "INF")
|
||||
self:I(self.lid..text)
|
||||
|
||||
return self
|
||||
@@ -1337,8 +1340,8 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To)
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
local Cstart= UTILS.SecondsToClock(mission.Tstart, true)
|
||||
local Cstop = mission.Tstop and UTILS.SecondsToClock(mission.Tstop, true) or "INF"
|
||||
text=text..string.format("\n[%d] %s (%s) status=%s, Time=%s-%s, waypoint=%s, prio=%d targets=%d",
|
||||
i, tostring(mission.name), mission.type, tostring(mission.status), Cstart, Cstop, tostring(mission.waypointindex), mission.prio, mission:CountMissionTargets())
|
||||
text=text..string.format("\n[%d] %s (%s) status=%s (%s), Time=%s-%s, prio=%d targets=%d",
|
||||
i, tostring(mission.name), mission.type, mission:GetFlightStatus(self), tostring(mission.status), Cstart, Cstop, mission.prio, mission:CountMissionTargets())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
|
||||
@@ -2990,30 +2993,48 @@ function FLIGHTGROUP:onafterTaskUnpause(From, Event, To)
|
||||
--self.task
|
||||
end
|
||||
|
||||
--- On after "TaskCancel" event. Cancels the current task.
|
||||
--- On after "TaskCancel" event. Cancels the current task or simply sets the status to DONE if the task is not the current one.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterTaskCancel(From, Event, To)
|
||||
-- @param #FLIGHTGROUP.Task Task The task to cancel. Default is the current task (if any).
|
||||
function FLIGHTGROUP:onafterTaskCancel(From, Event, To, Task)
|
||||
|
||||
-- Get current task.
|
||||
local task=self:GetTaskCurrent()
|
||||
local currenttask=self:GetTaskCurrent()
|
||||
|
||||
if task then
|
||||
Task=Task or currenttask
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Task %s ID=%d cancelled.", task.description, task.id)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
if Task then
|
||||
|
||||
-- Check if the task is the current task?
|
||||
if currenttask and Task.id==currenttask.id then
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Current task %s ID=%d cancelled", Task.description, Task.id)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone()
|
||||
Task.stopflag:Set(1)
|
||||
|
||||
else
|
||||
|
||||
self:I(self.lid..string.format("TaskCancel: Setting task %s ID=%d to DONE", Task.description, Task.id))
|
||||
Task.status=FLIGHTGROUP.TaskStatus.DONE
|
||||
|
||||
if Task.type==FLIGHTGROUP.TaskType.WAYPOINT and Task.waypoint then
|
||||
self:RemoveWaypoint(Task.waypoint)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
local text=string.format("WARNING: No (current) task to cancel!")
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone()
|
||||
task.stopflag:Set(1)
|
||||
|
||||
else
|
||||
local text=string.format("WARNING: No current task to cancel!")
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -3152,19 +3173,26 @@ end
|
||||
function FLIGHTGROUP:onafterMissionCancel(From, Event, To, Mission)
|
||||
|
||||
if self.currentmission and Mission.auftragsnummer==self.currentmission then
|
||||
|
||||
local Task=Mission:GetFlightWaypointTask(self)
|
||||
|
||||
env.info(string.format("FF Cancel current mission %s. Task=%s", tostring(Mission.name), tostring(Task and Task.description or "WTF")))
|
||||
|
||||
-- Cancelling the mission is actually cancelling the current task. This will trigger the task done.
|
||||
self:TaskCancel()
|
||||
self:TaskCancel(Task)
|
||||
|
||||
self.currentmission=nil
|
||||
|
||||
else
|
||||
|
||||
-- Not the current mission. So set status in queue.
|
||||
-- TODO: remove mission from queue?
|
||||
|
||||
-- Set missin flight status.
|
||||
Mission:SetFlightStatus(self, AUFTRAG.Status.CANCELLED)
|
||||
-- TODO: remove mission from queue?
|
||||
|
||||
end
|
||||
|
||||
-- Set missin flight status.
|
||||
env.info("FF setting mission to cancelled")
|
||||
Mission:SetFlightStatus(self, AUFTRAG.Status.CANCELLED)
|
||||
|
||||
end
|
||||
|
||||
@@ -3206,21 +3234,20 @@ function FLIGHTGROUP:RouteToMission(mission, delay)
|
||||
-- Next waypoint.
|
||||
local nextwaypoint=self.currentwp+1
|
||||
|
||||
-- Execute mission at the given waypoint (but ensure it has not been passed already) or the next waypoint.
|
||||
mission.waypointindex=mission.waypointindex and math.max(mission.waypointindex, nextwaypoint) or nextwaypoint
|
||||
|
||||
-- Add waypoint.
|
||||
self:AddWaypointAir(mission.waypointcoord, mission.waypointindex, self.speedmax*0.8, false)
|
||||
self:AddWaypointAir(mission.waypointcoord, nextwaypoint, self.speedmax*0.8, false)
|
||||
|
||||
-- Add waypoint task. UpdateRoute is called inside.
|
||||
-- TODO: The waypoint task is different for all assinged flights!
|
||||
mission.waypointtask=self:AddTaskWaypoint(mission.DCStask, mission.waypointindex, mission.name, mission.prio, mission.duration)
|
||||
local waypointtask=self:AddTaskWaypoint(mission.DCStask, nextwaypoint, mission.name, mission.prio, mission.duration)
|
||||
|
||||
-- Set waypoint task.
|
||||
mission:SetFlightWaypointTask(self, waypointtask)
|
||||
|
||||
-- TODO: better marker text, mission.maker
|
||||
mission.marker=mission.waypointcoord:MarkToCoalition(mission.name, self:GetCoalition(), true)
|
||||
|
||||
|
||||
self:SetROE(mission.optionROE)
|
||||
--self:SetROE(mission.optionROE)
|
||||
|
||||
end
|
||||
end
|
||||
@@ -3937,7 +3964,7 @@ function FLIGHTGROUP:AddWaypointAir(coordinate, wpnumber, speed, updateroute)
|
||||
-- Shift all waypoint tasks after the inserted waypoint.
|
||||
for _,_task in pairs(self.taskqueue) do
|
||||
local task=_task --#FLIGHTGROUP.Task
|
||||
if task.type==FLIGHTGROUP.TaskType.WAYPOINT and task.status==FLIGHTGROUP.TaskStatus.SCHEDULED and task.waypoint>=wpnumber then
|
||||
if task.type==FLIGHTGROUP.TaskType.WAYPOINT and task.waypoint and task.waypoint>=wpnumber then
|
||||
task.waypoint=task.waypoint+1
|
||||
end
|
||||
end
|
||||
@@ -3945,7 +3972,7 @@ function FLIGHTGROUP:AddWaypointAir(coordinate, wpnumber, speed, updateroute)
|
||||
-- Shift all mission waypoints after the inserted waypoint.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
if mission.status==AUFTRAG.Status.SCHEDULED and mission.waypointindex and mission.waypointindex>=wpnumber then
|
||||
if mission.waypointindex and mission.waypointindex>=wpnumber then
|
||||
mission.waypointindex=mission.waypointindex+1
|
||||
end
|
||||
end
|
||||
@@ -3958,26 +3985,36 @@ function FLIGHTGROUP:AddWaypointAir(coordinate, wpnumber, speed, updateroute)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the landing waypoint.
|
||||
--- Remove a waypoint.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The destination airbase.
|
||||
-- @param #number wpnumber Waypoint number. Default at the end.
|
||||
-- @param #number speed Speed in knots. Default 350 kts.
|
||||
-- @param #number wpindex Waypoint number.
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:RemoveWaypoint(wpindex)
|
||||
|
||||
for i, wp in pairs(self.waypoints) do
|
||||
if i==wpindex then
|
||||
table.remove(self.waypoints, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
-- Remove waypoint.
|
||||
table.remove(self.waypoints, wpindex)
|
||||
|
||||
-- Shift all waypoint tasks after the removed waypoint.
|
||||
for _,_task in pairs(self.taskqueue) do
|
||||
local task=_task --#FLIGHTGROUP.Task
|
||||
if task.type==FLIGHTGROUP.TaskType.WAYPOINT and task.waypoint and task.waypoint>wpindex then
|
||||
task.waypoint=task.waypoint-1
|
||||
end
|
||||
end
|
||||
|
||||
-- Shift all mission waypoints after the removerd waypoint.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
if mission.waypointindex and mission.waypointindex>wpindex then
|
||||
mission.waypointindex=mission.waypointindex-1
|
||||
end
|
||||
end
|
||||
|
||||
--TODO update route?
|
||||
-- no, if <= self.currentwaypoint or WP is landing.
|
||||
|
||||
--TODO shift task and mission waypoints
|
||||
|
||||
self:__UpdateRoute(-1)
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user