This commit is contained in:
Frank
2019-09-03 16:59:20 +02:00
parent 93af911891
commit 254dd92cd8
5 changed files with 256 additions and 42 deletions
+113 -26
View File
@@ -200,6 +200,7 @@
SETTINGS = {
ClassName = "SETTINGS",
ShowPlayerMenu = true,
MenuShort = false,
}
@@ -233,7 +234,12 @@ do -- SETTINGS
return Settings
end
end
--- Sets the SETTINGS metric.
-- @param #SETTINGS self
function SETTINGS:SetMenutextShort(onoff)
self.MenuShort = onoff
end
--- Sets the SETTINGS metric.
-- @param #SETTINGS self
@@ -436,6 +442,8 @@ do -- SETTINGS
end
--- @param #SETTINGS self
-- @param Wrapper.Group#GROUP MenuGroup Group for which to add menus.
-- @param #table RootMenu Root menu table
-- @return #SETTINGS
function SETTINGS:SetSystemMenu( MenuGroup, RootMenu )
@@ -445,31 +453,66 @@ do -- SETTINGS
local SettingsMenu = MENU_GROUP:New( MenuGroup, MenuText, RootMenu ):SetTime( MenuTime )
local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, "A2G Coordinate System", SettingsMenu ):SetTime( MenuTime )
-------
-- A2G Coordinate System
-------
local text="A2G Coordinate System"
if self.MenuShort then
text="A2G Coordinates"
end
local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
-- Set LL DMS
if not self:IsA2G_LL_DMS() then
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
local text="Lat/Lon Degree Min Sec (LL DMS)"
if self.MenuShort then
text="LL DMS"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
end
-- Set LL DDM
if not self:IsA2G_LL_DDM() then
local text="Lat/Lon Degree Dec Min (LL DDM)"
if self.MenuShort then
text="LL DDM"
end
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
end
-- Set LL DMS accuracy.
if self:IsA2G_LL_DDM() then
local text1="LL DDM Accuracy 1"
local text2="LL DDM Accuracy 2"
local text3="LL DDM Accuracy 3"
if self.MenuShort then
text1="LL DDM"
end
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime )
end
-- Set BR.
if not self:IsA2G_BR() then
MENU_GROUP_COMMAND:New( MenuGroup, "Bearing, Range (BR)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime )
local text="Bearing, Range (BR)"
if self.MenuShort then
text="BR"
end
MENU_GROUP_COMMAND:New( MenuGroup, text , A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime )
end
-- Set MGRS.
if not self:IsA2G_MGRS() then
MENU_GROUP_COMMAND:New( MenuGroup, "Military Grid (MGRS)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
local text="Military Grid (MGRS)"
if self.MenuShort then
text="MGRS"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
end
-- Set MGRS accuracy.
if self:IsA2G_MGRS() then
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 1", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 2", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
@@ -477,15 +520,31 @@ do -- SETTINGS
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 4", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 4 ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime )
end
local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, "A2A Coordinate System", SettingsMenu ):SetTime( MenuTime )
-------
-- A2A Coordinate System
-------
local text="A2A Coordinate System"
if self.MenuShort then
text="A2A Coordinates"
end
local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
if not self:IsA2A_LL_DMS() then
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
local text="Lat/Lon Degree Min Sec (LL DMS)"
if self.MenuShort then
text="LL DMS"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
end
if not self:IsA2A_LL_DDM() then
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
local text="Lat/Lon Degree Dec Min (LL DDM)"
if self.MenuShort then
text="LL DDM"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
end
if self:IsA2A_LL_DDM() then
@@ -495,15 +554,27 @@ do -- SETTINGS
end
if not self:IsA2A_BULLS() then
MENU_GROUP_COMMAND:New( MenuGroup, "Bullseye (BULLS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime )
local text="Bullseye (BULLS)"
if self.MenuShort then
text="Bulls"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime )
end
if not self:IsA2A_BRAA() then
MENU_GROUP_COMMAND:New( MenuGroup, "Bearing Range Altitude Aspect (BRAA)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime )
local text="Bearing Range Altitude Aspect (BRAA)"
if self.MenuShort then
text="BRAA"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime )
end
if not self:IsA2A_MGRS() then
MENU_GROUP_COMMAND:New( MenuGroup, "Military Grid (MGRS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
local text="Military Grid (MGRS)"
if self.MenuShort then
text="MGRS"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
end
if self:IsA2A_MGRS() then
@@ -512,19 +583,35 @@ do -- SETTINGS
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 3", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 4", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 4 ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime )
end
local MetricsMenu = MENU_GROUP:New( MenuGroup, "Measures and Weights System", SettingsMenu ):SetTime( MenuTime )
end
local text="Measures and Weights System"
if self.MenuShort then
text="Unit System"
end
local MetricsMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
if self:IsMetric() then
MENU_GROUP_COMMAND:New( MenuGroup, "Imperial (Miles,Feet)", MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime )
local text="Imperial (Miles,Feet)"
if self.MenuShort then
text="Imperial"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime )
end
if self:IsImperial() then
MENU_GROUP_COMMAND:New( MenuGroup, "Metric (Kilometers,Meters)", MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime )
local text="Metric (Kilometers,Meters)"
if self.MenuShort then
text="Metric"
end
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime )
end
local MessagesMenu = MENU_GROUP:New( MenuGroup, "Messages and Reports", SettingsMenu ):SetTime( MenuTime )
local text="Messages and Reports"
if self.MenuShort then
text="Messages"
end
local MessagesMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
local UpdateMessagesMenu = MENU_GROUP:New( MenuGroup, "Update Messages", MessagesMenu ):SetTime( MenuTime )
MENU_GROUP_COMMAND:New( MenuGroup, "Off", UpdateMessagesMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.Update, 0 ):SetTime( MenuTime )
@@ -671,11 +758,11 @@ do -- SETTINGS
end
if self:IsA2A_MGRS() then
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 1", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 2", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 3", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 4", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 5", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 )
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 1", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 2", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 3", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 4", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 5", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 )
end
local MetricsMenu = MENU_GROUP:New( PlayerGroup, "Measures and Weights System", PlayerMenu )
@@ -92,7 +92,7 @@ CVW.version="0.0.5"
--- Create a new CVW class object for a specific aircraft carrier unit.
-- @param #CVW self
-- @param #string carriername Name of the carrier.
-- @param #string carriername Name of the carrier unit.
-- @param #string cvwname Name of the carrier air wing, e.g. "CVW-8".
-- @return #CVW self
function CVW:New(carriername, cvwname)
+28 -1
View File
@@ -5,6 +5,7 @@
-- * Monitor flight status of elements or entire group.
-- * Monitor fuel and ammo status.
-- * Sophisicated task queueing system.
-- * Many additional events for each element and the whole group.
--
--
-- ===
@@ -37,6 +38,7 @@
-- @field #boolean fuelcritical Fuel critical switch.
-- @field #number fuelcriticalthresh Critical fuel threshold in percent.
-- @field #boolean fuelcriticalrtb RTB on critical fuel switch.
-- @field Ops.Squadron#SQUADRON squadron The squadron the flight group belongs to.
-- @extends Core.Fsm#FSM
--- Be surprised!
@@ -76,6 +78,7 @@ FLIGHTGROUP = {
fuelcritical = nil,
fuelcriticalthresh = nil,
fuelcriticalrtb = false,
squadron = nil,
}
@@ -178,7 +181,7 @@ FLIGHTGROUP.version="0.0.8"
-- TODO: Get ammo.
-- TODO: Get pylons.
-- TODO: Fuel threshhold ==> RTB.
-- TODO: ROE, Afterburner restrict
-- TODO: ROE, Afterburner restrict.
-- TODO: Respawn? With correct loadout, fuelstate.
-- TODO: Waypoints, read, add, insert, detour.
-- TODO: Damage?
@@ -410,6 +413,23 @@ function FLIGHTGROUP:AddTaskWaypoint(description, task, waypointindex, prio, dur
return self
end
--- Set squadron the flight group belongs to.
-- @param #FLIGHTGROUP self
-- @param Ops.Squadron#SQUADRON squadron The squadron object.
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetSquadron(squadron)
self.squadron=squadron
return self
end
--- Get squadron the flight group belongs to.
-- @param #FLIGHTGROUP self
-- @return Ops.Squadron#SQUADRON The squadron object.
function FLIGHTGROUP:GetSquadron()
return self.squadron
end
--- Set low fuel threshold. Triggers event "FuelLow" and calls event function "OnAfterFuelLow".
-- @param #FLIGHTGROUP self
-- @param #number threshold Fuel threshold in percent. Default 25 %.
@@ -448,6 +468,13 @@ function FLIGHTGROUP:GetGroup()
return self.flightgroup
end
--- Get flight group name.
-- @param #FLIGHTGROUP self
-- @return #string Group name.
function FLIGHTGROUP:GetName()
return self.flightgroup:GetName()
end
--- Check if flight is airborne.
-- @param #FLIGHTGROUP self
-- @return #boolean
+112 -14
View File
@@ -16,6 +16,8 @@
-- @field #string ClassName Name of the class.
-- @field #boolean Debug Debug mode. Messages to all about status.
-- @field #string sid Class id string for output to DCS log file.
-- @field #string livery Livery of the squadron.
-- @field #table flights Table of flight groups.
-- @extends Core.Fsm#FSM
--- Be surprised!
@@ -33,12 +35,15 @@ SQUADRON = {
ClassName = "SQUADRON",
Debug = nil,
sid = nil,
assets = {},
livery = nil,
flights = {},
tasks = {},
livery = nil,
}
--- Flight group element.
-- @type SQUADRON.Flight
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group object.
-- @field #string mission Mission assigned to the flight.
--- SQUADRON class version.
-- @field #string version
@@ -58,15 +63,19 @@ SQUADRON.version="0.0.1"
--- Create a new SQUADRON object and start the FSM.
-- @param #SQUADRON self
-- @param #string squadronname Name of the squadron, e.g. "VFA-37".
-- @param Wrapper.Airbase#AIRBASE airbase Home airbase object of the squadron.
-- @param #table Table of squadron tasks, e.g. {SQUADRON.Task.INTERCEPT, SQUADRON.Task.SEAD}.
-- @return #SQUADRON self
function SQUADRON:New(squadronname, tasks)
function SQUADRON:New(squadronname, airbase, tasks)
-- Inherit everything from WAREHOUSE class.
local self=BASE:Inherit(self, FSM:New()) -- #SQUADRON
--self.flightgroup=AIGroup
self.squadronname=tostring(name)
self.squadronname=tostring(squadronname)
-- Set home airbase.
self.homebase=airbase
-- Set some string id for output to DCS.log file.
self.sid=string.format("SQUADRON %s | ", self.squadronname)
@@ -76,16 +85,15 @@ function SQUADRON:New(squadronname, tasks)
-- Init set of detected units.
self.detectedunits=SET_UNIT:New()
self.assets={}
-- TODO Tasks?
self.tasks=tasks or {}
-- Add FSM transitions.
-- From State --> Event --> To State
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
-- From State --> Event --> To State
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
self:AddTransition("*", "FlightStatus", "*") -- SQUADRON status update
self:AddTransition("*", "SquadronStatus", "*") -- SQUADRON status update
------------------------
--- Pseudo Functions ---
@@ -109,11 +117,11 @@ function SQUADRON:New(squadronname, tasks)
-- @param #number delay Delay in seconds.
--- Triggers the FSM event "FlightStatus".
-- @function [parent=#SQUADRON] FlightStatus
-- @function [parent=#SQUADRON] SquadronStatus
-- @param #SQUADRON self
--- Triggers the FSM event "SkipperStatus" after a delay.
-- @function [parent=#SQUADRON] __FlightStatus
-- @function [parent=#SQUADRON] __SquadronStatus
-- @param #SQUADRON self
-- @param #number delay Delay in seconds.
@@ -131,9 +139,99 @@ function SQUADRON:New(squadronname, tasks)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set livery.
-- @param #SQUADRON self
-- @param #string liveryname Name of the livery.
-- @return #SQUADRON self
function SQUADRON:SetLivery(liveryname)
self.livery=liveryname
end
--- Add flight group(s) to squadron.
-- @param #SQUADRON self
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup Flight group.
-- @return #SQUADRON self
function SQUADRON:AddFlightGroup(flightgroup)
local text=string.format("Adding flight group %s to squadron", flightgroup:GetName())
self:I(self.sid..text)
-- Set squadron.
flightgroup:SetSquadron(self)
table.insert(self.flightgroups, flightgroup)
function flightgroup:OnAfterDetectedUnit(From,Event,To,Unit)
self:GetSquadron():DetectedUnit(Unit)
end
function flightgroup:OnAfterFlightAirborne(From,Event,To)
self:GetSquadron():FlightAirborne(self)
end
function flightgroup:OnAfterFlightDead(From,Event,To)
self:GetSquadron():FlightDead(self)
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Start & Status
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
-- @param #SQUADRON self
-- @param Wrapper.Group#GROUP Group Flight group.
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function SQUADRON:onafterStart(From, Event, To)
-- Short info.
local text=string.format("Starting flight group %s.", self.groupname)
self:I(self.sid..text)
-- Start the status monitoring.
self:__SquadronStatus(-1)
end
--- On after "FlightStatus" event.
-- @param #SQUADRON self
-- @param Wrapper.Group#GROUP Group Flight group.
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function SQUADRON:onafterSquadronStatus(From, Event, To)
-- FSM state.
local fsmstate=self:GetState()
-- Check if group has detected any units.
self:_CheckFlightStatus()
-- Short info.
local text=string.format("Flight status %s [%d/%d]. Task=%d/%d. Waypoint=%d/%d. Detected=%d", fsmstate, #self.element, #self.element, self.taskcurrent, #self.taskqueue, self.currentwp or 0, #self.waypoints or 0, self.detectedunits:Count())
self:I(self.sid..text)
end
--- On after "FlightStatus" event.
-- @param #SQUADRON self
function SQUADRON:_CheckFlightstatus()
for _,_flight in pairs(self.flights) do
local flight=_flight --#SQUADRON.Flight
flight.flightgroup:IsSpawned()
end
end
@@ -436,6 +436,7 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
end
-- 024 23' 12"N or 024 23' 12.031"N
return string.format('%03d', latDeg) .. ' ' .. string.format('%02d', latMin) .. '\' ' .. string.format(secFrmtStr, latSec) .. '"' .. latHemi .. ' '
.. string.format('%03d', lonDeg) .. ' ' .. string.format('%02d', lonMin) .. '\' ' .. string.format(secFrmtStr, lonSec) .. '"' .. lonHemi
@@ -461,6 +462,7 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
minFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
end
-- 024 23'N or 024 23.123'N
return string.format('%03d', latDeg) .. ' ' .. string.format(minFrmtStr, latMin) .. '\'' .. latHemi .. ' '
.. string.format('%03d', lonDeg) .. ' ' .. string.format(minFrmtStr, lonMin) .. '\'' .. lonHemi