public void IterationStarting(int iteration)
        {
            // initialize data structures
            _householdsByPD = ZoneSystemHelper.CreatePdArray <PDData>(Root.ZoneSystem.ZoneArray);
            var flat = _householdsByPD.GetFlatData();

            for (int i = 0; i < flat.Length; i++)
            {
                flat[i] = new PDData(_householdsByPD.GetSparseIndex(i));
            }
        }
        private int SavePersons(List<KeyValuePair<int, int>>[] results, PDData[] pds, ref int totalPerson)
        {
            int householdID;
            var zoneArray = Root.ZoneSystem.ZoneArray;
            var zones = zoneArray.GetFlatData();
            var workersPF = new float[zones.Length];
            var workersGF = new float[zones.Length];
            var workersSF = new float[zones.Length];
            var workersMF = new float[zones.Length];
            var workersPP = new float[zones.Length];
            var workersGP = new float[zones.Length];
            var workersSP = new float[zones.Length];
            var workersMP = new float[zones.Length];

            var workersCatPF = new float[zones.Length][];
            var workersCatGF = new float[zones.Length][];
            var workersCatSF = new float[zones.Length][];
            var workersCatMF = new float[zones.Length][];
            var workersCatPP = new float[zones.Length][];
            var workersCatGP = new float[zones.Length][];
            var workersCatSP = new float[zones.Length][];
            var workersCatMP = new float[zones.Length][];
            for(int i = 0; i < zones.Length; i++)
            {
                workersCatPF[i] = new float[3];
                workersCatGF[i] = new float[3];
                workersCatSF[i] = new float[3];
                workersCatMF[i] = new float[3];
                workersCatPP[i] = new float[3];
                workersCatGP[i] = new float[3];
                workersCatSP[i] = new float[3];
                workersCatMP[i] = new float[3];
            }
            using (var writer = new StreamWriter(PersonFile))
            {
                householdID = 1;
                writer.WriteLine("HouseholdID,PersonNumber,Age,Sex,License,TransitPass,EmploymentStatus,Occupation,FreeParking,StudentStatus,EmploymentZone,SchoolZone");
                for(int i = 0; i < results.Length; i++)
                {
                    var households = pds[i].Households;
                    foreach(var record in results[i])
                    {
                        var zone = record.Key;
                        var persons = households[record.Value].Household.Persons;
                        var workerCategory = ClassifyHousehold(households[record.Value].Household);
                        for(int j = 0; j < persons.Length; j++)
                        {
                            totalPerson++;
                            writer.Write(householdID);
                            writer.Write(',');
                            writer.Write((j + 1));
                            writer.Write(',');
                            writer.Write(persons[j].Age);
                            writer.Write(',');
                            writer.Write(persons[j].Female ? "F," : "M,");
                            writer.Write(persons[j].Licence ? "Y," : "N,");
                            switch(persons[j].TransitPass)
                            {
                                case TransitPass.Metro:
                                    writer.Write("M,");
                                    break;
                                case TransitPass.Go:
                                    writer.Write("G,");
                                    break;
                                case TransitPass.Combination:
                                    writer.Write("C,");
                                    break;
                                default:
                                    writer.Write("N,");
                                    break;
                            }
                            switch(persons[j].EmploymentStatus)
                            {
                                case TTSEmploymentStatus.FullTime:
                                    writer.Write("F,");
                                    break;
                                case TTSEmploymentStatus.PartTime:
                                    writer.Write("P,");
                                    break;
                                default:
                                    writer.Write("O,");
                                    break;
                            }
                            switch(persons[j].Occupation)
                            {
                                case Occupation.Professional:
                                    writer.Write("P,");
                                    break;
                                case Occupation.Office:
                                    writer.Write("G,");
                                    break;
                                case Occupation.Retail:
                                    writer.Write("S,");
                                    break;
                                case Occupation.Manufacturing:
                                    writer.Write("M,");
                                    break;
                                default:
                                    writer.Write("O,");
                                    break;
                            }
                            var workZone = persons[j].EmploymentZone;
                            var schoolZone = persons[j].SchoolZone;
                            if(!IsExternal(workZone))
                            {
                                switch(persons[j].EmploymentStatus)
                                {
                                    case TTSEmploymentStatus.FullTime:
                                        switch(persons[j].Occupation)
                                        {
                                            case Occupation.Professional:
                                                workersPF[zone] += 1;
                                                workersCatPF[zone][workerCategory] += 1;
                                                break;
                                            case Occupation.Office:
                                                workersGF[zone] += 1;
                                                workersCatGF[zone][workerCategory] += 1;
                                                break;
                                            case Occupation.Retail:
                                                workersSF[zone] += 1;
                                                workersCatSF[zone][workerCategory] += 1;
                                                break;
                                            case Occupation.Manufacturing:
                                                workersMF[zone] += 1;
                                                workersCatMF[zone][workerCategory] += 1;
                                                break;
                                        }
                                        break;
                                    case TTSEmploymentStatus.PartTime:
                                        switch(persons[j].Occupation)
                                        {
                                            case Occupation.Professional:
                                                workersPP[zone] += 1;
                                                workersCatPP[zone][workerCategory] += 1;
                                                break;
                                            case Occupation.Office:
                                                workersGP[zone] += 1;
                                                workersCatGP[zone][workerCategory] += 1;
                                                break;
                                            case Occupation.Retail:
                                                workersSP[zone] += 1;
                                                workersCatSP[zone][workerCategory] += 1;
                                                break;
                                            case Occupation.Manufacturing:
                                                workersMP[zone] += 1;
                                                workersCatMP[zone][workerCategory] += 1;
                                                break;
                                        }
                                        break;
                                }
                            }
                            writer.Write(persons[j].FreeParking ? "Y," : "N,");
                            switch(persons[j].StudentStatus)
                            {
                                case StudentStatus.FullTime:
                                    writer.Write("F,");
                                    break;
                                case StudentStatus.PartTime:
                                    writer.Write("P,");
                                    break;
                                default:
                                    writer.Write("O,");
                                    break;
                            }

                            // we don't save employment or school zone
                            if(IsExternal(workZone))
                            {
                                writer.Write(workZone.ZoneNumber);
                            }
                            else
                            {
                                writer.Write('0');
                            }
                            writer.Write(',');
                            if(IsExternal(schoolZone))
                            {
                                writer.Write(schoolZone.ZoneNumber);
                            }
                            else
                            {
                                writer.Write('0');
                            }
                            writer.WriteLine();
                        }
                        householdID++;
                    }
                }
            }
            SaveWorkerData(zones, Occupation.Professional, TTSEmploymentStatus.FullTime, workersPF);
            SaveWorkerData(zones, Occupation.Office, TTSEmploymentStatus.FullTime, workersGF);
            SaveWorkerData(zones, Occupation.Retail, TTSEmploymentStatus.FullTime, workersSF);
            SaveWorkerData(zones, Occupation.Manufacturing, TTSEmploymentStatus.FullTime, workersMF);
            SaveWorkerData(zones, Occupation.Professional, TTSEmploymentStatus.PartTime, workersPP);
            SaveWorkerData(zones, Occupation.Office, TTSEmploymentStatus.PartTime, workersGP);
            SaveWorkerData(zones, Occupation.Retail, TTSEmploymentStatus.PartTime, workersSP);
            SaveWorkerData(zones, Occupation.Manufacturing, TTSEmploymentStatus.PartTime, workersMP);

            SaveWorkerCategoryData(zones, Occupation.Professional, TTSEmploymentStatus.FullTime, workersCatPF);
            SaveWorkerCategoryData(zones, Occupation.Office, TTSEmploymentStatus.FullTime, workersCatGF);
            SaveWorkerCategoryData(zones, Occupation.Retail, TTSEmploymentStatus.FullTime, workersCatSF);
            SaveWorkerCategoryData(zones, Occupation.Manufacturing, TTSEmploymentStatus.FullTime, workersCatMF);
            SaveWorkerCategoryData(zones, Occupation.Professional, TTSEmploymentStatus.PartTime, workersCatPP);
            SaveWorkerCategoryData(zones, Occupation.Office, TTSEmploymentStatus.PartTime, workersCatGP);
            SaveWorkerCategoryData(zones, Occupation.Retail, TTSEmploymentStatus.PartTime, workersCatSP);
            SaveWorkerCategoryData(zones, Occupation.Manufacturing, TTSEmploymentStatus.PartTime, workersCatMP);

            return householdID;
        }
 private void Save(List<KeyValuePair<int, int>>[] results, PDData[] pds)
 {
     var zones = Root.ZoneSystem.ZoneArray.GetFlatData().Select(z => z.ZoneNumber).ToArray();
     int totalPerson = 0;
     var householdID = SaveHouseholds(results, pds, zones);
     householdID = SavePersons(results, pds, ref totalPerson);
     SaveSummeryFile(totalPerson, householdID);
 }
        private int SaveHouseholds(List<KeyValuePair<int, int>>[] results, PDData[] pds, int[] zones)
        {
            int householdID = 1;
            using (var writer = new StreamWriter(HouseholdFile))
            {
                writer.WriteLine("HouseholdID,Zone,ExpansionFactor,DwellingType,NumberOfPersons,NumberOfVehicles");
                for(int i = 0; i < results.Length; i++)
                {
                    var households = pds[i].Households;
                    foreach(var record in results[i])
                    {
                        var zone = record.Key;
                        var household = households[record.Value].Household;
                        writer.Write(householdID);
                        writer.Write(',');
                        writer.Write(zones[zone]);
                        // the expansion factor is always 1
                        writer.Write(",1,");
                        writer.Write((int)household.DwellingType);
                        writer.Write(',');
                        writer.Write(household.Persons.Length);
                        writer.Write(',');
                        writer.WriteLine(household.Vehicles.Length);
                        householdID++;
                    }
                }
            }

            return householdID;
        }
 public void IterationStarting(int iteration)
 {
     // initialize data structures
     HouseholdsByPD = ZoneSystemHelper.CreatePDArray<PDData>(Root.ZoneSystem.ZoneArray);
     var flat = HouseholdsByPD.GetFlatData();
     for(int i = 0; i < flat.Length; i++)
     {
         flat[i] = new PDData(HouseholdsByPD.GetSparseIndex(i));
     }
 }