    /* <CoffeeScript>
    {utils, Time} = require('tztime')

    csvStyleArray_To_ArrayOfMaps = (csvStyleArray, rowKeys) ->
    </CoffeeScript> */
      /**
       * @method csvStyleArray_To_ArrayOfMaps
       * @member Lumenize
       * @param {Array[]} csvStyleArray The first row is usually the list of column headers but if not, you can
       *   provide your own such list in the second parameter
       * @param {String[]} [rowKeys] specify the column headers like `['column1', 'column2']`. If not provided, it will use
       *   the first row of the csvStyleArray
       * @return {Object[]}
       *
       * `csvStyleArry_To_ArryOfMaps` is a convenience function that will convert a csvStyleArray like:
       *
       *     {csvStyleArray_To_ArrayOfMaps} = require('../')
       *
       *     csvStyleArray = [
       *       ['column1', 'column2'],
       *       [1         , 2       ],
       *       [3         , 4       ],
       *       [5         , 6       ]
       *     ]
       *
       * to an Array of Maps like this:
       *
       *     console.log(csvStyleArray_To_ArrayOfMaps(csvStyleArray))
       *
       *     # [ { column1: 1, column2: 2 },
       *     #   { column1: 3, column2: 4 },
       *     #   { column1: 5, column2: 6 } ]
       */
    /* <CoffeeScript>
      arrayOfMaps = []
      if rowKeys?
        i = 0
      else
        rowKeys = csvStyleArray[0]
        i = 1
      tableLength = csvStyleArray.length
      while i < tableLength
        inputRow = csvStyleArray[i]
        outputRow = {}
        for key, index in rowKeys
          outputRow[key] = inputRow[index]
        arrayOfMaps.push(outputRow)
        i++
      return arrayOfMaps

    arrayOfMaps_To_CSVStyleArray = (arrayOfMaps, fields) ->
    </CoffeeScript> */
      /**
       * @method arrayOfMaps_To_CSVStyleArray
       * @member Lumenize
       * @param {Object[]} arrayOfMaps
       * @param {String[]} [fields] If not provided, it will use the first row and get all fields
       * @return {Array[]} The first row will be the column headers
       *
       *    `arrayOfMaps_To_CSVStyleArray` is a convenience function that will convert an array of maps like:
       *
       *     {arrayOfMaps_To_CSVStyleArray} = require('../')
       *
       *     arrayOfMaps = [
       *       {column1: 10000, column2: 20000},
       *       {column1: 30000, column2: 40000},
       *       {column1: 50000, column2: 60000}
       *     ]
       *
       * to a CSV-style array like this:
       *
       *     console.log(arrayOfMaps_To_CSVStyleArray(arrayOfMaps))
       *
       *     # [ [ 'column1', 'column2' ],
       *     #   [ 10000, 20000 ],
       *     #   [ 30000, 40000 ],
       *     #   [ 50000, 60000 ] ]
       */
    /* <CoffeeScript>
      if arrayOfMaps.length == 0
        return []
      csvStyleArray = []
      outRow = []
      unless fields?
        fields = []
        for key, value of arrayOfMaps[0]
          fields.push(key)
      csvStyleArray.push(fields)

      for inRow in arrayOfMaps
        outRow = []
        for key in fields
          outRow.push(inRow[key])
        csvStyleArray.push(outRow)
      return csvStyleArray

    arrayOfMaps_To_HighChartsSeries = (arrayOfMaps, config) ->
    </CoffeeScript> */
      /**
       * @method arrayOfMaps_To_HighChartsSeries
       * @member Lumenize
       * @param {Array[]} arrayOfMaps
       * @param {Object} config You can use the same config you used to call TimeSeriesCalculator including your yAxis specifications
       * @return {Object[]} in HighCharts form
       *
       * Takes an array of arrays that came from a call to TimeSeriesCalculator and looks like this:
       *
       *     {arrayOfMaps_To_HighChartsSeries} = require('../')
       *
       *     arrayOfMaps = [
       *       {"Series 1": 8, "Series 2": 5, "Series3": 10},
       *       {"Series 1": 2, "Series 2": 3},
       *       {"Series 1": 1, "Series 2": 2, "Series3": 40},
       *     ]
       *
       * and a list of series configurations
       *
       *     config = [
       *       {name: "Series 1", yAxis: 1},
       *       {name: "Series 2"},
       *       {name: "Series3"}
       *     ]
       *
       * and extracts the data into seperate series
       *
       *     console.log(arrayOfMaps_To_HighChartsSeries(arrayOfMaps, config))
       *     # [ { name: 'Series 1', data: [ 8, 2, 1 ], yAxis: 1 },
       *     #   { name: 'Series 2', data: [ 5, 3, 2 ] },
       *     #   { name: 'Series3', data: [ 10, null, 40 ] } ]
       *
       * Notice how the extra fields from the series array are included in the output. Also, notice how the missing second
       * value for Series3 was replaced with a null. HighCharts will skip right over this for category charts as you would
       * expect.
       */
    /* <CoffeeScript>

      preOutput = {}

      seriesNames = []
      for a in config
        seriesNames.push(a.name)

      for s in seriesNames
        preOutput[s] = []
        for aggregationRow in arrayOfMaps
          value = aggregationRow[s]
          unless value?
            value = null
          preOutput[s].push(value)

      # Squash the nameField into each sub row
      output = []
      for s, idx in seriesNames
        outputRow = {name: s, data: preOutput[s]}
        seriesRow = config[idx]
        for key, value of seriesRow
          unless key in ['name', 'data']
            outputRow[key] = value
        output.push(outputRow)
      return output

    csvString_To_CSVStyleArray = (s, asterixForUndefined = true) ->  # This is not robust yet. Adding a comma inside a string will break it. It ignores stuff that fails JSON.parse. Etc.
      rows = s.split('\n')

      headerLength = rows[0].split(',').length

      out = []
      for row, index in rows
        newRow = []
        rawRowArray = row.split(',')
        if rawRowArray.length is headerLength
          for c in rawRowArray
            if asterixForUndefined and c is '*'
              cValue = undefined
            else
              try
                cValue = JSON.parse(c)
              catch error
                # Not sure what to do if this fails
            newRow.push(cValue)
          out.push(newRow)
        else
          #      throw new Error('Row length does not match header length.')
          console.log("Warning: Skipping row because length does not match header length in row #{index}: #{row}")

      return out

    csvStyleArray_To_CSVString = (csvStyleArray) ->
      s = ''
      for row in csvStyleArray
        for value in row
          s += JSON.stringify(value) + ', '
        s += "\n"
      return s

    exports.arrayOfMaps_To_CSVStyleArray = arrayOfMaps_To_CSVStyleArray
    exports.csvStyleArray_To_ArrayOfMaps = csvStyleArray_To_ArrayOfMaps
    exports.arrayOfMaps_To_HighChartsSeries = arrayOfMaps_To_HighChartsSeries
    exports.csvString_To_CSVStyleArray = csvString_To_CSVStyleArray
    exports.csvStyleArray_To_CSVString = csvStyleArray_To_CSVString

    </CoffeeScript> */