utilities.lua

--- General utilities, that are useful to utilise.
-- @module Utilities

--------------------------------------------------------
--- General utilities
-- @section general

function padnum ( _input, _minDecimalDigits)

    -- Get how many digits are after the decimal point. We can't allow a DecimalDigits less than this.
     _numberDecimals = string.gsub( string.match( tostring(_input), "%.%d+$"),"%.", "") or 0
    _numberDecimals = #_numberDecimals

    if _numberDecimals > _minDecimalDigits then
        _minDecimalDigits = _numberDecimals
        echo("Hey, _numberDecimals is bigger than _minDecimalDigits!\n")
    end

    echo("Input: "..tostring(_input).."\nDesired minimum decimal digits: ".._precision.."\nDecimal digits in input: ".._numberDecimals.."\nFinal string: ")

    return string.format( "%.0".._minDecimalDigits.."f", _input) or "error"

end

--- Rounds things to nearest integer, just like it sounds.
--
-- Somehow Math.round() isn't a thing. This is stupidly simple though, just adds 0.5 to our input and floors it.
-- @tparam number _input Number to round.
-- @tparam[opt] number _precision Number of decimal places to round to. Default 0.
-- @return Input rounded to nearest integer.
function round(_input, _precision)
    if _precision then
        if _precision > 0 then
            _precision = 10^_precision
            return math.floor(( (_input) * _precision )+ 0.5) / _precision
        elseif _precision <= 0  then
            return math.floor(_input + 0.5)
        end
    else
        return math.floor(_input + 0.5)
    end
end



-------------------------

--- Mimics C#/JS switch functionality.
--
-- Fails to optional entry _default if check fails, otherwise raises error.
-- @param _keyToCheck Input to check against keys in _caseTable
-- @tparam table _caseTable Key-value table, with keys being cases, and values being their returns
-- @return Value of _caseTable[_keyToCheck]
-- @raise Exception if key not found and no _default entry
-- @usage -- Function will return "I'm true", since 1 == 1
-- local truthiness = switch( 1 == 1, {
--   [true] = "I'm true!",
--   [false] = "I'm false!",
--   _default = "I'm neither, so probably nil!"
-- })
-- @usage -- Function will retrieve function B, and then ourFunction() will be executable
-- local functionTable = {
--   ["Function A"] = function() echo("I'm A!")        end
--   ["Function B"] = function() echo("I'm B!")        end
--   ["Function C"] = function() echo("I'm C!")        end
--   _default       = function() echo("I'm _default!") end
-- }
--
-- local ourFunction = switch( "Function B", functionTable)
-- ourFunction()  -- echo("I'm B!")
function switch(_keyToCheck, _caseTable)

    local case = false

    if _caseTable[_keyToCheck] then
        case = _caseTable[_keyToCheck]
        resultKey = tostring(_keyToCheck)
    elseif _caseTable["_default"] then
        case = _caseTable["_default"]
        resultKey = "_default"
    else
        error("switch() - Key not found in case table!")
    end

    return case, type(case)

end

-------------------------

--- Turns things from string to bool, duh.
-- @tparam string _input The string to check
function tobool(_input)

    _cleanInput = string.lower(string.trim(_input))

    if _cleanInput == "true" then
        return true
    elseif _cleanInput == "false" then
        return false
    else
        error("tobool() - Hey, \"".._input.."\" isn't something I can work with.")
    end

end








--------------------------------------------------------
--- Navigation utilities
-- @section navigation

--- Finds approximate 8-point compass direction from input heading.
-- @tparam num _heading Heading to convert.
-- @treturn string Nearest 8-point compass direction.
function headingToCardinal8(_heading)

    if _heading >= 360 then _heading = _heading - 360 end

    local _conversionTable = {
        [1] = {["cardinal"] = "N", ["minHeading"] = 337.5},
        [2] = {["cardinal"] = "NW", ["minHeading"] = 292.5},
        [3] = {["cardinal"] = "W", ["minHeading"] = 247.5},
        [4] = {["cardinal"] = "SW", ["minHeading"] = 202.5},
        [5] = {["cardinal"] = "S", ["minHeading"] = 157.5},
        [6] = {["cardinal"] = "SE", ["minHeading"] = 112.5},
        [7] = {["cardinal"] = "E", ["minHeading"] = 67.5},
        [8] = {["cardinal"] = "NE", ["minHeading"] = 22.5},
        [9] = {["cardinal"] = "N", ["minHeading"] = 0}
    }

    for k, v in ipairs(_conversionTable) do
        if _heading >= v.minHeading then return v.cardinal end
    end

    return -1

end

--- Finds approximate 16-point compass direction from input heading.
-- @tparam num _heading Heading to convert.
-- @treturn string Nearest 16-point compass direction.
function headingToCardinal16(_heading)

    while _heading >= 360 do _heading = _heading - 360 end

    local _conversionTable = {
        [1] = {["cardinal"] = "N", ["minHeading"] = 348.75},
        [2] = {["cardinal"] = "NNW", ["minHeading"] = 326.25},
        [3] = {["cardinal"] = "NW", ["minHeading"] = 303.75},
        [4] = {["cardinal"] = "WNW", ["minHeading"] = 281.25},
        [5] = {["cardinal"] = "W", ["minHeading"] = 258.75},
        [6] = {["cardinal"] = "WSW", ["minHeading"] = 236.25},
        [7] = {["cardinal"] = "SW", ["minHeading"] = 213.75},
        [8] = {["cardinal"] = "SSW", ["minHeading"] = 191.25},
        [9] = {["cardinal"] = "S", ["minHeading"] = 168.75},
        [10] = {["cardinal"] = "SSE", ["minHeading"] = 146.25},
        [11] = {["cardinal"] = "SE", ["minHeading"] = 123.75},
        [12] = {["cardinal"] = "ESE", ["minHeading"] = 101.25},
        [13] = {["cardinal"] = "E", ["minHeading"] = 78.75},
        [14] = {["cardinal"] = "ENE", ["minHeading"] = 56.25},
        [15] = {["cardinal"] = "NE", ["minHeading"] = 33.75},
        [16] = {["cardinal"] = "NNE", ["minHeading"] = 11.25},
        [17] = {["cardinal"] = "N", ["minHeading"] = 0}
    }

    for k, v in ipairs(_conversionTable) do
        if _heading >= v.minHeading then return v.cardinal end
    end

    return -1

end

--- Returns the opposite direction of a given cardinal direction.
-- @tparam num _cardinalDirection (e.g. "north", "e", "south-southwest", "ene")
-- @treturn float Heading in degrees
function invertDirection(_cardinalDirection)

    local _cardinalDirection = string.lower(string.trim(_cardinalDirection))

    local _lookupTable = {
        ["north"] = "south",
        ["north-northeast"] = "south-southwest",
        ["northeast"] = "southwest",
        ["east-northeast"] = "west-southwest",
        ["east"] = "west",
        ["east-southeast"] = "west-northwest",
        ["southeast"] = "northwest",
        ["south-southeast"] = "north-northwest",
        ["south"] = "north",
        ["south-southwest"] = "north-northeast",
        ["southwest"] = "northeast",
        ["west-southwest"] = "east-northeast",
        ["west"] = "east",
        ["west-northwest"] = "east-southeast",
        ["northwest"] = "southeast",
        ["north-northwest"] = "south-southeast",
        ["n"] = "s",
        ["nne"] = "ssw",
        ["ne"] = "sw",
        ["ene"] = "wsw",
        ["e"] = "w",
        ["ese"] = "wnw",
        ["se"] = "nw",
        ["sse"] = "nnw",
        ["s"] = "n",
        ["ssw"] = "nne",
        ["sw"] = "ne",
        ["wsw"] = "ene",
        ["w"] = "e",
        ["wnw"] = "ese",
        ["nw"] = "se",
        ["nnw"] = "sse"
    }

    return _lookupTable[_cardinalDirection] or false

end







--------------------------------------------------------
--- Unit conversion
-- @section unit

--- Does what it sounds like.
function mphToKmh(_input)
  return round(_input*1.609344)
end

--- Does what it sounds like.
function mphToMs(_input)
  return round (_input* 0.44704)
end

--- Does what it sounds like.
function fToC(_input)
  return round( (_input-32) / 1.8 )
end
generated by LDoc 1.4.3 Last updated 2021-01-24 20:08:44