/// <summary>obtain information on resource metrics for any resource contained within simulated vessel</summary>
		public SimulatedResource Resource(string name)
		{
			SimulatedResource res;
			if (!resources.TryGetValue(name, out res))
			{
				res = new SimulatedResource(name);
				resources.Add(name, res);
			}
			return res;
		}
Example #2
0
        ///<summary> Add habitat sub-panel, including tooltips </summary>
        private static void AddSubPanelHabitat(Panel p)
        {
            SimulatedResource atmo_res  = resource_sim.Resource("Atmosphere");
            SimulatedResource waste_res = resource_sim.Resource("WasteAtmosphere");
            SimulatedResource moist_res = resource_sim.Resource("MoistAtmosphere");

            // generate tooltips
            string atmo_tooltip  = atmo_res.Tooltip();
            string waste_tooltip = waste_res.Tooltip(true);
            string moist_tooltip = moist_res.Tooltip(true);

            // generate status string for scrubbing
            string waste_status = !Features.Poisoning                               //< feature disabled
                          ? "n/a"
                          : waste_res.produced <= double.Epsilon                    //< unnecessary
                          ? "not required"
                          : waste_res.consumed <= double.Epsilon                    //< no scrubbing
                          ? "<color=#ffff00>none</color>"
                          : waste_res.produced > waste_res.consumed * 1.001         //< insufficient scrubbing
                          ? "<color=#ffff00>inadequate</color>"
                          : "good";                                                 //< sufficient scrubbing

            // generate status string for humidity
            string moist_status = !Features.Humidity                                //< feature disabled
                          ? "n/a"
                          : moist_res.produced <= double.Epsilon                    //< unnecessary
                          ? "not required"
                          : moist_res.consumed <= double.Epsilon                    //< no humidity control
                          ? "<color=#ffff00>none</color>"
                          : moist_res.produced > moist_res.consumed * 1.001         //< insufficient humidity control
                          ? "<color=#ffff00>inadequate</color>"
                          : "good";                                                 //< sufficient humidity control

            // generate status string for pressurization
            string atmo_status = !Features.Pressure                                 //< feature disabled
                          ? "n/a"
                          : atmo_res.consumed <= double.Epsilon                     //< unnecessary
                          ? "not required"
                          : atmo_res.produced <= double.Epsilon                     //< no pressure control
                          ? "<color=#ffff00>none</color>"
                          : atmo_res.consumed > atmo_res.produced * 1.001           //< insufficient pressure control
                          ? "<color=#ffff00>inadequate</color>"
                          : "good";                                                 //< sufficient pressure control

            p.AddSection("HABITAT", string.Empty,
                         () => { p.Prev(ref environment_index, panel_environment.Count); update = true; },
                         () => { p.Next(ref environment_index, panel_environment.Count); update = true; });
            p.AddContent("volume", Lib.HumanReadableVolume(vessel_analyzer.volume), "volume of enabled habitats");
            p.AddContent("surface", Lib.HumanReadableSurface(vessel_analyzer.surface), "surface of enabled habitats");
            p.AddContent("scrubbing", waste_status, waste_tooltip);
            p.AddContent("humidity", moist_status, moist_tooltip);
            p.AddContent("pressurization", atmo_status, atmo_tooltip);
            p.AddContent("EVA's available", env_analyzer.breathable ? "infinite" : Lib.HumanReadableInteger(vessel_analyzer.evas),
                         env_analyzer.breathable ? "breathable atmosphere" : "approx (derived from stored N2)");
        }
Example #3
0
        ///<summary> Add electric charge sub-panel, including tooltips </summary>
        private static void AddSubPanelEC(Panel p)
        {
            // get simulated resource
            SimulatedResource res = resource_sim.Resource("ElectricCharge");

            // create tooltip
            string tooltip = res.Tooltip();

            // render the panel section
            p.AddSection(Local.Planner_ELECTRICCHARGE);                                         //"ELECTRIC CHARGE"
            p.AddContent(Local.Planner_storage, Lib.HumanReadableAmount(res.storage), tooltip); //"storage"
            p.AddContent(Local.Planner_consumed, Lib.HumanReadableRate(res.consumed), tooltip); //"consumed"
            p.AddContent(Local.Planner_produced, Lib.HumanReadableRate(res.produced), tooltip); //"produced"
            p.AddContent(Local.Planner_duration, Lib.HumanReadableDuration(res.Lifetime()));    //"duration"
        }
Example #4
0
        ///<summary> Add supply resource sub-panel, including tooltips </summary>
        ///<remarks>
        /// does not include electric charge
        /// does not include special resources like waste atmosphere
        /// restricted to resources that are configured explicitly in the profile as supplies
        ///</remarks>
        private static void AddSubPanelResource(Panel p, string res_name)
        {
            // get simulated resource
            SimulatedResource res = resource_sim.Resource(res_name);

            // create tooltip
            string tooltip = res.Tooltip();

            // render the panel section
            p.AddSection(Lib.SpacesOnCaps(res_name).ToUpper(), string.Empty,
                         () => { p.Prev(ref resource_index, panel_resource.Count); update = true; },
                         () => { p.Next(ref resource_index, panel_resource.Count); update = true; });
            p.AddContent("storage", Lib.HumanReadableAmount(res.storage), tooltip);
            p.AddContent("consumed", Lib.HumanReadableRate(res.consumed), tooltip);
            p.AddContent("produced", Lib.HumanReadableRate(res.produced), tooltip);
            p.AddContent("duration", Lib.HumanReadableDuration(res.Lifetime()));
        }
Example #5
0
        ///<summary> Add supply resource sub-panel, including tooltips </summary>
        ///<remarks>
        /// does not include electric charge
        /// does not include special resources like waste atmosphere
        /// restricted to resources that are configured explicitly in the profile as supplies
        ///</remarks>
        private static void AddSubPanelResource(Panel p, string res_name)
        {
            // get simulated resource
            SimulatedResource res = resource_sim.Resource(res_name);

            // create tooltip
            string tooltip = res.Tooltip();

            var resource = PartResourceLibrary.Instance.resourceDefinitions[res_name];

            // render the panel section
            p.AddSection(Lib.SpacesOnCaps(resource.displayName).ToUpper(), string.Empty,
                         () => { p.Prev(ref resource_index, panel_resource.Count); enforceUpdate = true; },
                         () => { p.Next(ref resource_index, panel_resource.Count); enforceUpdate = true; });
            p.AddContent(Local.Planner_storage, Lib.HumanReadableAmount(res.storage), tooltip);         //"storage"
            p.AddContent(Local.Planner_consumed, Lib.HumanReadableRate(res.consumed), tooltip);         //"consumed"
            p.AddContent(Local.Planner_produced, Lib.HumanReadableRate(res.produced), tooltip);         //"produced"
            p.AddContent(Local.Planner_duration, Lib.HumanReadableDuration(res.Lifetime()));            //"duration"
        }
Example #6
0
        ///<summary> Add habitat sub-panel, including tooltips </summary>
        private static void AddSubPanelHabitat(Panel p)
        {
            SimulatedResource atmo_res  = resource_sim.Resource("Atmosphere");
            SimulatedResource waste_res = resource_sim.Resource("WasteAtmosphere");

            // generate tooltips
            string atmo_tooltip  = atmo_res.Tooltip();
            string waste_tooltip = waste_res.Tooltip(true);

            // generate status string for scrubbing
            string waste_status = !Features.Poisoning                                        //< feature disabled
                          ? "n/a"
                          : waste_res.produced <= double.Epsilon                             //< unnecessary
                          ? Local.Planner_scrubbingunnecessary                               //"not required"
                          : waste_res.consumed <= double.Epsilon                             //< no scrubbing
                          ? Lib.Color(Local.Planner_noscrubbing, Lib.Kolor.Orange)           //"none"
                          : waste_res.produced > waste_res.consumed * 1.001                  //< insufficient scrubbing
                          ? Lib.Color(Local.Planner_insufficientscrubbing, Lib.Kolor.Yellow) //"inadequate"
                          : Lib.Color(Local.Planner_sufficientscrubbing, Lib.Kolor.Green);   //"good"                    //< sufficient scrubbing

            // generate status string for pressurization
            string atmo_status = !Features.Pressure                                                //< feature disabled
                          ? "n/a"
                          : atmo_res.consumed <= double.Epsilon                                    //< unnecessary
                          ? Local.Planner_pressurizationunnecessary                                //"not required"
                          : atmo_res.produced <= double.Epsilon                                    //< no pressure control
                          ? Lib.Color(Local.Planner_nopressurecontrol, Lib.Kolor.Orange)           //"none"
                          : atmo_res.consumed > atmo_res.produced * 1.001                          //< insufficient pressure control
                          ? Lib.Color(Local.Planner_insufficientpressurecontrol, Lib.Kolor.Yellow) //"inadequate"
                          : Lib.Color(Local.Planner_sufficientpressurecontrol, Lib.Kolor.Green);   //"good"                    //< sufficient pressure control

            p.AddSection(Local.Planner_HABITAT, string.Empty,                                      //"HABITAT"
                         () => { p.Prev(ref environment_index, panel_environment.Count); enforceUpdate = true; },
                         () => { p.Next(ref environment_index, panel_environment.Count); enforceUpdate = true; });
            p.AddContent(Local.Planner_volume, Lib.HumanReadableVolume(vessel_analyzer.volume), Local.Planner_volume_tip);                     //"volume""volume of enabled habitats"
            p.AddContent(Local.Planner_habitatssurface, Lib.HumanReadableSurface(vessel_analyzer.surface), Local.Planner_habitatssurface_tip); //"surface""surface of enabled habitats"
            p.AddContent(Local.Planner_scrubbing, waste_status, waste_tooltip);                                                                //"scrubbing"
            p.AddContent(Local.Planner_pressurization, atmo_status, atmo_tooltip);                                                             //"pressurization"
        }
		void Process_greenhouse(Greenhouse g, EnvironmentAnalyzer env, VesselAnalyzer va)
		{
			// skip disabled greenhouses
			if (!g.active)
				return;

			// shortcut to resources
			SimulatedResource ec = Resource("ElectricCharge");
			SimulatedResource res = Resource(g.crop_resource);

			// calculate natural and artificial lighting
			double natural = env.solar_flux;
			double artificial = Math.Max(g.light_tolerance - natural, 0.0);

			// if lamps are on and artificial lighting is required
			if (artificial > 0.0)
			{
				// consume ec for the lamps
				ec.Consume(g.ec_rate * (artificial / g.light_tolerance), "greenhouse");
			}

			// execute recipe
			SimulatedRecipe recipe = new SimulatedRecipe(g.part, "greenhouse");
			foreach (ModuleResource input in g.resHandler.inputResources)
			{
				// WasteAtmosphere is primary combined input
				if (g.WACO2 && input.name == "WasteAtmosphere")
					recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "CarbonDioxide");
				// CarbonDioxide is secondary combined input
				else if (g.WACO2 && input.name == "CarbonDioxide")
					recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "");
				// if atmosphere is breathable disable WasteAtmosphere / CO2
				else if (!g.WACO2 && (input.name == "CarbonDioxide" || input.name == "WasteAtmosphere"))
					recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "");
				else
					recipe.Input(input.name, input.rate);
			}
			foreach (ModuleResource output in g.resHandler.outputResources)
			{
				// if atmosphere is breathable disable Oxygen
				if (output.name == "Oxygen")
					recipe.Output(output.name, env.breathable ? 0.0 : output.rate, true);
				else
					recipe.Output(output.name, output.rate, true);
			}
			recipes.Add(recipe);

			// determine environment conditions
			bool lighting = natural + artificial >= g.light_tolerance;
			bool pressure = va.pressurized || g.pressure_tolerance <= double.Epsilon;
			bool radiation = (env.landed ? env.surface_rad : env.magnetopause_rad) * (1.0 - va.shielding) < g.radiation_tolerance;

			// if all conditions apply
			// note: we are assuming the inputs are satisfied, we can't really do otherwise here
			if (lighting && pressure && radiation)
			{
				// produce food
				res.Produce(g.crop_size * g.crop_rate, "greenhouse");

				// add harvest info
				res.harvests.Add(Lib.BuildString(g.crop_size.ToString("F0"), " in ", Lib.HumanReadableDuration(1.0 / g.crop_rate)));
			}
		}
Example #8
0
        // execute the recipe
        public bool Execute(ResourceSimulator sim)
        {
            // determine worst input ratio
            double worst_input = left;

            if (outputs.Count > 0)
            {
                for (int i = 0; i < inputs.Count; ++i)
                {
                    Resource_recipe.Entry e   = inputs[i];
                    SimulatedResourceView res = sim.Resource(e.name).GetSimulatedResourceView(loaded_part);
                    // handle combined inputs
                    if (e.combined != null)
                    {
                        // is combined resource the primary
                        if (e.combined != "")
                        {
                            Resource_recipe.Entry sec_e = inputs.Find(x => x.name.Contains(e.combined));
                            SimulatedResourceView sec   = sim.Resource(sec_e.name).GetSimulatedResourceView(loaded_part);
                            double pri_worst            = Lib.Clamp(res.amount * e.inv_quantity, 0.0, worst_input);
                            if (pri_worst > 0.0)
                            {
                                worst_input = pri_worst;
                            }
                            else
                            {
                                worst_input = Lib.Clamp(sec.amount * sec_e.inv_quantity, 0.0, worst_input);
                            }
                        }
                    }
                    else
                    {
                        worst_input = Lib.Clamp(res.amount * e.inv_quantity, 0.0, worst_input);
                    }
                }
            }

            // determine worst output ratio
            double worst_output = left;

            if (inputs.Count > 0)
            {
                for (int i = 0; i < outputs.Count; ++i)
                {
                    Resource_recipe.Entry e = outputs[i];
                    if (!e.dump)                     // ignore outputs that can dump overboard
                    {
                        SimulatedResourceView res = sim.Resource(e.name).GetSimulatedResourceView(loaded_part);
                        worst_output = Lib.Clamp((res.capacity - res.amount) * e.inv_quantity, 0.0, worst_output);
                    }
                }
            }

            // determine worst-io
            double worst_io = Math.Min(worst_input, worst_output);

            // consume inputs
            for (int i = 0; i < inputs.Count; ++i)
            {
                Resource_recipe.Entry e   = inputs[i];
                SimulatedResource     res = sim.Resource(e.name);
                // handle combined inputs
                if (e.combined != null)
                {
                    // is combined resource the primary
                    if (e.combined != "")
                    {
                        Resource_recipe.Entry sec_e = inputs.Find(x => x.name.Contains(e.combined));
                        SimulatedResourceView sec   = sim.Resource(sec_e.name).GetSimulatedResourceView(loaded_part);
                        double need = (e.quantity * worst_io) + (sec_e.quantity * worst_io);
                        // do we have enough primary to satisfy needs, if so don't consume secondary
                        if (res.amount >= need)
                        {
                            res.Consume(need, name);
                        }
                        // consume primary if any available and secondary
                        else
                        {
                            need -= res.amount;
                            res.Consume(res.amount, name);
                            sec.Consume(need, name);
                        }
                    }
                }
                else
                {
                    res.Consume(e.quantity * worst_io, name);
                }
            }

            // produce outputs
            for (int i = 0; i < outputs.Count; ++i)
            {
                Resource_recipe.Entry e   = outputs[i];
                SimulatedResourceView res = sim.Resource(e.name).GetSimulatedResourceView(loaded_part);
                res.Produce(e.quantity * worst_io, name);
            }

            // update amount left to execute
            left -= worst_io;

            // the recipe was executed, at least partially
            return(worst_io > double.Epsilon);
        }
Example #9
0
 public Simulated_resource_view_impl(Part p, string resource_name, SimulatedResource i)
 {
     info     = i;
     location = info.vessel_wide_location;
 }