-- commas.lua
-- ----------------------------------------------------------
-- Rounding, duration, comma functions
-- See forum thread:
--  http://www.gammon.com.au/forum/?id=7805

--[[

This function rounds any number to the closest integer.
The "tricky" case is exactly half-way. 
That is, should 1.5 round to 1 or 2? How about -1.5?

This function rounds 1.5 "up" to 2, and -1.5 "down" to -2.

--]]

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


-- round "up" to absolute value, so we treat negative differently
--  that is, round (-1.5) will return -2
  
function round (x)
  if x >= 0 then
    return math.floor (x + 0.5)
  end  -- if positive

  return math.ceil (x - 0.5)
end -- function round

--[[

Duration

This function is designed to display a time interval in "short form". 
That is, rounded to the nearest major time interval. Some examples of intervals:


    * 3.6 days - displays "4 d"
    * 3.5 days - displays "4 d"
    * 3.4 days - displays "3 d"

    * 3.6 hours - displays "4 h"
    * 3.5 hours - displays "4 h"
    * 3.4 hours - displays "3 h"

    * 3.6 minutes - displays "4 m"
    * 3.5 minutes - displays "4 m"
    * 3.4 minutes - displays "3 m"

    * 59 seconds - displays "59 s"
    * 58 seconds - displays "58 s"
    * 57 seconds - displays "57 s" ... and so on to "0 s"


--]]

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

function convert_time (secs)

  -- handle negative numbers
  local sign = ""
  if secs < 0 then
    secs = math.abs (secs)
    sign = "-"
  end -- if negative seconds
  
  -- weeks
  if secs >= (60 * 60 * 24 * 6.5) then
    return sign .. round (secs / (60 * 60 * 24 * 7)) .. " w"
  end -- 6.5 or more days
  
  -- days
  if secs >= (60 * 60 * 23.5) then
    return sign .. round (secs / (60 * 60 * 24)) .. " d"
  end -- 23.5 or more hours
  
  -- hours
  if secs >= (60 * 59.5) then
   return sign .. round (secs / (60 * 60)) .. " h"
  end -- 59.5 or more minutes
  
  -- minutes
  if secs >= 59.5 then
   return sign .. round (secs / 60) .. " m"
  end -- 59.5 or more seconds
  
  -- seconds
  return sign .. round (secs) .. " s"    
end -- function convert_time 

--[[

Commas in numbers

This function adds commas to big numbers. 
For example 123456 becomes "123,456".

--]]

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

function commas (num)
  assert (type (num) == "number" or
          type (num) == "string")
  
  local result = ""

  -- split number into 3 parts, eg. -1234.545e22
  -- sign = + or -
  -- before = 1234
  -- after = .545e22

  local sign, before, after =
    string.match (tostring (num), "^([%+%-]?)(%d*)(%.?.*)$")

  -- pull out batches of 3 digits from the end, put a comma before them

  while string.len (before) > 3 do
    result = "," .. string.sub (before, -3, -1) .. result
    before = string.sub (before, 1, -4)  -- remove last 3 digits
  end -- while

  -- we want the original sign, any left-over digits, the comma part,
  -- and the stuff after the decimal point, if any
  return sign .. before .. result .. after

end -- function commas


-- trim leading and trailing spaces from a string
function trim (s)
  return (string.gsub (s, "^%s*(.-)%s*$", "%1"))
end -- trim
