#region << Using Directives >>
using System;
using System.Collections.Generic;
using Volpe.Cafe;
using Volpe.Cafe.Data;
using Volpe.Cafe.Settings;
using TI = Volpe.Cafe.TechnologyIndexes;
#endregion
namespace Volpe.Cafe.Model
{
    public sealed class TechnologyApplicability
    {
        #region 
        static TechnologyApplicability()
        {
            TechSupersedes       = new int[TI.TechnologyCount][];
            TechSoftSupersedes   = new int[TI.TechnologyCount][];
            TechSupersedes2      = new int[TI.TechnologyCount][];
            TechDisallowBackfill = new int[TI.TechnologyCount][];
            TechKeys = new ulong[63];
            for (int i = 0; i < 63; i++) { TechKeys[i] = (ulong)Math.Pow(2, i); }
            TechTypes = new TechnologyType[] {TechnologyType.Engine, TechnologyType.DieselEngine, TechnologyType.Transmission,
                TechnologyType.Electrification, TechnologyType.MR, TechnologyType.ROLL, TechnologyType.DLR,
                TechnologyType.Aerodynamics, TechnologyType.Other};
            TechTypeCount = TechTypes.Length;
            RegClasses = new RegulatoryClass[] {RegulatoryClass.PassengerCar, RegulatoryClass.LightTruck, RegulatoryClass.LightTruck2b3};
            for (int i = 0; i < TI.TechnologyCount; i++)
            {
                TechSupersedes      [i] = new int[0];
                TechSoftSupersedes  [i] = new int[0];
                TechDisallowBackfill[i] = new int[0];
                switch (i)
                {
                    case TI.DCP:
                        TechSupersedes[i] = new int[] { TI.ICP };
                        break;
                    case TI.DVVLD:
                        TechDisallowBackfill[i] = new int[] { TI.CVVL };
                        break;
                    case TI.CVVL:
                        TechDisallowBackfill[i] = new int[] { TI.DVVLD };
                        break;
                    case TI.TRBDS1:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO };
                        break;
                    case TI.SEGR:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO, TI.TRBDS1 };
                        break;
                    case TI.DWNSP:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO, TI.TRBDS1, TI.SEGR };
                        break;
                    case TI.TRBDS2:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO, TI.TRBDS1, TI.SEGR, TI.DWNSP };
                        break;
                    case TI.CEGR1:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2 };
                        break;
                    case TI.CEGR2:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2,
                            TI.CEGR1 };
                        break;
                    case TI.MILLER:
                        TechSupersedes[i] = new int[] { TI.DEACS, TI.DEACD, TI.DEACO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2,
                            TI.CEGR1, TI.CEGR2 };
                        break;
                    case TI.LGDI:
                    case TI.CNG:
                    case TI.LNG:
                    case TI.LPG:
                        TechSupersedes[i] = new int[] { TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD,
                            TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2,
                            TI.MILLER };
                        TechDisallowBackfill[i] = new int[] { TI.LGDI, TI.CNG, TI.LNG, TI.LPG, TI.DSL, TI.DTURB, TI.EFRD, TI.DDOWN };
                        break;
                    case TI.DSL:
                        TechSupersedes[i] = new int[] { TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD,
                            TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2,
                            TI.MILLER };
                        TechDisallowBackfill[i] = new int[] { TI.LGDI, TI.CNG, TI.LNG, TI.LPG };
                        break;
                    case TI.DTURB:
                        TechSupersedes[i] = new int[] { TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD,
                            TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2,
                            TI.MILLER };
                        TechDisallowBackfill[i] = new int[] { TI.LGDI, TI.CNG, TI.LNG, TI.LPG };
                        break;
                    case TI.EFRD:
                        TechSupersedes[i] = new int[] { TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD,
                            TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2,
                            TI.MILLER };
                        TechDisallowBackfill[i] = new int[] { TI.LGDI, TI.CNG, TI.LNG, TI.LPG };
                        break;
                    case TI.DDOWN:
                        TechSupersedes[i] = new int[] { TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD,
                            TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO, TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2,
                            TI.MILLER };
                        TechDisallowBackfill[i] = new int[] { TI.LGDI, TI.CNG, TI.LNG, TI.LPG };
                        break;
                    case TI.HETRANSM:
                        TechSupersedes[i] = new int[] { TI.MAN6 };
                        break;
                    case TI.NAUTO:
                        TechSupersedes[i] = new int[] { TI.IATC };
                        break;
                    case TI.DCT:
                        TechSupersedes[i] = new int[] { TI.IATC, TI.NAUTO };
                        break;
                    case TI.A8SPD:
                        TechSupersedes[i] = new int[] { TI.IATC, TI.NAUTO, TI.DCT };
                        break;
                    case TI.ISG:
                        TechSupersedes[i] = new int[] { TI.MHEV };
                        break;
                    case TI.SHEV1:
                        TechSupersedes[i] = new int[] {
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.MHEV, TI.ISG };
                        TechDisallowBackfill[i] = new int[] { TI.SHEV2 };
                        break;
                    case TI.SHEV1_2:
                        TechSupersedes[i] = new int[] {
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.MHEV, TI.ISG, TI.SHEV1 };
                        TechDisallowBackfill[i] = new int[] { TI.SHEV2 };
                        break;
                    case TI.SHEV2:
                        TechSupersedes[i] = new int[] {
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.MHEV, TI.ISG };
                        TechDisallowBackfill[i] = new int[] { TI.SHEV1, TI.SHEV1_2 };
                        break;
                    case TI.PHEV1:
                        TechSupersedes[i] = new int[] {
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2 };
                        break;
                    case TI.PHEV2:
                        TechSupersedes[i] = new int[] {
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2, TI.PHEV1 };
                        break;
                    case TI.EV1:
                        TechSupersedes[i] = new int[] {
                            TI.LUB1, TI.EFR1, TI.LUB2_EFR2,
                            TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD, TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO,
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.LGDI, TI.CNG, TI.LNG, TI.LPG, TI.DSL, TI.DTURB, TI.EFRD, TI.DDOWN,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2, TI.PHEV1, TI.PHEV2 };
                        TechDisallowBackfill[i] = new int[] { TI.FCV };
                        break;
                    case TI.EV2:
                        TechSupersedes[i] = new int[] {
                            TI.LUB1, TI.EFR1, TI.LUB2_EFR2,
                            TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD, TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO,
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.LGDI, TI.CNG, TI.LNG, TI.LPG, TI.DSL, TI.DTURB, TI.EFRD, TI.DDOWN,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2, TI.PHEV1, TI.PHEV2, TI.EV1 };
                        TechDisallowBackfill[i] = new int[] { TI.FCV };
                        break;
                    case TI.EV3:
                        TechSupersedes[i] = new int[] {
                            TI.LUB1, TI.EFR1, TI.LUB2_EFR2,
                            TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD, TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO,
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.LGDI, TI.CNG, TI.LNG, TI.LPG, TI.DSL, TI.DTURB, TI.EFRD, TI.DDOWN,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2, TI.PHEV1, TI.PHEV2, TI.EV1, TI.EV2};
                        TechDisallowBackfill[i] = new int[] { TI.FCV };
                        break;
                    case TI.EV4:
                        TechSupersedes[i] = new int[] {
                            TI.LUB1, TI.EFR1, TI.LUB2_EFR2,
                            TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD, TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO,
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.LGDI, TI.CNG, TI.LNG, TI.LPG, TI.DSL, TI.DTURB, TI.EFRD, TI.DDOWN,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2, TI.PHEV1, TI.PHEV2, TI.EV1, TI.EV2, TI.EV3};
                        TechDisallowBackfill[i] = new int[] { TI.FCV };
                        break;
                    case TI.FCV:
                        TechSupersedes[i] = new int[] {
                            TI.LUB1, TI.EFR1, TI.LUB2_EFR2,
                            TI.CCPS, TI.DVVLS, TI.DEACS, TI.ICP, TI.DCP, TI.DVVLD, TI.CVVL, TI.DEACD, TI.SGDI, TI.DEACO, TI.VVA, TI.SGDIO,
                            TI.TRBDS1, TI.SEGR, TI.DWNSP, TI.TRBDS2, TI.CEGR1, TI.CEGR2, TI.MILLER,
                            TI.LGDI, TI.CNG, TI.LNG, TI.LPG, TI.DSL, TI.DTURB, TI.EFRD, TI.DDOWN,
                            TI.IATC, TI.NAUTO, TI.DCT, TI.A8SPD, TI.HETRANS, TI.SHFTOPT,
                            TI.MHEV, TI.ISG, TI.SHEV1, TI.SHEV1_2, TI.SHEV2, TI.PHEV1, TI.PHEV2 };
                        TechDisallowBackfill[i] = new int[] { TI.EV1, TI.EV2, TI.EV3, TI.EV4 };
                        break;
                } 
            } 
            for (int i = 0; i < TI.TechnologyCount; i++)
            {
                TechSupersedes2[i] = new int[TechSupersedes[i].Length + TechSoftSupersedes[i].Length];
                Array.Copy(TechSupersedes    [i], 0, TechSupersedes2[i],                        0, TechSupersedes    [i].Length);
                Array.Copy(TechSoftSupersedes[i], 0, TechSupersedes2[i], TechSupersedes[i].Length, TechSoftSupersedes[i].Length);
            } 
        }
        #endregion
        #region 
        #region 
        public static void Initialize(Component component, ModelingSettings settings)
        {
            Component.CModelData cmd = component.ModelData;
            cmd.TechUsed           = new bool[TI.TechnologyCount];
            cmd.TechApplied        = new bool[TI.TechnologyCount];
            cmd.TechAppliedYear    = new int [TI.TechnologyCount];
            cmd.TechSuperseded     = new bool[TI.TechnologyCount];
            cmd.TechSupersededYear = new int [TI.TechnologyCount];
            if (component.Vehicles.Count > 0)
            {
                Vehicle veh      = component.GetPlatformLeader();
                int[]   techList = component.TechnologyList;
                for (int i = 0; i < techList.Length; i++)
                {
                    int techIndex = techList[i];
                    if (veh.ModelData.TechUsed[techIndex])
                    {
                        cmd.TechUsed[techIndex] = true;
                    }
                }
            }
            component.UpdateComponentVersion(null, null);
        }
        public static void Initialize(Vehicle vehicle, ModelingSettings settings)
        {
            bool                      hasEng = (vehicle.Engine       != null);
            bool                      hasTrn = (vehicle.Transmission != null);
            Vehicle     .CDescription vd     = vehicle.Description;
            Engine      .CDescription ed     = (hasEng) ? vehicle.Engine      .Description : null;
            Transmission.CDescription td     = (hasTrn) ? vehicle.Transmission.Description : null;
            Vehicle     .CModelData   vmd    = vehicle.ModelData;   
            TechnologyClass  techClass    = vehicle.TechnologyClass;
            List<Technology> technologies = settings.Technologies;
            vmd.TechAvailable         = new bool[TI.TechnologyCount];
            vmd.TechUsed              = new bool[TI.TechnologyCount];
            vmd.TechInherited         = new bool[TI.TechnologyCount];
            vmd.TechApplied           = new bool[TI.TechnologyCount];
            vmd.TechAppliedYear       = new int [TI.TechnologyCount];
            vmd.TechSuperseded        = new bool[TI.TechnologyCount];
            vmd.TechSupersededYear    = new int [TI.TechnologyCount];
            vmd.TechEnabled           = new bool[TI.TechnologyCount];
            vmd.TechIgnored           = new bool[TI.TechnologyCount];
            for (int i = 0; i < vd.UsedTechnologies.Length; i++) { vmd.TechUsed[vd.UsedTechnologies[i]] = true; }
            for (int i = 0; i < vd.AvailableTechnologies.Length; i++)
            {
                int index = vd.AvailableTechnologies[i];
                vmd.TechAvailable[index] = technologies[index].Attributes[vehicle].Applicable;
            }
            if (hasEng)
            {
                for (int i = 0; i < ed.UsedTechnologies.Length; i++) { vmd.TechUsed[ed.UsedTechnologies[i]] = true; }
                for (int i = 0; i < ed.AvailableTechnologies.Length; i++)
                {
                    int index = ed.AvailableTechnologies[i];
                    vmd.TechAvailable[index] = technologies[index].Attributes[vehicle].Applicable;
                }
            }
            if (hasTrn)
            {
                for (int i = 0; i < td.UsedTechnologies.Length; i++) { vmd.TechUsed[td.UsedTechnologies[i]] = true; }
                for (int i = 0; i < td.AvailableTechnologies.Length; i++)
                {
                    int index = td.AvailableTechnologies[i];
                    vmd.TechAvailable[index] = technologies[index].Attributes[vehicle].Applicable;
                }
            }
            if (hasTrn && td.Type == "M")
            {
                TechnologyApplicability.RectifyDependencies_DisableDeacEng(vmd.TechAvailable);
            }
            if (!settings.OperatingModes.IgnoreWeightInMsApplication)
            {
                if (vd.CurbWeight < 5000)
                {   
                    vmd.TechAvailable[TI.MR1] = false;
                    vmd.TechAvailable[TI.MR2] = false;
                    vmd.TechAvailable[TI.MR3] = false;
                    vmd.TechAvailable[TI.MR4] = false;
                    vmd.TechAvailable[TI.MR5] = false;
                }
            }
            vmd.OffCycleCredit = 0;
            for (int i = 0; i < TI.TechnologyCount; i++)
            {
                if (vmd.TechUsed[i])
                {
                    vmd.OffCycleCredit += technologies[i].OffCycleCredit[vehicle.RegClass];
                }
            }
            TechnologyApplicability.RectifyDependencies(vehicle, null, -1, settings);
        }
        public static void Enable(Vehicle vehicle, ModelYear year, int techIndex, ModelingSettings settings)
        {
            Vehicle.CModelData vmd          = vehicle.ModelData;
            TechnologyClass    techClass    = vehicle.TechnologyClass;
            List<Technology>   technologies = settings.Technologies;
            if (techIndex == -1)
            {   
                for (int i = 0; i < TI.TechnologyCount; i++)
                {
                    TechnologyAttributes attr = technologies[i].Attributes[vehicle];
                    vmd.TechEnabled [i] = vmd.TechAvailable[i] &&
                        (settings.OperatingModes.IgnoreYearAvailable || attr.YearAvailable <= year.Year) &&
                        (attr.YearRetired == 0 || attr.YearRetired >= year.Year);
                    vmd.TechIgnored [i] = false;
                }
            }
            else
            {   
                TechnologyAttributes attr = technologies[techIndex].Attributes[vehicle];
                vmd.TechEnabled[techIndex] = vmd.TechAvailable[techIndex] &&
                    (attr.YearAvailable <= year.Year) &&
                    (attr.YearRetired == 0 || attr.YearRetired >= year.Year);
            }
            int sIdx = (techIndex == -1) ? 0                  : techIndex;
            int eIdx = (techIndex == -1) ? TI.TechnologyCount : techIndex + 1;
            if (!settings.OperatingModes.IgnoreRefreshRedesign)
            {   
                bool atRedesign = vehicle.IsAtRedesign(year);
                bool atRefresh  = vehicle.IsAtRefresh (year);
                for (int i = sIdx; i < eIdx; i++)
                {   
                    if (vmd.TechEnabled[i])
                    {   
                        if ((!atRedesign && TI.IsTiedToRedesign(i)) || (!atRedesign && !atRefresh && TI.IsTiedToRefresh(i)))
                        {
                            vmd.TechEnabled[i] = false;
                        }
                    } 
                } 
            }
            for (int i = eIdx - 1; i >= sIdx; i--)
            {
                if (vmd.TechUsed[i])
                {
                    if (TI.IsConversionToFCV (i)) { vehicle.HEVType = HEVType.FuelCell    ; break; }
                    if (TI.IsConversionToEV  (i)) { vehicle.HEVType = HEVType.PureElectric; break; }
                    if (TI.IsConversionToPHEV(i)) { vehicle.HEVType = HEVType.PlugInHybrid; break; }
                    if (TI.IsConversionToSHEV(i)) { vehicle.HEVType = HEVType.StrongHybrid; break; }
                    if (TI.IsConversionToMHEV(i)) { vehicle.HEVType = HEVType.MildHybrid  ; break; }
                }
            }
            TechnologyApplicability.RectifyDependencies(vehicle, year, techIndex, settings);
        }
        static void RectifyDependencies(Vehicle vehicle, ModelYear year, int techIdx, ModelingSettings settings)
        {
            Vehicle  .CModelData vmd =  vehicle.ModelData; 
            Component.CModelData emd = (vehicle.Engine       == null) ? null : vehicle.Engine      .ModelData;
            Component.CModelData tmd = (vehicle.Transmission == null) ? null : vehicle.Transmission.ModelData;
            Component.CModelData pmd = (vehicle.Platform     == null) ? null : vehicle.Platform    .ModelData;
            bool   updateTechEnabled = (year != null);
            bool    updateSuperseded = (techIdx != -1);
            bool[]            techAE = (updateTechEnabled) ? vmd.TechEnabled : vmd.TechAvailable;
            bool[]          techUsed = vmd.TechUsed;
            int sIdx = (techIdx == -1) ? 0                  : techIdx;
            int eIdx = (techIdx == -1) ? TI.TechnologyCount : techIdx + 1;
            bool hevRectified       = false;    
            bool advTurboRectified  = false;    
            bool advEngineRectified = false;    
            bool dslRectified       = false;    
            for (int i = sIdx; i < eIdx; i++)
            {   
                if (techUsed[i]) { techAE[i] = false; }
                RectifyDependenciesHelper(i, techUsed, techAE, updateTechEnabled, ref hevRectified, ref advTurboRectified,
                    ref advEngineRectified, ref dslRectified, vehicle, year, techIdx, settings);
                if (updateSuperseded)
                {
                    RectifyDependencies_UpdateSuperseded(i, vmd);
                    RectifyDependencies_UpdateSuperseded(i, emd);
                    RectifyDependencies_UpdateSuperseded(i, tmd);
                    RectifyDependencies_UpdateSuperseded(i, pmd);
                }
            } 
        }
        static void RectifyDependencies_UpdateSuperseded(int techIndex, Vehicle.CModelData vmd)
        {
            RectifyDependencies_UpdateSuperseded(techIndex, vmd.TechUsed, vmd.TechApplied, vmd.TechAppliedYear, vmd.TechSuperseded, vmd.TechSupersededYear);
        }
        static void RectifyDependencies_UpdateSuperseded(int techIndex, Component.CModelData cmd)
        {
            if (cmd != null)
            {
                RectifyDependencies_UpdateSuperseded(techIndex,
                    cmd.TechUsed, cmd.TechApplied, cmd.TechAppliedYear, cmd.TechSuperseded, cmd.TechSupersededYear);
            }
        }
        static void RectifyDependencies_UpdateSuperseded(int techIndex,
            bool[] techUsed, bool[] techApplied, int[] techAppliedYear, bool[] techSuperseded, int[] techSupersededYear)
        {
            if (!techUsed[techIndex] || !techApplied[techIndex]) { return; }
            int[] techSupersedes = TechSupersedes[techIndex];
            for (int j = 0; j < techSupersedes.Length; j++)
            {   
                if (techUsed[techSupersedes[j]] && !techSuperseded[techSupersedes[j]])
                {
                    techSuperseded    [techSupersedes[j]] = true;
                    techSupersededYear[techSupersedes[j]] = techAppliedYear[techIndex];
                }
            }
            int[] techSoftSupersedes = TechSoftSupersedes[techIndex];
            for (int j = 0; j < techSoftSupersedes.Length; j++)
            {   
                if (techUsed[techSoftSupersedes[j]] && techSupersededYear[techSoftSupersedes[j]] == 0)
                {   
                    if (techAppliedYear[techIndex] > techAppliedYear[techSoftSupersedes[j]])
                    {
                        techSupersededYear[techSoftSupersedes[j]] = techAppliedYear[techIndex];
                    }
                }
            }
        }
        static void RectifyDependenciesHelper(int i, bool[] techUsed, bool[] techArr, bool updateTechEnabled,
            ref bool hevRectified, ref bool advTurboRectified, ref bool advEngineRectified, ref bool dslRectified,
            Vehicle vehicle, ModelYear year, int techIdx, ModelingSettings settings)
        {
            switch (i)
            {
                case TI.LUB1:
                case TI.EFR1:
                case TI.LUB2_EFR2:
                    if (updateTechEnabled && !hevRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableHev(techArr, techUsed, vehicle, year, techIdx, settings);
                        hevRectified = true;    
                    }
                    break;
                case TI.CCPS:
                case TI.DVVLS:
                case TI.DEACS:
                    break;
                case TI.ICP:
                case TI.DEACD:
                    break;
                case TI.DCP:
                    if (techUsed[i]) { techArr[TI.ICP] = false; }
                    break;
                case TI.DVVLD:
                    if (techUsed[i]) { techArr[TI.CVVL] = false; }
                    break;
                case TI.CVVL:
                    if (techUsed[i]) { techArr[TI.DVVLD] = false; }
                    break;
                case TI.SGDI:
                    break;
                case TI.DEACO:
                case TI.VVA:
                case TI.SGDIO:
                    break;
                case TI.TRBDS1:
                case TI.SEGR:
                case TI.DWNSP:
                case TI.TRBDS2:
                case TI.CEGR1:
                case TI.CEGR2:
                case TI.MILLER:
                    if (techUsed[i])
                    {   
                        TechnologyApplicability.RectifyDependencies_DisableDeacEng(techArr);
                    }
                    if (updateTechEnabled && !hevRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableHev(techArr, techUsed, vehicle, year, techIdx, settings);
                        hevRectified = true;    
                    }
                    if (updateTechEnabled && !dslRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableDiesel(techArr, techUsed, vehicle, year, techIdx, settings);
                        dslRectified = true;    
                    }
                    break;
                case TI.LGDI:
                case TI.CNG:
                case TI.LNG:
                case TI.LPG:
                    if (techUsed[i])
                    {   
                        TechnologyApplicability.RectifyDependencies_DisableAllEng(techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllHev(techArr, true, true);
                    }
                    break;
                case TI.DSL:
                case TI.DTURB:
                case TI.EFRD:
                case TI.DDOWN:
                    if (techUsed[i])
                    {   
                        TechnologyApplicability.RectifyDependencies_DisableAllEng(techArr, false);
                        if (i == TI.DTURB) { techArr[TI.DSL] = false;  }
                        if (i == TI.EFRD ) { techArr[TI.DSL] = false; techArr[TI.DTURB] = false; }
                        if (i == TI.DDOWN) { techArr[TI.DSL] = false; techArr[TI.DTURB] = false; techArr[TI.EFRD] = false; }
                    }
                    if (updateTechEnabled && !hevRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableHev(techArr, techUsed, vehicle, year, techIdx, settings);
                        hevRectified = true;    
                    }
                    break;
                case TI.MAN6:
                case TI.HETRANSM:
                    if (techUsed[i])
                    {   
                        TechnologyApplicability.RectifyDependencies_DisableAutoTrn(techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllHev (techArr, true, true);
                        TechnologyApplicability.RectifyDependencies_DisableDeacEng(techArr);
                    }
                    if (updateTechEnabled && !advTurboRectified && (i == TI.MAN6))
                    {
                        TechnologyApplicability.RectifyDependencies_EnableAdvancedTurbo(techArr, techUsed, vehicle, year, techIdx, settings);
                        advTurboRectified = true;   
                    }
                    if (updateTechEnabled && !advEngineRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableAdvancedEngine(techArr, techUsed, vehicle, year, techIdx, settings);
                        advEngineRectified = true;   
                    }
                    break;
                case TI.IATC:
                case TI.NAUTO:
                case TI.DCT:
                case TI.A8SPD:
                case TI.HETRANS:
                case TI.SHFTOPT:
                    if (techUsed[i])
                    {   
                        TechnologyApplicability.RectifyDependencies_DisableManualTrn(techArr);
                        techArr[TI.IATC] = false;
                        if (i == TI.DCT) { techArr[TI.NAUTO] = false; }
                        if (i == TI.A8SPD) { techArr[TI.NAUTO] = false; techArr[TI.DCT] = false; }
                    }
                    if (updateTechEnabled && !advTurboRectified && (i == TI.A8SPD))
                    {
                        TechnologyApplicability.RectifyDependencies_EnableAdvancedTurbo(techArr, techUsed, vehicle, year, techIdx, settings);
                        advTurboRectified = true;   
                    }
                    if (updateTechEnabled && !advEngineRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableAdvancedEngine(techArr, techUsed, vehicle, year, techIdx, settings);
                        advEngineRectified = true;   
                    }
                    if (updateTechEnabled && !hevRectified)
                    {
                        TechnologyApplicability.RectifyDependencies_EnableHev(techArr, techUsed, vehicle, year, techIdx, settings);
                        hevRectified = true;    
                    }
                    break;
                case TI.EPS:
                case TI.IACC1:
                case TI.IACC2:
                case TI.MHEV:
                    break;
                case TI.ISG:
                    if (techUsed[i])
                    {   
                        RectifyDependencies_DisableAllElec(techArr);
                    }
                    break;
                case TI.SHEV1:
                    if (techUsed[i])
                    {
                        TechnologyApplicability.RectifyDependencies_DisableAllEng (techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllTrn (techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllElec(techArr);
                        techArr[TI.SHEV2] = false;
                    }
                    if (updateTechEnabled && !techUsed[i] && !techArr[i]) { techArr[TI.SHEV1_2] = false; }
                    break;
                case TI.SHEV1_2:
                    if (techUsed[i])
                    {
                        TechnologyApplicability.RectifyDependencies_DisableAllEng (techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllTrn (techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllElec(techArr);
                        techArr[TI.SHEV1] = false;
                        techArr[TI.SHEV2] = false;
                    }
                    break;
                case TI.SHEV2:
                    if (techUsed[i])
                    {
                        TechnologyApplicability.RectifyDependencies_DisableAllEng (techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllTrn (techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllElec(techArr);
                        techArr[TI.SHEV1  ] = false;
                        techArr[TI.SHEV1_2] = false;
                    }
                    break;
                case TI.PHEV1:
                    if (techUsed[i])
                    {
                        TechnologyApplicability.RectifyDependencies_DisableAllEng (techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllTrn (techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllElec(techArr);
                        techArr[TI.SHEV1  ] = false;
                        techArr[TI.SHEV1_2] = false;
                        techArr[TI.SHEV2  ] = false;
                    }
                    break;
                case TI.PHEV2:
                    if (techUsed[i])
                    {
                        TechnologyApplicability.RectifyDependencies_DisableAllEng (techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllTrn (techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllElec(techArr);
                        techArr[TI.SHEV1  ] = false;
                        techArr[TI.SHEV1_2] = false;
                        techArr[TI.SHEV2  ] = false;
                        techArr[TI.PHEV1  ] = false;
                    }
                    break;
                case TI.EV1:
                case TI.EV2:
                case TI.EV3:
                case TI.EV4:
                case TI.FCV:
                    if (techUsed[i])
                    {
                        TechnologyApplicability.RectifyDependencies_DisableAllEng (techArr, true);
                        TechnologyApplicability.RectifyDependencies_DisableAllTrn (techArr);
                        TechnologyApplicability.RectifyDependencies_DisableAllElec(techArr);
                        if (i == TI.EV4 || i == TI.FCV)
                        {   
                            TechnologyApplicability.RectifyDependencies_DisableAllHev(techArr, true, true);
                        }
                        else
                        {   
                            TechnologyApplicability.RectifyDependencies_DisableAllHev(techArr, false, true);
                            if (i == TI.EV2) { techArr[TI.EV1] = false; }
                            if (i == TI.EV3) { techArr[TI.EV1] = false; techArr[TI.EV2] = false; }
                        }
                    }
                    break;
                case TI.MR1:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.MR2] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.MR2, settings); }
                    }
                    break;
                case TI.MR2:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.MR3] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.MR3, settings); }
                    }
                    break;
                case TI.MR3:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.MR4] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.MR4, settings); }
                    }
                    break;
                case TI.MR4:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.MR5] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.MR5, settings); }
                    }
                    break;
                case TI.MR5:
                    break;
                case TI.ROLL1:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.ROLL2] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.ROLL2, settings); }
                    }
                    break;
                case TI.ROLL2:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.ROLL3] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.ROLL3, settings); }
                    }
                    break;
                case TI.ROLL3:
                    break;
                case TI.LDB:
                case TI.SAX:
                    break;
                case TI.AERO1:
                    if (updateTechEnabled)
                    {   
                        if      (!techUsed[i] ) { techArr[TI.AERO2] = false; }
                        else if (techIdx != -1) { TechnologyApplicability.Enable(vehicle, year, TI.AERO2, settings); }
                    }
                    break;
                case TI.AERO2:
                    break;
            } 
        }
        static void RectifyDependencies_DisableAllEng(bool[] techAE, bool disableDSL)
        {
            TechnologyApplicability.RectifyDependencies_DisableSohcEng(techAE, true);
            TechnologyApplicability.RectifyDependencies_DisableDohcEng(techAE, true);
            TechnologyApplicability.RectifyDependencies_DisableOhvEng (techAE);
            techAE[TI.LUB1     ] = false;
            techAE[TI.EFR1     ] = false;
            techAE[TI.LUB2_EFR2] = false;
            techAE[TI.TRBDS1] = false;
            techAE[TI.SEGR  ] = false;
            techAE[TI.DWNSP ] = false;
            techAE[TI.TRBDS2] = false;
            techAE[TI.CEGR1 ] = false;
            techAE[TI.CEGR2 ] = false;
            techAE[TI.MILLER] = false;
            techAE[TI.LGDI  ] = false;
            techAE[TI.CNG   ] = false;
            techAE[TI.LNG   ] = false;
            techAE[TI.LPG   ] = false;
            if (disableDSL)
            {
                TechnologyApplicability.RectifyDependencies_DisableAllDsl(techAE);
            }
        }
        static void RectifyDependencies_DisableSohcEng(bool[] techAE, bool disableSGDI)
        {
            techAE[TI.CCPS ] = false;
            techAE[TI.DVVLS] = false;
            techAE[TI.DEACS] = false;
            if (disableSGDI) { techAE[TI.SGDI] = false; }
        }
        static void RectifyDependencies_DisableDohcEng(bool[] techAE, bool disableSGDI)
        {
            techAE[TI.ICP  ] = false;
            techAE[TI.DCP  ] = false;
            techAE[TI.DVVLD] = false;
            techAE[TI.CVVL ] = false;
            techAE[TI.DEACD] = false;
            if (disableSGDI) { techAE[TI.SGDI] = false; }
        }
        static void RectifyDependencies_DisableOhvEng(bool[] techAE)
        {
            techAE[TI.DEACO] = false;
            techAE[TI.VVA  ] = false;
            techAE[TI.SGDIO] = false;
        }
        static void RectifyDependencies_DisableDeacEng(bool[] techAE)
        {
            techAE[TI.DEACS] = false;
            techAE[TI.DEACD] = false;
            techAE[TI.DEACO] = false;
        }
        static void RectifyDependencies_DisableAllTrn(bool[] techAE)
        {
            TechnologyApplicability.RectifyDependencies_DisableManualTrn(techAE);
            TechnologyApplicability.RectifyDependencies_DisableAutoTrn  (techAE);
        }
        static void RectifyDependencies_DisableManualTrn(bool[] techAE)
        {
            techAE[TI.MAN6    ] = false;
            techAE[TI.HETRANSM] = false;
        }
        static void RectifyDependencies_DisableAutoTrn(bool[] techAE)
        {
            techAE[TI.IATC   ] = false;
            techAE[TI.NAUTO  ] = false;
            techAE[TI.DCT    ] = false;
            techAE[TI.A8SPD  ] = false;
            techAE[TI.HETRANS] = false;
            techAE[TI.SHFTOPT] = false;
        }
        static void RectifyDependencies_DisableAllElec(bool[] techAE)
        {
            techAE[TI.EPS  ] = false;
            techAE[TI.IACC1] = false;
            techAE[TI.IACC2] = false;
            techAE[TI.MHEV ] = false;
            techAE[TI.ISG  ] = false;
        }
        static void RectifyDependencies_DisableAllDsl(bool[] techAE)
        {
            techAE[TI.DSL  ] = false;
            techAE[TI.DTURB] = false;
            techAE[TI.EFRD ] = false;
            techAE[TI.DDOWN] = false;
        }
        static void RectifyDependencies_DisableAllHev(bool[] techAE, bool disableEV, bool disableFCV)
        {
            techAE[TI.SHEV1  ] = false;
            techAE[TI.SHEV1_2] = false;
            techAE[TI.SHEV2  ] = false;
            techAE[TI.PHEV1  ] = false;
            techAE[TI.PHEV2  ] = false;
            if (disableEV)
            {
                techAE[TI.EV1] = false;
                techAE[TI.EV2] = false;
                techAE[TI.EV3] = false;
                techAE[TI.EV4] = false;
            }
            if (disableFCV)
            {
                techAE[TI.FCV] = false;
            }
        }
        static void RectifyDependencies_EnableAdvancedTurbo(bool[] techEnabled, bool[] techUsed, Vehicle veh, ModelYear year,
            int techIdx, ModelingSettings settings)
        {
            bool[] techAvailable = veh.ModelData.TechAvailable;
            bool advancedTurboSatisfied =
                (veh.TechnologyClass == TechnologyClass.Truck2b3  ||
                 veh.TechnologyClass == TechnologyClass.Van2b3  ) ||
                ((!techAvailable[TI.MAN6 ] || techUsed[TI.MAN6 ]) &&
                 (!techAvailable[TI.A8SPD] || techUsed[TI.A8SPD]));
            if (!advancedTurboSatisfied)
            {   
                techEnabled[TI.SEGR  ] = false;
                techEnabled[TI.DWNSP ] = false;
                techEnabled[TI.TRBDS2] = false;
                techEnabled[TI.CEGR1 ] = false;
                techEnabled[TI.CEGR2 ] = false;
                techEnabled[TI.MILLER] = false;
            }
            else if (techIdx != -1)
            {   
                TechnologyApplicability.Enable(veh, year, TI.SEGR  , settings);
                TechnologyApplicability.Enable(veh, year, TI.DWNSP , settings);
                TechnologyApplicability.Enable(veh, year, TI.TRBDS2, settings);
                TechnologyApplicability.Enable(veh, year, TI.CEGR1 , settings);
                TechnologyApplicability.Enable(veh, year, TI.CEGR2 , settings);
                TechnologyApplicability.Enable(veh, year, TI.MILLER, settings);
            }
        }
        static void RectifyDependencies_EnableAdvancedEngine(bool[] techEnabled, bool[] techUsed, Vehicle veh, ModelYear year,
            int techIdx, ModelingSettings settings)
        {
            bool[] techAvailable = veh.ModelData.TechAvailable;
            bool advancedEngineSatisfied =
                (!techAvailable[TI.MAN6    ] || techUsed[TI.MAN6    ]) &&
                (!techAvailable[TI.HETRANSM] || techUsed[TI.HETRANSM]) &&
                (!techAvailable[TI.IATC    ] || techUsed[TI.IATC    ]) &&
                (!techAvailable[TI.NAUTO   ] || techUsed[TI.NAUTO   ]) &&
                (!techAvailable[TI.DCT     ] || techUsed[TI.DCT     ]) &&
                (!techAvailable[TI.A8SPD   ] || techUsed[TI.A8SPD   ]) &&
                (!techAvailable[TI.HETRANS ] || techUsed[TI.HETRANS ]) &&
                (!techAvailable[TI.SHFTOPT ] || techUsed[TI.SHFTOPT ]);
            if (!advancedEngineSatisfied)
            {   
                techEnabled[TI.LGDI] = false;
                techEnabled[TI.CNG ] = false;
                techEnabled[TI.LNG ] = false;
                techEnabled[TI.LPG ] = false;
            }
            else if (techIdx != -1)
            {   
                TechnologyApplicability.Enable(veh, year, TI.LGDI, settings);
                TechnologyApplicability.Enable(veh, year, TI.CNG , settings);
                TechnologyApplicability.Enable(veh, year, TI.LNG , settings);
                TechnologyApplicability.Enable(veh, year, TI.LPG , settings);
            }
        }
        static void RectifyDependencies_EnableDiesel(bool[] techEnabled, bool[] techUsed, Vehicle veh, ModelYear year,
            int techIdx, ModelingSettings settings)
        {
            bool[] techAvailable = veh.ModelData.TechAvailable;
            bool dslSatisfied =
                !(techUsed[TI.LGDI] || techUsed[TI.CNG] || techUsed[TI.LNG] || techUsed[TI.LPG]) &&
                !(techUsed[TI.SHEV1] || techUsed[TI.SHEV1_2] || techUsed[TI.SHEV2] || techUsed[TI.PHEV1] || techUsed[TI.PHEV2] ||
                  techUsed[TI.EV1  ] || techUsed[TI.EV2    ] || techUsed[TI.EV3  ] || techUsed[TI.EV4  ] || techUsed[TI.FCV  ]) &&
                (!techAvailable[TI.LUB1     ] || techUsed[TI.LUB1     ]) &&     
                (!techAvailable[TI.EFR1     ] || techUsed[TI.EFR1     ]) &&     
                (!techAvailable[TI.LUB2_EFR2] || techUsed[TI.LUB2_EFR2]) &&     
                (!techAvailable[TI.TRBDS1   ] || techUsed[TI.TRBDS1   ]) &&
                (!techAvailable[TI.SEGR     ] || techUsed[TI.SEGR     ]) &&
                (!techAvailable[TI.DWNSP    ] || techUsed[TI.DWNSP    ]) &&
                (!techAvailable[TI.TRBDS2   ] || techUsed[TI.TRBDS2   ]) &&
                (!techAvailable[TI.CEGR1    ] || techUsed[TI.CEGR1    ]) &&
                (!techAvailable[TI.CEGR2    ] || techUsed[TI.CEGR2    ]) &&
                (!techAvailable[TI.MILLER   ] || techUsed[TI.MILLER   ]);
            if (!dslSatisfied)
            {   
                TechnologyApplicability.RectifyDependencies_DisableAllDsl(techEnabled);
            }
            else if (techIdx != -1)
            {   
                TechnologyApplicability.Enable(veh, year, TI.DSL   , settings);
                TechnologyApplicability.Enable(veh, year, TI.DTURB , settings);
                TechnologyApplicability.Enable(veh, year, TI.EFRD  , settings);
                TechnologyApplicability.Enable(veh, year, TI.DDOWN , settings);
            }
        }
        static void RectifyDependencies_EnableHev(bool[] techEnabled, bool[] techUsed, Vehicle vehicle, ModelYear year,
            int techIdx, ModelingSettings settings)
        {
            bool[] techAvailable = vehicle.ModelData.TechAvailable;
            bool hevSatisfied =
                !(techUsed[TI.LGDI] || techUsed[TI.CNG  ] || techUsed[TI.LNG ] || techUsed[TI.LPG  ]) &&
                (!techAvailable[TI.LUB1     ] || techUsed[TI.LUB1     ]) &&     
                (!techAvailable[TI.EFR1     ] || techUsed[TI.EFR1     ]) &&     
                (!techAvailable[TI.LUB2_EFR2] || techUsed[TI.LUB2_EFR2]) &&     
                (!techAvailable[TI.TRBDS1   ] || techUsed[TI.TRBDS1   ]) &&
                (!techAvailable[TI.SEGR     ] || techUsed[TI.SEGR     ]) &&
                (!techAvailable[TI.DWNSP    ] || techUsed[TI.DWNSP    ]) &&
                (!techAvailable[TI.TRBDS2   ] || techUsed[TI.TRBDS2   ]) &&
                (!techAvailable[TI.CEGR1    ] || techUsed[TI.CEGR1    ]) &&
                (!techAvailable[TI.CEGR2    ] || techUsed[TI.CEGR2    ]) &&
                (!techAvailable[TI.MILLER   ] || techUsed[TI.MILLER   ]) &&
                (!techAvailable[TI.DSL      ] || techUsed[TI.DSL      ]) &&
                (!techAvailable[TI.DTURB    ] || techUsed[TI.DTURB    ]) &&
                (!techAvailable[TI.EFRD     ] || techUsed[TI.EFRD     ]) &&
                (!techAvailable[TI.DDOWN    ] || techUsed[TI.DDOWN    ]) &&
                (!techAvailable[TI.IATC     ] || techUsed[TI.IATC     ]) &&
                (!techAvailable[TI.NAUTO    ] || techUsed[TI.NAUTO    ]) &&
                (!techAvailable[TI.DCT      ] || techUsed[TI.DCT      ]) &&
                (!techAvailable[TI.A8SPD    ] || techUsed[TI.A8SPD    ]) &&
                (!techAvailable[TI.HETRANS  ] || techUsed[TI.HETRANS  ]) &&
                (!techAvailable[TI.SHFTOPT  ] || techUsed[TI.SHFTOPT  ]); 
            if (!hevSatisfied)
            {   
                TechnologyApplicability.RectifyDependencies_DisableAllHev(techEnabled, true, true);
            }
            else if (techIdx != -1)
            {   
                TechnologyApplicability.Enable(vehicle, year, TI.SHEV1, settings);
                TechnologyApplicability.Enable(vehicle, year, TI.SHEV2, settings);
                TechnologyApplicability.Enable(vehicle, year, TI.PHEV1, settings);
                TechnologyApplicability.Enable(vehicle, year, TI.PHEV2, settings);
                TechnologyApplicability.Enable(vehicle, year, TI.EV1  , settings);
                TechnologyApplicability.Enable(vehicle, year, TI.EV2  , settings);
                TechnologyApplicability.Enable(vehicle, year, TI.EV3  , settings);
                TechnologyApplicability.Enable(vehicle, year, TI.EV4  , settings);
                TechnologyApplicability.Enable(vehicle, year, TI.FCV  , settings);
                if (techEnabled[TI.SHEV1]) { TechnologyApplicability.Enable(vehicle, year, TI.SHEV1_2, settings); }
            }
        }
        #endregion
        #region 
        public static void GetWeightChange(Technology tech, Vehicle veh, Scenario scen, ModelYear year,
            out double newCW, out double newGVWR, out double newGCWR)
        {
            var    attr    = tech.Attributes[veh];
            var    vd      = veh .Description;
            double deltaCW = ((attr.DeltaWeightPCT != 0) ? vd.BaseWeight * attr.DeltaWeightPCT :
                              (attr.DeltaWeightLBS != 0) ?                 attr.DeltaWeightLBS : 0);
            newCW   = vd.CurbWeight;
            newGVWR = vd.GVWR;
            newGCWR = vd.GCWR;
            if (deltaCW != 0)
            {
                if (TI.IsMaterialSubstitution(tech.Index))
                {
                    double p = 1 - scen.ScenInfo[veh.RegClass].PayloadReturn[year.Index];
                    double t = 1 - scen.ScenInfo[veh.RegClass].TowingReturn [year.Index];
                    newCW   = vd.CurbWeight - deltaCW;
                    newGVWR = Math.Max(8501,
                              Math.Min(vd.GVWR - p * (vd.CurbWeight - newCW  ), newCW   * vd.MaxGVWRToCW  ));
                    newGCWR = Math.Min(vd.GCWR - t * (vd.GVWR       - newGVWR), newGVWR * vd.MaxGCWRToGVWR);
                }
                else if (TI.IsConversionToSHEV(tech.Index) ||
                         TI.IsConversionToPHEV(tech.Index) ||
                         TI.IsConversionToEV  (tech.Index))
                {
                    newCW = vd.CurbWeight - deltaCW;
                }
            }
        }
        #endregion
        #region 
        #region 
        static double GetSynergy(Technology tech, Vehicle veh, bool scanAllTechs, bool getFCSynergy, List<Technology> techGroup,
            ulong techKey)
        {
            int      maxTech         =  (scanAllTechs) ? TI.TechnologyCount : tech.Index;
            bool  [] techUtilization =  (getFCSynergy) ? veh.ModelData.TechUsed : veh.ModelData.TechApplied;
            var      techSynergies   = ((getFCSynergy) ? tech.ImprvSynergies : tech.CostSynergies);
            double   synergy         = 0.0;
            for (int i = 0; i < maxTech; i++)
            {
                if (techUtilization[i]) { synergy += techSynergies[veh, i].Value; }
            }
            if (techGroup != null && techKey > 0)
            {
                for (int i = 0; i < techGroup.Count; i++)
                {   
                    if ((techKey & TechKeys[i]) != 0)
                    {   
                        if (techGroup[i].Index >= tech.Index) { break; }
                        synergy += techSynergies[veh, techGroup[i].Index].Value;
                    }
                } 
            }
            return synergy;
        }
        #endregion
        #region 
        public static double GetImprovement(Technology tech, Vehicle veh, Scenario scen, ModelYear year, out double synergy,
            out double fcPrimaryShare)
        {
            Vehicle.CModelData vmd = veh.ModelData;
            return GetImprovement(tech, veh, scen, year, null, 0, out synergy, out fcPrimaryShare);
        }
        public static double GetImprovement(Technology tech, Vehicle veh, Scenario scen, ModelYear year,
            List<Technology> techGroup, ulong techKey, out double synergy, out double fcPrimaryShare)
        {
            TechnologyAttributes ta = tech.Attributes[veh];
            double fc = GetEstimatedFC(tech, veh, scen, year);
            fcPrimaryShare = ta.FCPrimaryShare;
            synergy = GetSynergy(tech, veh, true, true, techGroup, techKey);
            return fc + synergy;
        }
        static double GetEstimatedFC(Technology tech, Vehicle veh, Scenario scen, ModelYear year)
        {
            TechnologyAttributes attr = tech.Attributes[veh];
            double fc = attr.FC;
            if (TI.IsMaterialSubstitution(tech.Index))
            {   
                double newCW, newGVWR, newGCWR;
                GetWeightChange(tech, veh, scen, year, out newCW, out newGVWR, out newGCWR);
                var    vd      = veh.Description;
                double deltaCW = (vd.CurbWeight - newCW) / vd.BaseWeight;
                if (deltaCW != 0)
                {
                    double baseTW  = Standards.GetTestWeight(veh, scen, year, vd.BaseWeight, vd.BaseGVWR, vd.BaseGCWR, 0);
                    double vehTW   = Standards.GetTestWeight(veh, scen, year, vd.CurbWeight, vd.GVWR    , vd.GCWR    , 0);
                    double newTW   = Standards.GetTestWeight(veh, scen, year, newCW        , newGVWR    , newGCWR    , 0);
                    double deltaTW = (vehTW - newTW) / baseTW;
                    fc = deltaTW * (fc / deltaCW);
                }
            }
            return fc;
        }
        #endregion
        #region 
        public static double GetCost(Technology tech, Vehicle veh, Industry data, ModelYear year, int startYear, int endYear)
        {
            double erpCost;
            bool[] committedERPCosts = null;
            return GetCost(tech, veh, data, null, year, 0, startYear, endYear, null, 0, false, out erpCost, ref committedERPCosts);
        }
        public static double GetCost(Technology tech, Vehicle veh, Industry data, ModelingSettings settings, ModelYear year,
            int yearOfInitialApplication, int startYear, int endYear, List<Technology> techGroup, ulong techKey)
        {
            double erpCost;
            bool[] committedERPCosts = null;
            return GetCost(tech, veh, data, settings, year, yearOfInitialApplication, startYear, endYear, techGroup, techKey,
                true, out erpCost, ref committedERPCosts);
        }
        public static double GetCost(Technology tech, Vehicle veh, Industry data, ModelingSettings settings, ModelYear year,
            int yearOfInitialApplication, int startYear, int endYear, List<Technology> techGroup, ulong techKey,
            out double strandedCapital, ref bool[] committedStrandedCapital)
        {
            return GetCost(tech, veh, data, settings, year, yearOfInitialApplication, startYear, endYear, techGroup, techKey,
                true, out strandedCapital, ref committedStrandedCapital);
        }
        static double GetCost(Technology tech, Vehicle veh, Industry data, ModelingSettings settings, ModelYear year,
            int yearOfInitialApplication, int startYear, int endYear, List<Technology> techGroup, ulong techKey, bool isCF,
            out double strandedCapital, ref bool[] committedStrandedCapital)
        {
            double techCost = GetEstimatedCost(tech, veh, year);
            double synergy  = GetSynergy(tech, veh, isCF, false, techGroup, techKey);
            strandedCapital = GetStrandedCapitalCost(tech, veh, settings, year, yearOfInitialApplication, isCF, ref committedStrandedCapital);
            return techCost + synergy + strandedCapital;
        }
        static double GetEstimatedCost(Technology tech, Vehicle veh, ModelYear year)
        {
            TechnologyAttributes attr = tech.Attributes[veh];
            int yrIndex = Math.Min(attr.CostTable.Length - 1, year.Index);
            double cost = attr.CostTable[yrIndex];
            if (TI.IsMaterialSubstitution(tech.Index))
            {   
                if      (attr.DeltaWeightPCT != 0) { cost *= (veh.Description.BaseWeight * Math.Max(0, attr.DeltaWeightPCT)); }
                else if (attr.DeltaWeightLBS != 0) { cost *= (Math.Max(0, attr.DeltaWeightLBS)); }
                else                               { cost  = 0; }
            }
            else if (TI.IsCylinderBased(tech.Index))
            {   
                int cylinders = (veh.Engine == null) ? veh.LegacyEng.Cylinders : veh.Engine.Description.Cylinders;
                cost *= cylinders;
            }
            else if (TI.IsConfigurationBased(tech.Index))
            {   
                string engConfig = (veh.Engine == null) ? veh.LegacyEng.Configuration.ToUpper() : veh.Engine.Description.Configuration.ToUpper();
                int costMult = (engConfig == "R" || engConfig == "I") ? 1 :
                    (engConfig == "F" || engConfig == "H" || engConfig == "V") ? 2 : (engConfig == "W") ? 4 : 0;
                cost *= costMult;
            }
            return cost;
        }
        static double GetStrandedCapitalCost(Technology tech, Vehicle veh, ModelingSettings settings, ModelYear year,
            int yearOfInitialApplication, bool isCF, ref bool[] committedStrandedCapital)
        {
            double strandedCapital = 0;
            if (isCF)
            {   
                for (int i = 0; i < TechSupersedes2[tech.Index].Length; i++)
                {
                    int sTech = TechSupersedes2[tech.Index][i]; 
                    Vehicle.CModelData vmd = veh.ModelData;
                    bool isCommittedStrandedCapital = (committedStrandedCapital != null && committedStrandedCapital[sTech]);
                    if (!isCommittedStrandedCapital && vmd.TechApplied[sTech] && vmd.TechSupersededYear[sTech] == 0)
                    {   
                        TechnologyAttributes attr = settings.Technologies[sTech].Attributes[veh];
                        int techAge = yearOfInitialApplication - vmd.TechAppliedYear[sTech] - 1;
                        strandedCapital += (techAge < 0 || techAge >= attr.StrandedCapital.Length) ? 0 : attr.StrandedCapital[techAge];
                        if (committedStrandedCapital != null) { committedStrandedCapital[sTech] = true; }
                    }
                } 
            }
            else
            {   
                Vehicle.CModelData vmd = veh.ModelData;
                int supersededYear = vmd.TechSupersededYear[tech.Index];
                if (vmd.TechApplied[tech.Index] && supersededYear > 0)
                {   
                    if (year.Year - supersededYear < 5)
                    {
                        TechnologyAttributes attr = tech.Attributes[veh];
                        int techAge = supersededYear - vmd.TechAppliedYear[tech.Index] - 1;
                        strandedCapital = (techAge < 0 || techAge >= attr.StrandedCapital.Length) ? 0 : attr.StrandedCapital[techAge];
                    }
                }
            }
            return strandedCapital;
        }
        #endregion
        #region 
        public static double GetMaintenanceCost(Technology tech, Vehicle veh, ModelYear year)
        {
            return GetEstimatedMaintenanceCost(tech, veh, year);
        }
        static double GetEstimatedMaintenanceCost(Technology tech, Vehicle veh, ModelYear year)
        {
            TechnologyAttributes attr = tech.Attributes[veh];
            int yrIndex = Math.Min(attr.MaintenanceCostTable.Length - 1, year.Index);
            double cost = attr.MaintenanceCostTable[yrIndex];
            return cost;
        }
        public static double GetRepairCost(Technology tech, Vehicle veh, ModelYear year)
        {
            return GetEstimatedRepairCost(tech, veh, year);
        }
        static double GetEstimatedRepairCost(Technology tech, Vehicle veh, ModelYear year)
        {
            TechnologyAttributes attr = tech.Attributes[veh];
            int yrIndex = Math.Min(attr.RepairCostTable.Length - 1, year.Index);
            double cost = attr.RepairCostTable[yrIndex];
            if (TI.IsMaterialSubstitution(tech.Index))
            {   
                if      (attr.DeltaWeightPCT != 0) { cost *= (veh.Description.BaseWeight * Math.Max(0, attr.DeltaWeightPCT)); }
                else if (attr.DeltaWeightLBS != 0) { cost *= (Math.Max(0, attr.DeltaWeightLBS)); }
                else                               { cost  = 0; }
            }
            return cost;
        }
        #endregion
        #endregion
        #region 
        public static List<Technology> GetTechnologyGroup(List<Technology> techs, TechnologyType type)
        {
            List<Technology> newTechs = new List<Technology>(GetTechnologyGroupCount(techs, type));
            for (int i = 0, techCount = techs.Count; i < techCount; i++)
            {
                if (techs[i].Type == type) { newTechs.Add(techs[i]); }
            }
            return newTechs;
        }
        public static int GetTechnologyGroupCount(List<Technology> techs, TechnologyType type)
        {
            int count = 0;
            for (int i = 0, techCount = techs.Count; i < techCount; i++)
            {
                if (techs[i].Type == type) { count++; }
            }
            return count;
        }
        public static bool HasTechnologyGroup(List<Technology> techs, TechnologyType type)
        {
            for (int i = 0, techCount = techs.Count; i < techCount; i++)
            {
                if      (techs[i]      == null) { break; }
                else if (techs[i].Type == type) { return true; }
            }
            return false;
        }
        #endregion
        public static bool CanBackfill(int techIndex, List<Technology> techs, bool[] techUsed)
        {
            for (int i = 0, count = techs.Count; i < count; i++)
            {   
                if (!CanBackfillHelper(techIndex, techs[i].Index)) { return false; }
            }
            for (int i = 0; i < TI.TechnologyCount; i++)
            {   
                if (techUsed[i] && !CanBackfillHelper(techIndex, i)) { return false; }
            }
            return true;
        }
        public static bool CanBackfill(int techIndex, List<Technology> techGroup, ulong techKey, bool[] techUsed)
        {
            int trueTechIndex = techGroup[techIndex].Index;
            for (int i = 0, techCount = techGroup.Count; i < techCount; i++)
            {   
                if ((techKey & TechKeys[i]) != 0)
                {   
                    if (!CanBackfillHelper(trueTechIndex, techGroup[i].Index)) { return false; }
                }
            }
            for (int i = 0; i < TI.TechnologyCount; i++)
            {   
                if (techUsed[i] && !CanBackfillHelper(trueTechIndex, i)) { return false; }
            }
            return true;
        }
        static bool CanBackfillHelper(int techIndex, int selTechIndex)
        {
            if (techIndex == selTechIndex) { return false; }
            int[] techDisallowBackfill = TechDisallowBackfill[selTechIndex];
            for (int j = 0, disallowCount = techDisallowBackfill.Length; j < disallowCount; j++)
            {
                if (techIndex == techDisallowBackfill[j])
                {   
                    return false;
                }
            }
            return true;
        }
        public static bool IsTechValid(Industry[] modelYearData, ModelYear year, Vehicle veh, int techIdx,
            bool ignorePhaseIn, bool backfilling, out bool lingering, out ModelYear lingerYear)
        {
            lingering  = false;
            lingerYear = null;
            Manufacturer            mfr = veh.Manufacturer;
            Manufacturer.CModelData mmd = mfr.ModelData;
            Vehicle     .CModelData vmd = veh.ModelData;
            if ( vmd.TechUsed     [techIdx]                  ||
                (vmd.TechIgnored  [techIdx] && !backfilling) ||
                (mmd.TechExhausted[techIdx] && !backfilling && !ignorePhaseIn)) { return false; }
            Component platform = null;
            if      (TI.IsEngineLevel      (techIdx)) { platform = veh.Engine      ; }
            else if (TI.IsTransmissionLevel(techIdx)) { platform = veh.Transmission; }
            else if (TI.IsPlatformLevel    (techIdx)) { platform = veh.Platform    ; }
            Vehicle pLeader = (platform == null) ? null : platform.GetPlatformLeader();
            bool      pEnabled    = true;
            bool      pLingering  = false;
            ModelYear pLingerYear = null;
            if (pLeader != null)
            {   
                if      (platform.ModelData.TechUsed[techIdx]) { pEnabled = false; }
                else if (veh == pLeader) { pLeader = null; }
                else
                {
                    pEnabled = IsTechValid(modelYearData, year, pLeader, techIdx, ignorePhaseIn, backfilling,
                        out pLingering, out pLingerYear);
                }
            }
            if (!pEnabled) { return false; }
            ModelYear vehTechLingerYear = null;
            bool[]    vehTechLingering  = null;
            if (pLingering)
            {
                for (int i = 0; i < vmd.TechLingerYear.Count; i++)
                {
                    if (vmd.TechLingerYear[i].Year >= pLingerYear.Year)
                    {
                        vehTechLingerYear = vmd.TechLingerYear[i];
                    }
                }
            }
            else
            {
                int lastLinger = vmd.TechLingerYear.Count - 1;
                if (lastLinger != -1)
                {
                    vehTechLingerYear = vmd.TechLingerYear[lastLinger];
                }
            }
            if (vehTechLingerYear != null)
            {
                Manufacturer lMfr = modelYearData[vehTechLingerYear.Index].Manufacturers[mfr.Index];
                Vehicle      lVeh = lMfr.Vehicles.Find((query) => { return (query.Description.Code == veh.Description.Code); });
                vehTechLingering  = lVeh.ModelData.TechEnabled;
            }
            if (vmd.TechEnabled[techIdx] && !pLingering)
            {   
                return true;
            }
            if (vmd.TechEnabled[techIdx] && (vehTechLingerYear == null || vehTechLingerYear.Year < pLingerYear.Year))
            {   
                return true;
            }
            if (vehTechLingering != null && vehTechLingering[techIdx] && (pLeader == null || pLingering))
            {   
                int                     lYr  = (pLingering) ? pLingerYear.Index : vehTechLingerYear.Index;
                Manufacturer.CModelData lMMD = modelYearData[lYr].Manufacturers[mfr.Index].ModelData;
                if (backfilling || ignorePhaseIn || !lMMD.TechExhausted[techIdx])
                {   
                    if (pLeader == null || vehTechLingerYear.Year >= pLingerYear.Year)
                    {
                        lingering  = true;
                        lingerYear = vehTechLingerYear;
                        return true;
                    }
                }
            }
            return false;
        }
        public static void InstallTechnologyOnVehicle(Vehicle veh, Technology tech, ModelYear year, int yearOfInitialApplication,
            bool isInherited, ModelingSettings settings)
        {
            Vehicle     .CDescription vd  =                                     veh             .Description;
            Engine      .CDescription ed  = (veh.Engine       == null) ? null : veh.Engine      .Description;
            Transmission.CDescription td  = (veh.Transmission == null) ? null : veh.Transmission.Description;
            Vehicle     .CModelData   vmd =                                     veh             .ModelData;
            Engine      .CModelData   emd = (veh.Engine       == null) ? null : veh.Engine      .ModelData;
            Transmission.CModelData   tmd = (veh.Transmission == null) ? null : veh.Transmission.ModelData;
            Platform    .CModelData   pmd = (veh.Platform     == null) ? null : veh.Platform    .ModelData;
            TechnologyAttributes attr = tech.Attributes[veh];
            vmd.TechUsed       [tech.Index] = true;
            vmd.TechInherited  [tech.Index] = isInherited;
            vmd.TechApplied    [tech.Index] = true;
            vmd.TechAppliedYear[tech.Index] = yearOfInitialApplication;
            if (TI.IsEngineLevel(tech.Index) && veh.Engine != null && !emd.TechUsed[tech.Index])
            {
                emd.TechUsed       [tech.Index] = true;
                emd.TechApplied    [tech.Index] = true;
                emd.TechAppliedYear[tech.Index] = yearOfInitialApplication;
            }
            if (TI.IsTransmissionLevel(tech.Index) && veh.Transmission != null && !tmd.TechUsed[tech.Index])
            {
                tmd.TechUsed       [tech.Index] = true;
                tmd.TechApplied    [tech.Index] = true;
                tmd.TechAppliedYear[tech.Index] = yearOfInitialApplication;
            }
            if (TI.IsPlatformLevel(tech.Index) && veh.Platform != null && !pmd.TechUsed[tech.Index])
            {
                pmd.TechUsed       [tech.Index] = true;
                pmd.TechApplied    [tech.Index] = true;
                pmd.TechAppliedYear[tech.Index] = yearOfInitialApplication;
            }
            switch (tech.Index)
            {
                case TI.LUB1:
                    ed.EngineOilViscosity = "LUB1";
                    break;
                case TI.LUB2_EFR2:
                    ed.EngineOilViscosity = "LUB2";
                    break;
                case TI.DVVLS:
                case TI.CVVL:
                    ed.ValveLift = "CV";
                    break;
                case TI.DVVLD:
                    ed.ValveLift = "SVI";
                    break;
                case TI.TRBDS1:
                case TI.SEGR:
                case TI.DWNSP:
                case TI.TRBDS2:
                case TI.CEGR1:
                case TI.CEGR2:
                    ed.Aspiration = "T";
                    break;
                case TI.LGDI:
                    break;
                case TI.CNG:
                    ed.Fuel = FuelType.CNG;
                    break;
                case TI.LNG:
                    ed.Fuel = FuelType.LNG;
                    break;
                case TI.LPG:
                    ed.Fuel = FuelType.LPG;
                    break;
                case TI.DSL:
                case TI.DTURB:
                case TI.EFRD:
                case TI.DDOWN:
                    ed.Fuel = FuelType.Diesel;
                    ed.FuelSystem = "DI";
                    ed.Cycle = 'D';
                    if (tech.Index != TI.DSL) { ed.Aspiration = "T"; }
                    break;
                case TI.MAN6:
                    td.Type = "M";
                    td.NumForwardGears = 6;
                    break;
                case TI.IATC:
                    td.Type = "A";
                    break;
                case TI.NAUTO:
                    td.Type = "A";
                    td.NumForwardGears = 6;
                    break;
                case TI.DCT:
                    td.Type = "DCT";
                    td.NumForwardGears = 6;
                    break;
                case TI.A8SPD:
                    td.NumForwardGears = 8;
                    break;
                case TI.SHEV1:
                case TI.SHEV1_2:
                case TI.SHEV2:
                    vd.HybridType = "SHEV";
                    break;
                case TI.PHEV1:
                case TI.PHEV2:
                    vd.HybridType = "PHEV";
                    veh.Description.ElectricRange = attr.ElectricRange;
                    veh.RemoveTransmission();
                    break;
                case TI.EV1:
                case TI.EV2:
                case TI.EV3:
                case TI.EV4:
                    vd.HybridType = "EV";
                    veh.Description.ElectricRange = attr.ElectricRange;
                    if (ed != null) { veh.Description.ElectricPower = ed.Horsepower; }
                    veh.RemoveTransmission();
                    veh.RemoveEngine();
                    break;
                case TI.FCV:
                    vd.HybridType = "FCV";
                    veh.Description.ElectricRange = attr.ElectricRange;
                    if (ed != null) { veh.Description.ElectricPower = ed.Horsepower; }
                    veh.RemoveTransmission();
                    veh.RemoveEngine();
                    break;
            }
            TechnologyApplicability.Enable(veh, year, tech.Index, settings);
        }
        public static void CheckPhaseIn(ModelingSettings settings, Manufacturer.CModelData mmd, Technology tech, ModelYear year,
            int sYrIndex)
        {
            if (mmd.TechExhausted[tech.Index]) { return; }
            int[] phaseInPairs = TI.GetSharedPhaseInTechs(tech.Index);
            if (phaseInPairs == null)
            {   
                double techSales = mmd.TechUsedSales[tech.Index].Total;
                double mfrSales = mmd.Sales.Total;
                if (mfrSales > 0 && techSales >= mfrSales * tech.GetPhaseIn(year.Index, sYrIndex, mmd.TechPhaseInOffset[tech.Index]))
                {   
                    if (tech.Index != -1) { mmd.TechExhausted[tech.Index] = true; }
                }
            }
            else
            {   
                double techSales = 0D;
                for (int i = 0; i < phaseInPairs.Length; i++)
                {
                    if (phaseInPairs[i] != -1) { techSales += mmd.TechUsedSales[phaseInPairs[i]].Total; }
                }
                double mfrSales = mmd.Sales.Total;
                if (mfrSales > 0 && techSales >= mfrSales * tech.GetPhaseIn(year.Index, sYrIndex, mmd.TechPhaseInOffset[tech.Index]))
                {   
                    for (int i = 0; i < phaseInPairs.Length; i++)
                    {
                        if (phaseInPairs[i] != -1) { mmd.TechExhausted[phaseInPairs[i]] = true; }
                    }
                }
            }
        }
        public static void ComputeMfrAdjustedPhaseIn(Manufacturer mfr, ModelYear year, ModelingSettings settings)
        {
            Manufacturer.CModelData mmd = mfr.ModelData;
            double mfrSales = Standards.GetSales(mfr, year).Total;
            for (int i = 0; i < TI.TechnologyCount; i++)
            {   
                double techPenRate = (mmd.TechUsedSales[i].Total - mmd.TechAppliedSales[i].Total) / mfrSales;
                double[] techPhaseIn = settings.Technologies[i].PhaseIn;
                for (int k = 0; k < techPhaseIn.Length; k++)
                {
                    if (techPenRate <= techPhaseIn[k])
                    {
                        mmd.TechPhaseInOffset[i] = k;
                        break;
                    }
                }
            } 
        }
        #endregion
        #region 
        static readonly int[][] TechSupersedes;
        static readonly int[][] TechSoftSupersedes;
        static readonly int[][] TechSupersedes2;
        static readonly int[][] TechDisallowBackfill;
        public static readonly ulong[] TechKeys;
        public static TechnologyType[] TechTypes;
        public static int TechTypeCount;
        public static RegulatoryClass[] RegClasses;
        #endregion
    }
}

