 
   def normalize_difference(pValue), do: pValue
 
-  # this has too many flag parameters
-  # it should be refactored to take a single options paramerter
-  def radians(pHour, pMinute, pAdjustHour \\ false, pNormalize \\ false, pPositiveResult \\ false, pCheckBounds \\ false)
-
-  def radians(pHour, pMinute, _pAdjustHour, _pNormalize, _pPositiveResult, true) when
+  def neuterOptions(pOptions) do
+    pOptions
+    |> Map.merge(%{normalize: false, positive: false})
+  end
+
+  def radians(pOptions \\ %{})
+
+  def radians(%{hour: pHour, minute: pMinute, bounds: true}) when
     pHour < 0 or @hours_in_day <= pHour or
     pMinute < 0 or @minutes_in_circle <= pMinute
   do
     :error
   end
 
+  # normalized positive result
+  def radians(%{normalize: true, positive: true} = pOptions) do
+    radians(pOptions |> neuterOptions)
+    |> normalize_difference
+  end
+
+  # normalize result
+  def radians(%{normalize: true} = pOptions) do
+    radians(pOptions |> neuterOptions)
+    |> normalize
+  end
+
+  # positive result
+  def radians(%{positive: true} = pOptions) do
+    radians(pOptions |> neuterOptions)
+    |> Kernel.abs
+  end
+
+  # adjust hour hand
+  def radians(%{hour: pHour, minute: pMinute, adjust: true}) do
+    minuteToRadians(pMinute) - hourToRadians(pHour) - adjustHourInRadians(pMinute)
+  end
+
   # do not adjust hour hand
-  def radians(pHour, pMinute, false, false, false, _pCheckBounds) do
+  def radians(%{hour: pHour, minute: pMinute}) do
     minuteToRadians(pMinute) - hourToRadians(pHour)
   end
 
-  # adjust hour hand
-  def radians(pHour, pMinute, true, false, false, _pCheckBounds) do
-    minuteToRadians(pMinute) - hourToRadians(pHour) - adjustHourInRadians(pMinute)
-  end
-
-  # normalize result
-  def radians(pHour, pMinute, pAdjustHour, true, false, pCheckBounds) do
-    radians(pHour, pMinute, pAdjustHour, false, false, pCheckBounds)
-    |> normalize
-  end
-
-  # positive result
-  def radians(pHour, pMinute, pAdjustHour, false, true, pCheckBounds) do
-    radians(pHour, pMinute, pAdjustHour, false, false, pCheckBounds)
-    |> Kernel.abs
-  end
-
-  # normalized positive result
-  def radians(pHour, pMinute, pAdjustHour, true, true, pCheckBounds) do
-    radians(pHour, pMinute, pAdjustHour, false, false, pCheckBounds)
-    |> normalize_difference
-  end
+  # catch all
+  def radians(_), do: :error
 end
 
 defmodule Format do

  def round(pValue, pPrecision), do: pValue |> Float.round(pPrecision)

  def case(pHour, pMinute, pExpected, pOptions) do
    adjust = pOptions[:adjust]
    normalize = pOptions[:normalize]
    positive = pOptions[:positive]
    bounds = pOptions[:bounds]
    precision = pOptions[:precision]

    actual = ClockAngle.radians(pHour, pMinute, adjust, normalize, positive, bounds)
    actual_rounded = actual |> round(precision)

    expected = pExpected

    {parsed, remaining, invalid} = OptionParser.parse(args, strict: switches, aliases: aliases)
    options = defaults
    |> Keyword.merge(parsed)
    |> Enum.into(%{})
    cond do
      options[:help] or (0 < length remaining) or (0 < length invalid) ->
        usage
