public static string TestRequirements(string experiment_id, string requirements, Vessel v) { CelestialBody body = v.mainBody; Vessel_info vi = Cache.VesselInfo(v); List <string> list = Lib.Tokenize(requirements, ','); foreach (string s in list) { var parts = Lib.Tokenize(s, ':'); var condition = parts[0]; string value = string.Empty; if (parts.Count > 1) { value = parts[1]; } bool good = true; switch (condition) { case "OrbitMinInclination": good = Math.Abs(v.orbit.inclination) >= double.Parse(value); break; case "OrbitMaxInclination": good = Math.Abs(v.orbit.inclination) <= double.Parse(value); break; case "OrbitMinEccentricity": good = v.orbit.eccentricity >= double.Parse(value); break; case "OrbitMaxEccentricity": good = v.orbit.eccentricity <= double.Parse(value); break; case "OrbitMinArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis >= double.Parse(value); break; case "OrbitMaxArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis <= double.Parse(value); break; case "TemperatureMin": good = vi.temperature >= double.Parse(value); break; case "TemperatureMax": good = vi.temperature <= double.Parse(value); break; case "AltitudeMin": good = v.altitude >= double.Parse(value); break; case "AltitudeMax": good = v.altitude <= double.Parse(value); break; case "RadiationMin": good = vi.radiation >= double.Parse(value); break; case "RadiationMax": good = vi.radiation <= double.Parse(value); break; case "Microgravity": good = vi.zerog; break; case "Body": good = TestBody(v.mainBody.name, value); break; case "Shadow": good = vi.sunlight < double.Epsilon; break; case "Sunlight": good = vi.sunlight > 0.5; break; case "CrewMin": good = vi.crew_count >= int.Parse(value); break; case "CrewMax": good = vi.crew_count <= int.Parse(value); break; case "CrewCapacityMin": good = vi.crew_capacity >= int.Parse(value); break; case "CrewCapacityMax": good = vi.crew_capacity <= int.Parse(value); break; case "VolumePerCrewMin": good = vi.volume_per_crew >= double.Parse(value); break; case "VolumePerCrewMax": good = vi.volume_per_crew <= double.Parse(value); break; case "Greenhouse": good = vi.greenhouses.Count > 0; break; case "Surface": good = Lib.Landed(v); break; case "Atmosphere": good = body.atmosphere && v.altitude < body.atmosphereDepth; break; case "AtmosphereBody": good = body.atmosphere; break; case "AtmosphereAltMin": good = body.atmosphere && (v.altitude / body.atmosphereDepth) >= double.Parse(value); break; case "AtmosphereAltMax": good = body.atmosphere && (v.altitude / body.atmosphereDepth) <= double.Parse(value); break; case "BodyWithAtmosphere": good = body.atmosphere; break; case "BodyWithoutAtmosphere": good = !body.atmosphere; break; case "SunAngleMin": good = Lib.IsSun(v.mainBody) || Lib.SunBodyAngle(v) >= double.Parse(value); break; case "SunAngleMax": good = Lib.IsSun(v.mainBody) || Lib.SunBodyAngle(v) <= double.Parse(value); break; case "Vacuum": good = !body.atmosphere || v.altitude > body.atmosphereDepth; break; case "Ocean": good = body.ocean && v.altitude < 0.0; break; case "PlanetarySpace": good = body.flightGlobalsIndex != 0 && !Lib.Landed(v) && v.altitude > body.atmosphereDepth; break; case "AbsoluteZero": good = vi.temperature < 30.0; break; case "InnerBelt": good = vi.inner_belt; break; case "OuterBelt": good = vi.outer_belt; break; case "MagneticBelt": good = vi.inner_belt || vi.outer_belt; break; case "Magnetosphere": good = vi.magnetosphere; break; case "Thermosphere": good = vi.thermosphere; break; case "Exosphere": good = vi.exosphere; break; case "InterPlanetary": good = body.flightGlobalsIndex == 0 && !vi.interstellar; break; case "InterStellar": good = body.flightGlobalsIndex == 0 && vi.interstellar; break; case "SurfaceSpeedMin": good = v.srfSpeed >= double.Parse(value); break; case "SurfaceSpeedMax": good = v.srfSpeed <= double.Parse(value); break; case "VerticalSpeedMin": good = v.verticalSpeed >= double.Parse(value); break; case "VerticalSpeedMax": good = v.verticalSpeed <= double.Parse(value); break; case "SpeedMin": good = v.speed >= double.Parse(value); break; case "SpeedMax": good = v.speed <= double.Parse(value); break; case "DynamicPressureMin": good = v.dynamicPressurekPa >= double.Parse(value); break; case "DynamicPressureMax": good = v.dynamicPressurekPa <= double.Parse(value); break; case "StaticPressureMin": good = v.staticPressurekPa >= double.Parse(value); break; case "StaticPressureMax": good = v.staticPressurekPa <= double.Parse(value); break; case "AtmDensityMin": good = v.atmDensity >= double.Parse(value); break; case "AtmDensityMax": good = v.atmDensity <= double.Parse(value); break; case "AltAboveGroundMin": good = v.heightFromTerrain >= double.Parse(value); break; case "AltAboveGroundMax": good = v.heightFromTerrain <= double.Parse(value); break; case "Part": good = Lib.HasPart(v, value); break; case "Module": good = Lib.FindModules(v.protoVessel, value).Count > 0; break; case "AstronautComplexLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) >= (double.Parse(value) - 1) / 2.0; break; case "AstronautComplexLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) <= (double.Parse(value) - 1) / 2.0; break; case "TrackingStationLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) >= (double.Parse(value) - 1) / 2.0; break; case "TrackingStationLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) <= (double.Parse(value) - 1) / 2.0; break; case "MissionControlLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) >= (double.Parse(value) - 1) / 2.0; break; case "MissionControlLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) <= (double.Parse(value) - 1) / 2.0; break; case "AdministrationLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) >= (double.Parse(value) - 1) / 2.0; break; case "AdministrationLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) <= (double.Parse(value) - 1) / 2.0; break; case "MaxAsteroidDistance": good = AsteroidDistance(v) <= double.Parse(value); break; } if (!good) { return(s); } } var subject_id = Science.Generate_subject_id(experiment_id, v); var exp = Science.Experiment(subject_id); var sit = GetExperimentSituation(v); if (!v.loaded && sit.AtmosphericFlight()) { return("Background flight"); } if (!sit.IsAvailable(exp)) { return("Invalid situation"); } // At this point we know the situation is valid and the experiment can be done // create it in R&D Science.Generate_subject(experiment_id, v); return(string.Empty); }
public bool TestRequirements(Vessel v, out RequireResult[] results, bool testAll = false) { UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.ExperimentRequirements.TestRequirements"); VesselData vd = v.KerbalismData(); results = new RequireResult[Requires.Length]; bool good = true; for (int i = 0; i < Requires.Length; i++) { results[i] = new RequireResult(Requires[i]); switch (Requires[i].require) { case Require.OrbitMinInclination: TestReq((c, r) => c >= r, v.orbit.inclination, (double)Requires[i].value, results[i]); break; case Require.OrbitMaxInclination: TestReq((c, r) => c <= r, v.orbit.inclination, (double)Requires[i].value, results[i]); break; case Require.OrbitMinEccentricity: TestReq((c, r) => c >= r, v.orbit.eccentricity, (double)Requires[i].value, results[i]); break; case Require.OrbitMaxEccentricity: TestReq((c, r) => c <= r, v.orbit.eccentricity, (double)Requires[i].value, results[i]); break; case Require.OrbitMinArgOfPeriapsis: TestReq((c, r) => c >= r, v.orbit.argumentOfPeriapsis, (double)Requires[i].value, results[i]); break; case Require.OrbitMaxArgOfPeriapsis: TestReq((c, r) => c <= r, v.orbit.argumentOfPeriapsis, (double)Requires[i].value, results[i]); break; case Require.TemperatureMin: TestReq((c, r) => c >= r, vd.EnvTemperature, (double)Requires[i].value, results[i]); break; case Require.TemperatureMax: TestReq((c, r) => c <= r, vd.EnvTemperature, (double)Requires[i].value, results[i]); break; case Require.AltitudeMin: TestReq((c, r) => c >= r, v.altitude, (double)Requires[i].value, results[i]); break; case Require.AltitudeMax: TestReq((c, r) => c <= r, v.altitude, (double)Requires[i].value, results[i]); break; case Require.RadiationMin: TestReq((c, r) => c >= r, vd.EnvRadiation, (double)Requires[i].value, results[i]); break; case Require.RadiationMax: TestReq((c, r) => c <= r, vd.EnvRadiation, (double)Requires[i].value, results[i]); break; case Require.VolumePerCrewMin: TestReq((c, r) => c >= r, vd.VolumePerCrew, (double)Requires[i].value, results[i]); break; case Require.VolumePerCrewMax: TestReq((c, r) => c <= r, vd.VolumePerCrew, (double)Requires[i].value, results[i]); break; case Require.SunAngleMin: TestReq((c, r) => c >= r, vd.EnvSunBodyAngle, (double)Requires[i].value, results[i]); break; case Require.SunAngleMax: TestReq((c, r) => c <= r, vd.EnvSunBodyAngle, (double)Requires[i].value, results[i]); break; case Require.SurfaceSpeedMin: TestReq((c, r) => c >= r, v.srfSpeed, (double)Requires[i].value, results[i]); break; case Require.SurfaceSpeedMax: TestReq((c, r) => c <= r, v.srfSpeed, (double)Requires[i].value, results[i]); break; case Require.VerticalSpeedMin: TestReq((c, r) => c >= r, v.verticalSpeed, (double)Requires[i].value, results[i]); break; case Require.VerticalSpeedMax: TestReq((c, r) => c <= r, v.verticalSpeed, (double)Requires[i].value, results[i]); break; case Require.SpeedMin: TestReq((c, r) => c >= r, v.speed, (double)Requires[i].value, results[i]); break; case Require.SpeedMax: TestReq((c, r) => c <= r, v.speed, (double)Requires[i].value, results[i]); break; case Require.DynamicPressureMin: TestReq((c, r) => c >= r, v.dynamicPressurekPa, (double)Requires[i].value, results[i]); break; case Require.DynamicPressureMax: TestReq((c, r) => c <= r, v.dynamicPressurekPa, (double)Requires[i].value, results[i]); break; case Require.StaticPressureMin: TestReq((c, r) => c >= r, v.staticPressurekPa, (double)Requires[i].value, results[i]); break; case Require.StaticPressureMax: TestReq((c, r) => c <= r, v.staticPressurekPa, (double)Requires[i].value, results[i]); break; case Require.AtmDensityMin: TestReq((c, r) => c >= r, v.atmDensity, (double)Requires[i].value, results[i]); break; case Require.AtmDensityMax: TestReq((c, r) => c <= r, v.atmDensity, (double)Requires[i].value, results[i]); break; case Require.AltAboveGroundMin: TestReq((c, r) => c >= r, v.heightFromTerrain, (double)Requires[i].value, results[i]); break; case Require.AltAboveGroundMax: TestReq((c, r) => c <= r, v.heightFromTerrain, (double)Requires[i].value, results[i]); break; case Require.MaxAsteroidDistance: TestReq((c, r) => c <= r, TestAsteroidDistance(v), (double)Requires[i].value, results[i]); break; case Require.AtmosphereAltMin: TestReq((c, r) => c >= r, v.mainBody.atmosphere ? v.altitude / v.mainBody.atmosphereDepth : double.NaN, (double)Requires[i].value, results[i]); break; case Require.AtmosphereAltMax: TestReq((c, r) => c <= r, v.mainBody.atmosphere ? v.altitude / v.mainBody.atmosphereDepth : double.NaN, (double)Requires[i].value, results[i]); break; case Require.CrewMin: TestReq((c, r) => c >= r, vd.CrewCount, (int)Requires[i].value, results[i]); break; case Require.CrewMax: TestReq((c, r) => c <= r, vd.CrewCount, (int)Requires[i].value, results[i]); break; case Require.CrewCapacityMin: TestReq((c, r) => c >= r, vd.CrewCapacity, (int)Requires[i].value, results[i]); break; case Require.CrewCapacityMax: TestReq((c, r) => c <= r, vd.CrewCapacity, (int)Requires[i].value, results[i]); break; case Require.AstronautComplexLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.AstronautComplex), (int)Requires[i].value, results[i]); break; case Require.AstronautComplexLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.AstronautComplex), (int)Requires[i].value, results[i]); break; case Require.TrackingStationLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.TrackingStation), (int)Requires[i].value, results[i]); break; case Require.TrackingStationLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.TrackingStation), (int)Requires[i].value, results[i]); break; case Require.MissionControlLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.MissionControl), (int)Requires[i].value, results[i]); break; case Require.MissionControlLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.MissionControl), (int)Requires[i].value, results[i]); break; case Require.AdministrationLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.Administration), (int)Requires[i].value, results[i]); break; case Require.AdministrationLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.Administration), (int)Requires[i].value, results[i]); break; case Require.Shadow: TestReq(() => vd.EnvInFullShadow, results[i]); break; case Require.Sunlight: TestReq(() => vd.EnvInSunlight, results[i]); break; case Require.Greenhouse: TestReq(() => vd.Greenhouses.Count > 0, results[i]); break; case Require.AbsoluteZero: TestReq(() => vd.EnvTemperature < 30.0, results[i]); break; case Require.InnerBelt: TestReq(() => vd.EnvInnerBelt, results[i]); break; case Require.OuterBelt: TestReq(() => vd.EnvOuterBelt, results[i]); break; case Require.MagneticBelt: TestReq(() => vd.EnvInnerBelt || vd.EnvOuterBelt, results[i]); break; case Require.Magnetosphere: TestReq(() => vd.EnvMagnetosphere, results[i]); break; case Require.InterStellar: TestReq(() => Lib.IsSun(v.mainBody) && vd.EnvInterstellar, results[i]); break; case Require.Part: TestReq(() => Lib.HasPart(v, (string)Requires[i].value), results[i]); break; case Require.Module: TestReq(() => Lib.FindModules(v.protoVessel, (string)Requires[i].value).Count > 0, results[i]); break; default: results[i].isValid = true; break; } if (!testAll && !results[i].isValid) { UnityEngine.Profiling.Profiler.EndSample(); return(false); } good &= results[i].isValid; } UnityEngine.Profiling.Profiler.EndSample(); return(good); }