/// <summary>
 /// Describes something's allowance.
 /// </summary>
 /// <param name="allowance">The allowance.</param>
 /// <param name="minGameVersion">The minimum game version.</param>
 /// <param name="maxGameVersion">The maximum game version.</param>
 /// <returns>The allowance description.</returns>
 private string AllowanceText(ServiceDispatcherSettings.Allowance allowance, uint minGameVersion = 0, uint maxGameVersion = uint.MaxValue)
 {
     if (allowance == ServiceDispatcherSettings.Allowance.Never)
     {
         return "No (disabled)";
     }
     else if (BuildConfig.APPLICATION_VERSION < minGameVersion)
     {
         return "No (game version too low)";
     }
     else if (allowance == ServiceDispatcherSettings.Allowance.Always)
     {
         return "Yes (overridden)";
     }
     else if (BuildConfig.APPLICATION_VERSION >= maxGameVersion)
     {
         return "No (game version too high)";
     }
     else if (minGameVersion > 0 || maxGameVersion < uint.MaxValue)
     {
         return "Yes (game version within limits)";
     }
     else
     {
         return "Yes (enabled)";
     }
 }
        /// <summary>
        /// Saves settings to the specified file name.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public void Save(string fileName = null)
        {
            Log.Debug(this, "Save", "Begin");

            if (Log.LogALot || Library.IsDebugBuild)
            {
                this.LogSettings();
            }

            try
            {
                if (fileName == null)
                {
                    fileName = FilePathName;
                }

                string filePath = Path.GetDirectoryName(Path.GetFullPath(fileName));
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }

                Log.Info(this, "Save", fileName);

                this.SaveCount++;
                using (FileStream file = File.Create(fileName))
                {
                    ServiceDispatcherSettings cfg = new ServiceDispatcherSettings();

                    cfg.DispatchByDistrict = this.DeathCare.DispatchByDistrict && this.Garbage.DispatchByDistrict && this.HealthCare.DispatchByDistrict;
                    cfg.DispatchByRange = this.DeathCare.DispatchByRange || this.Garbage.DispatchByRange || this.HealthCare.DispatchByRange;
                    cfg.RangeModifier = this.RangeModifier;
                    cfg.RangeLimit = this.RangeLimit;
                    cfg.RangeMaximum = this.RangeMaximum;
                    cfg.RangeMinimum = this.RangeMinimum;
                    cfg.ReflectionAllowance = this.ReflectionAllowance;
                    cfg.AssignmentCompatibilityMode = this.AssignmentCompatibilityMode;
                    cfg.CreationCompatibilityMode = this.CreationCompatibilityMode;

                    cfg.DispatchHearses = this.DeathCare.DispatchVehicles;
                    cfg.DispatchHearsesByDistrict = this.DeathCare.DispatchByDistrict;
                    cfg.DispatchHearsesByRange = this.DeathCare.DispatchByRange;
                    cfg.RemoveHearsesFromGrid = this.DeathCare.RemoveFromGrid;
                    cfg.CreateSpareHearses = this.DeathCare.CreateSpares;
                    cfg.DeathChecksPreset = this.DeathCare.ChecksPreset;
                    cfg.DeathChecksCustom = this.DeathCare.ChecksCustom;
                    cfg.DeathChecksCurrent = this.DeathCare.ChecksParameters;
                    cfg.AutoEmptyCemeteries = this.DeathCare.AutoEmpty;
                    cfg.AutoEmptyCemeteryStartLevelPercent = this.DeathCare.AutoEmptyStartLevelPercent;
                    cfg.AutoEmptyCemeteryStopLevelPercent = this.DeathCare.AutoEmptyStopLevelPercent;

                    cfg.DispatchAmbulances = this.HealthCare.DispatchVehicles;
                    cfg.DispatchAmbulancesByDistrict = this.HealthCare.DispatchByDistrict;
                    cfg.DispatchAmbulancesByRange = this.HealthCare.DispatchByRange;
                    cfg.RemoveAmbulancesFromGrid = this.HealthCare.RemoveFromGrid;
                    cfg.CreateSpareAmbulances = this.HealthCare.CreateSpares;
                    cfg.SickChecksPreset = this.HealthCare.ChecksPreset;
                    cfg.SickChecksCustom = this.HealthCare.ChecksCustom;
                    cfg.SickChecksCurrent = this.HealthCare.ChecksParameters;

                    cfg.DispatchGarbageTrucks = this.Garbage.DispatchVehicles;
                    cfg.DispatchGarbageTrucksByDistrict = this.Garbage.DispatchByDistrict;
                    cfg.DispatchGarbageTrucksByRange = this.Garbage.DispatchByRange;
                    cfg.LimitOpportunisticGarbageCollection = this.Garbage.LimitOpportunisticCollection;
                    cfg.CreateSpareGarbageTrucks = this.Garbage.CreateSpares;
                    cfg.MinimumGarbageForDispatch = this.Garbage.MinimumAmountForDispatch;
                    cfg.MinimumGarbageForPatrol = this.Garbage.MinimumAmountForPatrol;
                    cfg.GarbageChecksPreset = this.Garbage.ChecksPreset;
                    cfg.GarbageChecksCustom = this.Garbage.ChecksCustom;
                    cfg.GarbageChecksCurrent = this.Garbage.ChecksParameters;
                    cfg.AutoEmptyLandfills = this.Garbage.AutoEmpty;
                    cfg.AutoEmptyLandfillStartLevelPercent = this.Garbage.AutoEmptyStartLevelPercent;
                    cfg.AutoEmptyLandfillStopLevelPercent = this.Garbage.AutoEmptyStopLevelPercent;

                    cfg.AutoBulldozeBuildings = this.WreckingCrews.DispatchVehicles;
                    cfg.AutoBulldozeBuildingsDelaySeconds = this.WreckingCrews.DelaySeconds;

                    cfg.RemoveStuckVehicles = this.RecoveryCrews.DispatchVehicles;
                    cfg.RemoveStuckVehiclesDelaySeconds = this.RecoveryCrews.DelaySeconds;

                    cfg.BuildingChecksPresets = (Enum.GetValues(typeof(ServiceDispatcherSettings.BuildingCheckOrder)) as ServiceDispatcherSettings.BuildingCheckOrder[]).Where(bco => bco != ServiceDispatcherSettings.BuildingCheckOrder.Custom).Select(bco => new ServiceDispatcherSettings.BuildingChecksPresetInfo(bco)).ToArray();
                    cfg.BuildingChecksPossible = (Enum.GetValues(typeof(ServiceDispatcherSettings.BuildingCheckParameters)) as ServiceDispatcherSettings.BuildingCheckParameters[]).Where(bcp => bcp != ServiceDispatcherSettings.BuildingCheckParameters.Custom).ToArray();

                    cfg.Version = this.Version;
                    cfg.SaveCount = this.SaveCount;

                    XmlSerializer ser = new XmlSerializer(typeof(ServiceDispatcherSettings));
                    ser.Serialize(file, cfg);
                    file.Flush();
                    file.Close();
                }
            }
            catch (Exception ex)
            {
                Log.Error(this, "Save", ex);
            }

            Log.Debug(this, "Save", "End");
        }
 /// <summary>
 /// Check whether something is allowed.
 /// </summary>
 /// <param name="allowance">The allowance.</param>
 /// <param name="minGameVersion">The minimum game version.</param>
 /// <param name="maxGameVersion">The maximum game version.</param>
 /// <returns>True if allowed.</returns>
 private bool AllowanceCheck(ServiceDispatcherSettings.Allowance allowance, uint minGameVersion = 0, uint maxGameVersion = uint.MaxValue)
 {
     return allowance != ServiceDispatcherSettings.Allowance.Never &&
            BuildConfig.APPLICATION_VERSION >= minGameVersion &&
            (allowance == ServiceDispatcherSettings.Allowance.Always || BuildConfig.APPLICATION_VERSION < maxGameVersion);
 }
 /// <summary>
 /// Gets the display name of the vehicle creation option.
 /// </summary>
 /// <param name="option">The option.</param>
 /// <returns>
 /// The display name.
 /// </returns>
 public static string GetSpareVehiclesCreationDescription(ServiceDispatcherSettings.SpareVehiclesCreation option)
 {
     string description;
     return spareVehiclesCreationDescriptions.TryGetValue(option, out description) ? description : null;
 }
 /// <summary>
 /// Gets the display name of the vehicle creation option.
 /// </summary>
 /// <param name="option">The option.</param>
 /// <returns>
 /// The display name.
 /// </returns>
 public static string GetSpareVehiclesCreationName(ServiceDispatcherSettings.SpareVehiclesCreation option)
 {
     string name;
     return spareVehiclesCreationNames.TryGetValue(option, out name) ? name : option.ToString();
 }
        /// <summary>
        /// Gets the building checks parameters for the specified check order.
        /// </summary>
        /// <param name="buildingChecks">The building check order.</param>
        /// <param name="customBuildingCheckParameters">The custom building check parameters.</param>
        /// <returns>
        /// The building checks parameters.
        /// </returns>
        public static ServiceDispatcherSettings.BuildingCheckParameters[] GetBuildingChecksParameters(ServiceDispatcherSettings.BuildingCheckOrder buildingChecks, ServiceDispatcherSettings.BuildingCheckParameters[] customBuildingCheckParameters = null)
        {
            switch (buildingChecks)
            {
                case ServiceDispatcherSettings.BuildingCheckOrder.FirstFirst:
                    return new ServiceDispatcherSettings.BuildingCheckParameters[] { ServiceDispatcherSettings.BuildingCheckParameters.Any };

                case ServiceDispatcherSettings.BuildingCheckOrder.InRangeFirst:
                    return new ServiceDispatcherSettings.BuildingCheckParameters[] { ServiceDispatcherSettings.BuildingCheckParameters.InRange, ServiceDispatcherSettings.BuildingCheckParameters.ProblematicIgnoreRange };

                case ServiceDispatcherSettings.BuildingCheckOrder.ProblematicFirst:
                    return new ServiceDispatcherSettings.BuildingCheckParameters[] { ServiceDispatcherSettings.BuildingCheckParameters.ProblematicInRange, ServiceDispatcherSettings.BuildingCheckParameters.ProblematicIgnoreRange, ServiceDispatcherSettings.BuildingCheckParameters.InRange };

                case ServiceDispatcherSettings.BuildingCheckOrder.VeryProblematicFirst:
                    return new ServiceDispatcherSettings.BuildingCheckParameters[] { ServiceDispatcherSettings.BuildingCheckParameters.VeryProblematicInRange, ServiceDispatcherSettings.BuildingCheckParameters.VeryProblematicIgnoreRange, ServiceDispatcherSettings.BuildingCheckParameters.InRange, ServiceDispatcherSettings.BuildingCheckParameters.ProblematicIgnoreRange };

                case ServiceDispatcherSettings.BuildingCheckOrder.ForgottenFirst:
                    return new ServiceDispatcherSettings.BuildingCheckParameters[] { ServiceDispatcherSettings.BuildingCheckParameters.ForgottenInRange, ServiceDispatcherSettings.BuildingCheckParameters.ForgottenIgnoreRange, ServiceDispatcherSettings.BuildingCheckParameters.InRange, ServiceDispatcherSettings.BuildingCheckParameters.ProblematicIgnoreRange };

                case ServiceDispatcherSettings.BuildingCheckOrder.InRange:
                    return new ServiceDispatcherSettings.BuildingCheckParameters[] { ServiceDispatcherSettings.BuildingCheckParameters.InRange, ServiceDispatcherSettings.BuildingCheckParameters.ForgottenIgnoreRange };

                case ServiceDispatcherSettings.BuildingCheckOrder.Custom:
                    return (customBuildingCheckParameters != null) ? customBuildingCheckParameters : GetBuildingChecksParameters(ServiceDispatcherSettings.BuildingCheckOrder.InRange);

                default:
                    return GetBuildingChecksParameters(ServiceDispatcherSettings.BuildingCheckOrder.FirstFirst);
            }
        }
 /// <summary>
 /// Gets the name of the mod compatibility mode.
 /// </summary>
 /// <param name="modCompatibilityMode">The mod compatibility mode.</param>
 /// <returns>The name of the mod compatibility mode.</returns>
 public static string GetModCompatibilityModeName(ServiceDispatcherSettings.ModCompatibilityMode modCompatibilityMode)
 {
     string name;
     return modCompatibilityModeNames.TryGetValue(modCompatibilityMode, out name) ? name : modCompatibilityMode.ToString();
 }
 /// <summary>
 /// Gets the display name of the building check order.
 /// </summary>
 /// <param name="checkOrder">The check order.</param>
 /// <returns>The display name.</returns>
 public static string GetBuildingCheckOrderDescription(ServiceDispatcherSettings.BuildingCheckOrder checkOrder)
 {
     string description;
     return buildingCheckOrderDescriptions.TryGetValue(checkOrder, out description) ? description : null;
 }
 /// <summary>
 /// Gets the display name of the building check order.
 /// </summary>
 /// <param name="checkOrder">The check order.</param>
 /// <returns>The display name.</returns>
 public static string GetBuildingCheckOrderName(ServiceDispatcherSettings.BuildingCheckOrder checkOrder)
 {
     string name;
     return buildingCheckOrderNames.TryGetValue(checkOrder, out name) ? name : checkOrder.ToString();
 }
 /// <summary>
 /// Gets the name of the allowance.
 /// </summary>
 /// <param name="allowance">The allowance.</param>
 /// <returns>The name of the allowance.</returns>
 public static string GetAllowanceName(ServiceDispatcherSettings.Allowance allowance)
 {
     return allowance.ToString();
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="Settings"/> class.
        /// </summary>
        /// <param name="settings">The file settings.</param>
        public Settings(ServiceDispatcherSettings settings = null)
        {
            if (settings != null)
            {
                this.loadedVersion = settings.Version;

                this.RangeModifier = settings.RangeModifier;
                this.RangeLimit = settings.RangeLimit;
                this.RangeMaximum = settings.RangeMaximum;
                this.RangeMinimum = settings.RangeMinimum;
                this.ReflectionAllowance = settings.ReflectionAllowance;
                this.AssignmentCompatibilityMode = settings.AssignmentCompatibilityMode;
                this.CreationCompatibilityMode = settings.CreationCompatibilityMode;

                this.DeathCare.DispatchVehicles = settings.DispatchHearses;
                this.DeathCare.DispatchByDistrict = settings.DispatchHearsesByDistrict;
                this.DeathCare.DispatchByRange = settings.DispatchHearsesByRange;
                this.DeathCare.CreateSpares = settings.CreateSpareHearses;
                this.DeathCare.RemoveFromGrid = settings.RemoveHearsesFromGrid;
                this.DeathCare.ChecksCustom = settings.DeathChecksCustom;
                this.DeathCare.ChecksPreset = settings.DeathChecksPreset;
                this.DeathCare.AutoEmpty = settings.AutoEmptyCemeteries;
                this.DeathCare.AutoEmptyStartLevelPercent = settings.AutoEmptyCemeteryStartLevelPercent;
                this.DeathCare.AutoEmptyStopLevelPercent = settings.AutoEmptyCemeteryStopLevelPercent;

                this.HealthCare.DispatchVehicles = settings.DispatchAmbulances;
                this.HealthCare.DispatchByDistrict = settings.DispatchAmbulancesByDistrict;
                this.HealthCare.DispatchByRange = settings.DispatchAmbulancesByRange;
                this.HealthCare.CreateSpares = settings.CreateSpareAmbulances;
                this.HealthCare.RemoveFromGrid = settings.RemoveAmbulancesFromGrid;
                this.HealthCare.ChecksCustom = settings.SickChecksCustom;
                this.HealthCare.ChecksPreset = settings.SickChecksPreset;

                this.Garbage.DispatchVehicles = settings.DispatchGarbageTrucks;
                this.Garbage.DispatchByDistrict = settings.DispatchGarbageTrucksByDistrict;
                this.Garbage.DispatchByRange = settings.DispatchGarbageTrucksByRange;
                this.Garbage.LimitOpportunisticCollection = settings.LimitOpportunisticGarbageCollection;
                this.Garbage.CreateSpares = settings.CreateSpareGarbageTrucks;
                this.Garbage.MinimumAmountForDispatch = settings.MinimumGarbageForDispatch;
                this.Garbage.MinimumAmountForPatrol = settings.MinimumGarbageForPatrol;
                this.Garbage.ChecksCustom = settings.GarbageChecksCustom;
                this.Garbage.ChecksPreset = settings.GarbageChecksPreset;
                this.Garbage.AutoEmpty = settings.AutoEmptyLandfills;
                this.Garbage.AutoEmptyStartLevelPercent = settings.AutoEmptyLandfillStartLevelPercent;
                this.Garbage.AutoEmptyStopLevelPercent = settings.AutoEmptyLandfillStopLevelPercent;

                this.WreckingCrews.DispatchVehicles = settings.AutoBulldozeBuildings;
                this.WreckingCrews.DelaySeconds = settings.AutoBulldozeBuildingsDelaySeconds;

                this.RecoveryCrews.DispatchVehicles = settings.RemoveStuckVehicles;
                this.RecoveryCrews.DelaySeconds = settings.RemoveStuckVehiclesDelaySeconds;
            }

            if (!Global.EnableExperiments)
            {
                this.DeathCare.AutoEmpty = false;
                this.Garbage.AutoEmpty = false;
            }

            this.AssignmentCompatibilityMode = ServiceDispatcherSettings.ModCompatibilityMode.UseCustomCode;
            this.CreationCompatibilityMode = ServiceDispatcherSettings.ModCompatibilityMode.UseCustomCode;
            this.HealthCare.DispatchVehicles = false;
        }
            /// <summary>
            /// Gets the dispatcher building check parameters with an extra entry for patrolling vehicles.
            /// </summary>
            /// <param name="buildingCheckParameters">The building check parameters.</param>
            /// <returns>
            /// The dispatcher building check parameters.
            /// </returns>
            public static BuldingCheckParameters[] GetBuldingCheckParametersWithPatrol(ServiceDispatcherSettings.BuildingCheckParameters[] buildingCheckParameters)
            {
                List<BuldingCheckParameters> parameters = buildingCheckParameters.Select(bcp => new BuldingCheckParameters(bcp)).ToList();
                parameters.Add(new BuldingCheckParameters(false, true, false, 0, false));

                return parameters.ToArray();
            }
 /// <summary>
 /// Gets the dispatcher building check parameters.
 /// </summary>
 /// <param name="buildingCheckParameters">The configured building check parameters.</param>
 /// <returns>
 /// The dispatcher building check parameters.
 /// </returns>
 public static BuldingCheckParameters[] GetBuldingCheckParameters(ServiceDispatcherSettings.BuildingCheckParameters[] buildingCheckParameters)
 {
     return buildingCheckParameters.Select(bcp => new BuldingCheckParameters(bcp)).ToArray();
 }
            /// <summary>
            /// Initializes a new instance of the <see cref="BuldingCheckParameters"/> class.
            /// </summary>
            /// <param name="buildingCheckParameters">The building check parameters.</param>
            public BuldingCheckParameters(ServiceDispatcherSettings.BuildingCheckParameters buildingCheckParameters)
            {
                this.Setting = buildingCheckParameters;

                this.IncludeUneedy = false;
                this.AllowCreateSpares = true;

                switch (buildingCheckParameters)
                {
                    case ServiceDispatcherSettings.BuildingCheckParameters.Any:
                        this.OnlyProblematic = false;
                        this.IgnoreRange = true;
                        this.MinProblemValue = 0;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.InRange:
                        this.OnlyProblematic = false;
                        this.IgnoreRange = false;
                        this.MinProblemValue = 0;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.ProblematicInRange:
                        this.OnlyProblematic = true;
                        this.IgnoreRange = false;
                        this.MinProblemValue = 0;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.ProblematicIgnoreRange:
                        this.OnlyProblematic = true;
                        this.IgnoreRange = true;
                        this.MinProblemValue = 0;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.VeryProblematicInRange:
                        this.OnlyProblematic = true;
                        this.IgnoreRange = false;
                        this.MinProblemValue = ProblemLimitMajor;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.VeryProblematicIgnoreRange:
                        this.OnlyProblematic = true;
                        this.IgnoreRange = true;
                        this.MinProblemValue = ProblemLimitMajor;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.ForgottenInRange:
                        this.OnlyProblematic = true;
                        this.IgnoreRange = false;
                        this.MinProblemValue = ProblemLimitForgotten;
                        break;

                    case ServiceDispatcherSettings.BuildingCheckParameters.ForgottenIgnoreRange:
                        this.OnlyProblematic = true;
                        this.IgnoreRange = true;
                        this.MinProblemValue = ProblemLimitForgotten;
                        break;

                    default:
                        this.OnlyProblematic = false;
                        this.IgnoreRange = true;
                        this.MinProblemValue = ProblemLimit;
                        break;
                }
            }