context: /*
      Copyright 2014-2017 Travel Modelling Group, Department of Civil Engineering, University of Toronto
  
      This file is part of XTMF.
  
      XTMF is free software: you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation, either version 3 of the License, or
      (at your option) any later version.
  
      XTMF is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with XTMF.  If not, see <http://www.gnu.org/licenses/>.
  */
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Text;
  
  namespace Datastructure
  {
      public class OdcCreator2<T>
      {
          public int Times;
  
          public int Types;
  
          private SparseTwinIndex<float[]> Data;
  
          public OdcCreator2(SparseArray<T> sparseRepresentation, int types, int times)
          {
              Data = sparseRepresentation.CreateSquareTwinArray<float[]>();
              Types = types;
              Times = times;
          }
  
          public int HighestZone
          {
              get
              {
                  return Data.ValidIndexes().Last();
              }
          }
  
          /// <summary>
          /// Converts a csv file into odc.
          /// Multiple entries are stored as different types.
          /// </summary>
          /// <param name="csv">The CSV file to read</param>
          /// <param name="header">Does the CSV have a header?</param>
          /// <param name="offsetTimes">The offset into the times</param>
          /// <param name="offsetType">Should we offset the CSV's information in the types?</param>
          public void LoadCsvTimes(string csv, bool header, int offsetTimes, int offsetType)
          {
              // Gain access to the files
              using (StreamReader reader = new StreamReader(new
                  FileStream(csv, FileMode.Open, FileAccess.Read, FileShare.Read,
                  0x1000, FileOptions.SequentialScan)))
              {
                  string line;
                  var ammountOfData = Types * Times;
                  int injectIndex = Times * offsetType + offsetTimes;
                  if (header) reader.ReadLine();
                  // Read the line from the CSV
                  while ((line = reader.ReadLine()) != null)
                  {
                      // Calculate where to store the data
                      int pos, next;
                      int o = FastParse.ParseInt(line, 0, (pos = line.IndexOf(',')));
                      int d = FastParse.ParseInt(line, pos + 1, (next = line.IndexOf(',', pos + 1)));
                      pos = next + 1;
                      int length = line.Length;
                      int entry = 0;
                      var position = Data[o, d];
                      if (position == null)
                      {
                          Data[o, d] = position = new float[ammountOfData];
                      }
                      for (int i = pos; i < length; i++)
                      {
                          if (line[i] == ',')
                          {
                              position[injectIndex + entry] = FastParse.ParseFixedFloat(line, pos, i - pos);
                              entry++;
                              pos = i + 1;
                          }
                      }
                      if (pos < length)
                      {
                          position[injectIndex + entry] = FastParse.ParseFixedFloat(line, pos, length - pos);
                      }
                  }
                  // Close our access to the file streams
              }
          }
  
          /// <summary>
          /// Converts a csv file into odc.
          /// </summary>
          /// <param name="csv">The CSV file to read</param>
          /// <param name="header">Does the CSV have a header?</param>
          public void LoadCsvTypes(string csv, bool header)
          {
              LoadCsvTypes(csv, header, 0, 0);
          }
  
          /// <param name="csv">The file path to the csv file to load</param>
          /// <param name="header">Does the CSV have a header?</param>
          /// <param name="offset">Should we offset the CSV's information in the types?</param>
          public void LoadCsvTypes(string csv, bool header, int offset)
          {
              LoadCsvTypes(csv, header, 0, offset);
          }
  
          /// <summary>
          /// Converts a csv file into odc.
          /// Multiple entries are stored as different types.
          /// </summary>
          /// <param name="csv">The CSV file to read</param>
          /// <param name="header">Does the CSV have a header?</param>
          /// <param name="offsetTimes">The offset into the times</param>
          /// <param name="offsetType">Should we offset the CSV's information in the types?</param>
          public void LoadCsvTypes(string csv, bool header, int offsetTimes, int offsetType)
          {
              // Gain access to the files
              using (StreamReader reader = new StreamReader(new
                  FileStream(csv, FileMode.Open, FileAccess.Read, FileShare.Read,
                  0x1000, FileOptions.SequentialScan)))
              {
                  string line;
                  var ammountOfData = Types * Times;
                  int injectIndex = Times * offsetType + offsetTimes;
                  if (header) reader.ReadLine();
                  // Read the line from the CSV
  
                  while ((line = reader.ReadLine()) != null)
                  {
                      // Calculate where to store the data
                      string[] data = line.Split(',');
                      int o = int.Parse(data[0]);
                      int d = int.Parse(data[1]);
                      var position = Data[o, d];
                      if (position == null)
                      {
                          Data[o, d] = position = new float[ammountOfData];
                      }
                      int entry = 0;
                      for (int i = 2; i < data.Length; i++)
                      {
                          position[injectIndex + entry] = float.Parse(data[i]);
                          entry++;
                      }
                  }
                  // Close our access to the file streams
              }
          }
  
          /// <summary>
          /// Converts a csv file into odc.
          /// </summary>
          /// <summary>
          ///  Loads the data from an emme2 311 file into a ODC
          /// </summary>
          /// <param name="emme2File">The emm2 file to read from</param>
          /// <param name="offset">The type offset to use</param>
          public void LoadEmme2(string emme2File, int offset)
          {
              LoadEmme2(emme2File, 0, offset);
          }
  
          /// <summary>
          ///  Loads the data from an emme2 311 file into a ODC
          /// </summary>
          /// <param name="emme2File">The emm2 file to read from</param>
          /// <param name="offsetTimes">The time offset to use</param>
          /// <param name="offsetType">The type offset to use</param>
          public void LoadEmme2(string emme2File, int offsetTimes, int offsetType)
          {
              string line;
              int pos;
              var ammountOfData = Types * Times;
              // do this because highest zone isn't high enough for array indexes
              using (StreamReader reader = new StreamReader(new
                  FileStream(emme2File, FileMode.Open, FileAccess.Read, FileShare.Read,
                  0x1000, FileOptions.SequentialScan)))
              {
                  int injectIndex = Times * offsetType + offsetTimes;
                  while ((line = reader.ReadLine()) != null)
                  {
                      if (line.Length > 0 && line[0] == 'a') break;
                  }
                  while ((line = reader.ReadLine()) != null)
                  {
                      int length = line.Length;
                      // don't read blank lines
                      if (length < 7) continue;
                      int o = FastParse.ParseFixedInt(line, 0, 7);
                      pos = 7;
                      while (pos + 8 <= length)
                      {
                          int d = FastParse.ParseFixedInt(line, pos, 7);
                          var data = Data[o, d];
                          if (data == null)
                          {
                              Data[o, d] = data = new float[ammountOfData];
                          }
                          if (line[pos + 7] == ':')
                          {
                              data[injectIndex] = FastParse.ParseFixedFloat(line, pos + 8, 5);
                          }
                          else
                          {
                              data[injectIndex] = FastParse.ParseFixedFloat(line, pos + 8, (length > ((pos + 8) + 9) ? 9 : (length - (pos + 8))));
                          }
  
gt:                         pos += 13;