Exemple #1
0
        // specifics support
        public Specifics Specs()
        {
            Specifics specs = new Specifics();

            if (redundancy.Length > 0)
            {
                specs.Add("Redundancy", redundancy);
            }
            specs.Add("Repair", new CrewSpecs(repair).Info());
            specs.Add(string.Empty);
            specs.Add("<color=#00ffff>Standard quality</color>");
            specs.Add("MTBF", Lib.HumanReadableDuration(mtbf));
            specs.Add(string.Empty);
            specs.Add("<color=#00ffff>High quality</color>");
            specs.Add("MTBF", Lib.HumanReadableDuration(mtbf * Settings.QualityScale));
            if (extra_cost > double.Epsilon)
            {
                specs.Add("Extra cost", Lib.HumanReadableCost(extra_cost * part.partInfo.cost));
            }
            if (extra_mass > double.Epsilon)
            {
                specs.Add("Extra mass", Lib.HumanReadableMass(extra_mass * part.partInfo.partPrefab.mass));
            }
            return(specs);
        }
Exemple #2
0
        // specifics support
        public Specifics Specs()
        {
            if (exp == null)
            {
                exp = ResearchAndDevelopment.GetExperiment(experiment_id);
            }

            var specs = new Specifics();

            specs.Add(Lib.BuildString("<b>", ResearchAndDevelopment.GetExperiment(experiment_id).experimentTitle, "</b>"));

            if (!string.IsNullOrEmpty(experiment_desc))
            {
                specs.Add(Lib.BuildString("<i>", experiment_desc, "</i>"));
            }
            specs.Add(string.Empty);

            double expSize = exp.scienceCap * exp.dataScale;

            if (sample_mass < float.Epsilon)
            {
                specs.Add("Data", Lib.HumanReadableDataSize(expSize));
                specs.Add("Data rate", Lib.HumanReadableDataRate(data_rate));
                specs.Add("Duration", Lib.HumanReadableDuration(expSize / data_rate));
            }
            else
            {
                specs.Add("Sample size", Lib.HumanReadableSampleSize(expSize));
                specs.Add("Sample mass", Lib.HumanReadableMass(sample_mass));
                specs.Add("Duration", Lib.HumanReadableDuration(expSize / data_rate));
            }

            specs.Add("EC required", Lib.HumanReadableRate(ec_rate));
            if (crew_operate.Length > 0)
            {
                specs.Add("Opration", new CrewSpecs(crew_operate).Info());
            }
            if (crew_reset.Length > 0)
            {
                specs.Add("Reset", new CrewSpecs(crew_reset).Info());
            }
            if (crew_prepare.Length > 0)
            {
                specs.Add("Preparation", new CrewSpecs(crew_prepare).Info());
            }

            if (!string.IsNullOrEmpty(requires))
            {
                specs.Add(string.Empty);
                specs.Add("<color=#00ffff>Requirements:</color>", string.Empty);
                var tokens = Lib.Tokenize(requires, ',');
                foreach (string s in tokens)
                {
                    specs.Add(Lib.BuildString("• <b>", Science.RequirementText(s), "</b>"));
                }
            }
            return(specs);
        }
Exemple #3
0
        private void UpdateCapacity()
        {
            if (drive == null)
            {
                return;
            }

            double mass = 0;

            foreach (var sample in drive.samples.Values)
            {
                mass += sample.mass;
            }
            totalSampleMass = mass;

            if (effectiveDataCapacity < 0 || effectiveSampleCapacity < 0 || IsPrivate())
            {
                Fields["Capacity"].guiActive       = false;
                Fields["Capacity"].guiActiveEditor = false;
                return;
            }

            double availableDataCapacity = effectiveDataCapacity;
            int    availableSlots        = effectiveSampleCapacity;

            if (Lib.IsFlight())
            {
                availableDataCapacity = drive.FileCapacityAvailable();
                availableSlots        = Lib.SampleSizeToSlots(drive.SampleCapacityAvailable());
            }

            Capacity = string.Empty;
            if (availableDataCapacity > double.Epsilon)
            {
                Capacity = Lib.HumanReadableDataSize(availableDataCapacity);
            }
            if (availableSlots > 0)
            {
                if (Capacity.Length > 0)
                {
                    Capacity += " ";
                }
                Capacity += Lib.HumanReadableSampleSize(availableSlots);
            }

            if (Lib.IsFlight() && totalSampleMass > double.Epsilon)
            {
                Capacity += " " + Lib.HumanReadableMass(totalSampleMass);
            }
        }
Exemple #4
0
        // specifics support
        public Specifics Specs()
        {
            Specifics specs = new Specifics();

            specs.Add(Local.Habitat_info1, Lib.HumanReadableVolume(volume > 0.0 ? volume : Lib.PartBoundsVolume(part)) + (volume > 0.0 ? "" : " (bounds)"));      //"Volume"
            specs.Add(Local.Habitat_info2, Lib.HumanReadableSurface(surface > 0.0 ? surface : Lib.PartBoundsSurface(part)) + (surface > 0.0 ? "" : " (bounds)")); //"Surface"
            specs.Add(Local.Habitat_info3, max_pressure >= Settings.PressureThreshold ? Local.Habitat_yes : Local.Habitat_no);                                    //"Pressurized""yes""no"
            if (inflate.Length > 0)
            {
                specs.Add(Local.Habitat_info4, Local.Habitat_yes);                    //"Inflatable""yes"
            }
            if (PhysicsGlobals.KerbalCrewMass > 0)
            {
                specs.Add(Local.Habitat_info5, Lib.HumanReadableMass(PhysicsGlobals.KerbalCrewMass));//"Added mass per crew"
            }
            return(specs);
        }
Exemple #5
0
        // specifics support
        public Specifics Specs()
        {
            Specifics specs = new Specifics();

            specs.Add("Volume", Lib.HumanReadableVolume(volume > double.Epsilon ? volume : Lib.PartVolume(part)));
            specs.Add("Surface", Lib.HumanReadableSurface(surface > double.Epsilon ? surface : Lib.PartSurface(part)));
            if (inflate.Length > 0)
            {
                specs.Add("Inflatable", "yes");
            }
            if (PhysicsGlobals.KerbalCrewMass > 0)
            {
                specs.Add("Added mass per crew", Lib.HumanReadableMass(PhysicsGlobals.KerbalCrewMass));
            }

            return(specs);
        }
Exemple #6
0
        static void Render_sample(Panel p, uint partId, Sample sample, Drive drive, bool short_strings)
        {
            // render experiment name
            string exp_label = Lib.BuildString
                               (
                "<b>",
                Lib.Ellipsis(sample.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)),
                "</b> <size=", Styles.ScaleInteger(10).ToString(), ">",
                Lib.Ellipsis(sample.subjectData.SituationTitle, Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(sample.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)),
                "</size>"
                               );
            string exp_tooltip = Lib.BuildString
                                 (
                sample.subjectData.ExperimentTitle, "\n",
                Lib.Color(sample.subjectData.SituationTitle, Lib.Kolor.LightGrey)
                                 );

            double exp_value = sample.size * sample.subjectData.SciencePerMB;

            if (exp_value >= 0.1)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value, false), "</b>");
            }
            if (sample.mass > Double.Epsilon)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableMass(sample.mass), "</b>");
            }
            if (!string.IsNullOrEmpty(sample.resultText))
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n", Lib.WordWrapAtLength(sample.resultText, 50));
            }

            p.AddContent(exp_label, Lib.HumanReadableSampleSize(sample.size), exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan));
            p.AddRightIcon(sample.analyze ? Textures.lab_cyan : Textures.lab_black, Local.FILEMANAGER_analysis, () => { sample.analyze = !sample.analyze; }); //"Flag the file for analysis in a <b>laboratory</b>"
            p.AddRightIcon(Textures.toggle_red, Local.FILEMANAGER_Dumpsample, () =>                                                                           //"Dump the sample"
            {
                Lib.Popup(Local.FILEMANAGER_Warning_title,                                                                                                    //"Warning!"
                          Local.FILEMANAGER_DumpConfirm.Format(sample.subjectData.FullTitle),                                                                 //"Do you really want to dump <<1>>?",
                          new DialogGUIButton(Local.FILEMANAGER_DumpConfirm_button1, () => drive.Delete_sample(sample.subjectData)),                          //"Dump it"
                          new DialogGUIButton(Local.FILEMANAGER_DumpConfirm_button2, () => { }));                                                             //"Keep it"
            }
                           );
        }
        static void Render_sample(Panel p, uint partId, string filename, Sample sample, Drive drive, bool short_strings)
        {
            // get experiment info
            ExperimentInfo exp = Science.Experiment(filename);

            // render experiment name
            string exp_label = Lib.BuildString
                               (
                "<b>",
                Lib.Ellipsis(exp.name, Styles.ScaleStringLength(short_strings ? 24 : 38)),
                "</b> <size=", Styles.ScaleInteger(10).ToString(), ">",
                Lib.Ellipsis(ExperimentInfo.Situation(filename), Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(exp.name, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)),
                "</size>"
                               );
            string exp_tooltip = Lib.BuildString
                                 (
                exp.name, "\n",
                "<color=#aaaaaa>", ExperimentInfo.Situation(filename), "</color>"
                                 );
            double exp_value = Science.Value(filename, sample.size);

            if (exp_value >= 0.1)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value), "</b>");
            }
            if (sample.mass > Double.Epsilon)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableMass(sample.mass), "</b>");
            }

            p.AddContent(exp_label, Lib.HumanReadableSampleSize(sample.size), exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan));
            p.AddIcon(sample.analyze ? Icons.lab_cyan : Icons.lab_black, "Flag the file for analysis in a <b>laboratory</b>", () => { sample.analyze = !sample.analyze; });
            p.AddIcon(Icons.toggle_red, "Dump the sample", () =>
            {
                Lib.Popup("Warning!",
                          Lib.BuildString("Do you really want to dump ", exp.FullName(filename), "?"),
                          new DialogGUIButton("Dump it", () => drive.samples.Remove(filename)),
                          new DialogGUIButton("Keep it", () => { }));
            }
                      );
        }
Exemple #8
0
        private void UpdateCapacity()
        {
            totalSampleMass = 0;
            foreach (var sample in drive.samples.Values)
            {
                totalSampleMass += sample.mass;
            }

            double availableDataCapacity = dataCapacity;
            int    availableSlots        = sampleCapacity;

            if (Lib.IsFlight())
            {
                availableDataCapacity = drive.FileCapacityAvailable();
                availableSlots        = Lib.SampleSizeToSlots(drive.SampleCapacityAvailable());
            }

            Capacity = string.Empty;
            if (availableDataCapacity > double.Epsilon)
            {
                Capacity = Lib.HumanReadableDataSize(availableDataCapacity);
            }
            if (availableSlots > 0)
            {
                if (Capacity.Length > 0)
                {
                    Capacity += " ";
                }
                Capacity += Lib.HumanReadableSampleSize(availableSlots);
            }

            if (Lib.IsFlight() && totalSampleMass > double.Epsilon)
            {
                Capacity += " " + Lib.HumanReadableMass(totalSampleMass);
            }
        }
        /// <summary>
        /// If short_strings parameter is true then the strings used for display of the data will be shorter when inflight.
        /// </summary>
        public static void Fileman(this Panel p, Vessel v, bool short_strings = false)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            Vessel_info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(40)), " <color=#cccccc>FILE MANAGER</color>"));
            p.Width(Styles.ScaleWidthFloat(465.0f));
            p.paneltype = Panel.PanelType.data;

            // time-out simulation
            if (!Lib.IsControlUnit(v) && p.Timeout(vi))
            {
                return;
            }

            var drives = Drive.GetDriveParts(v);

            int    filesCount        = 0;
            double usedDataCapacity  = 0;
            double totalDataCapacity = 0;

            int    samplesCount     = 0;
            int    usedSlots        = 0;
            int    totalSlots       = 0;
            double totalMass        = 0;
            bool   unlimitedData    = false;
            bool   unlimitedSamples = false;

            foreach (var idDrivePair in drives)
            {
                var drive = idDrivePair.Value;

                if (!drive.is_private)
                {
                    usedDataCapacity  += drive.FilesSize();
                    totalDataCapacity += drive.dataCapacity;

                    unlimitedData    |= drive.dataCapacity < 0;
                    unlimitedSamples |= drive.sampleCapacity < 0;

                    usedSlots  += drive.SamplesSize();
                    totalSlots += drive.sampleCapacity;
                }

                filesCount   += drive.files.Count;
                samplesCount += drive.samples.Count;
                foreach (var sample in drive.samples.Values)
                {
                    totalMass += sample.mass;
                }
            }

            if (filesCount > 0 || totalDataCapacity > 0)
            {
                var title = "DATA " + Lib.HumanReadableDataSize(usedDataCapacity);
                if (!unlimitedData)
                {
                    title += Lib.BuildString(" (", Lib.HumanReadablePerc((totalDataCapacity - usedDataCapacity) / totalDataCapacity), " available)");
                }
                p.AddSection(title);

                foreach (var idDrivePair in drives)
                {
                    uint partId = idDrivePair.Key;
                    var  drive  = idDrivePair.Value;
                    foreach (var pair in drive.files)
                    {
                        string filename = pair.Key;
                        File   file     = pair.Value;
                        Render_file(p, partId, filename, file, drive, short_strings && Lib.IsFlight(), v);
                    }
                }

                if (filesCount == 0)
                {
                    p.AddContent("<i>no files</i>", string.Empty);
                }
            }

            if (samplesCount > 0 || totalSlots > 0)
            {
                var title = "SAMPLES " + Lib.HumanReadableMass(totalMass) + " " + Lib.HumanReadableSampleSize(usedSlots);
                if (totalSlots > 0 && !unlimitedSamples)
                {
                    title += ", " + Lib.HumanReadableSampleSize(totalSlots) + " available";
                }
                p.AddSection(title);

                foreach (var idDrivePair in drives)
                {
                    uint partId = idDrivePair.Key;
                    var  drive  = idDrivePair.Value;
                    foreach (var pair in drive.samples)
                    {
                        string samplename = pair.Key;
                        Sample sample     = pair.Value;
                        Render_sample(p, partId, samplename, sample, drive, short_strings && Lib.IsFlight());
                    }
                }

                if (samplesCount == 0)
                {
                    p.AddContent("<i>no samples</i>", string.Empty);
                }
            }
        }
Exemple #10
0
        public void generate_details(Configure cfg)
        {
            // If a setup component is defined after the Configure module in the ConfigNode,
            // then it is not present in the part during Configure::OnLoad (at precompilation time)
            // so, find_module() will fail in that situation, resulting in no component details
            // being added to the Configure window. Therefore we are forced to generate the details
            // at first use every time the module is loaded, instead of generating them only once.

            // already generated
            if (details != null)
            {
                return;
            }

            // generate module details
            details = new List <Detail>();
            foreach (ConfigureModule cm in modules)
            {
                // find module, skip if it doesn't exist
                PartModule m = cfg.find_module(cm);
                if (m == null)
                {
                    continue;
                }

                // get title
                IModuleInfo module_info = m as IModuleInfo;
                string      title       = module_info != null?module_info.GetModuleTitle() : cm.type;

                if (title.Length == 0)
                {
                    continue;
                }

                // get specs, skip if not implemented by module
                ISpecifics specifics = m as ISpecifics;
                if (specifics == null)
                {
                    continue;
                }
                Specifics specs = specifics.Specs();
                if (specs.entries.Count == 0)
                {
                    continue;
                }

                // add title to details
                details.Add(new Detail(Lib.BuildString("<b><color=#00ffff>", title, "</color></b>")));

                // add specs to details
                foreach (Specifics.Entry e in specs.entries)
                {
                    details.Add(new Detail(e.label, e.value));
                }
            }

            // get visible resources subset
            List <ConfigureResource> visible_resources = resources.FindAll(k => Lib.GetDefinition(k.name).isVisible);

            // generate resource details
            if (visible_resources.Count > 0)
            {
                // add resources title
                details.Add(new Detail("<b><color=#00ffff>Resources</color></b>"));

                // for each visible resource
                foreach (ConfigureResource cr in visible_resources)
                {
                    // add capacity info
                    details.Add(new Detail(cr.name, Lib.Parse.ToDouble(cr.maxAmount).ToString("F2")));
                }
            }

            // generate extra details
            if (mass > double.Epsilon || cost > double.Epsilon)
            {
                details.Add(new Detail("<b><color=#00ffff>Extra</color></b>"));
                if (mass > double.Epsilon)
                {
                    details.Add(new Detail("mass", Lib.HumanReadableMass(mass)));
                }
                if (cost > double.Epsilon)
                {
                    details.Add(new Detail("cost", Lib.HumanReadableCost(cost)));
                }
            }
        }
        /// <summary>
        /// parts that have experiments can't get their module info (what is shown in the VAB tooltip) correctly setup
        /// because the ExperimentInfo database isn't available at loading time, so we recompile their info manually.
        /// </summary>
        public void CompileModuleInfos()
        {
            if (PartLoader.LoadedPartsList == null)
            {
                Lib.Log("Dazed and confused: PartLoader.LoadedPartsList == null");
                return;
            }

            foreach (AvailablePart ap in PartLoader.LoadedPartsList)
            {
                if (ap == null || ap.partPrefab == null)
                {
                    Lib.Log("AvailablePart is null or without prefab: " + ap);
                    continue;
                }

                foreach (PartModule module in ap.partPrefab.Modules)
                {
                    if (module is Experiment expModule)
                    {
                        // don't show configurable experiments
                        if (!expModule.isConfigurable && expModule.experiment_id == ExperimentId)
                        {
                            expModule.ExpInfo = this;

                            // get module info for the ExperimentInfo, once
                            if (string.IsNullOrEmpty(ModuleInfo))
                            {
                                ModuleInfo  = Lib.Color(Title, Lib.Kolor.Cyan, true);
                                ModuleInfo += "\n";
                                ModuleInfo += expModule.GetInfo();
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(ModuleInfo))
                    {
                        continue;
                    }

                    if (module is ModuleScienceExperiment stockExpModule)
                    {
                        if (stockExpModule.experimentID == ExperimentId)
                        {
                            ModuleInfo  = Lib.Color(Title, Lib.Kolor.Cyan, true);
                            ModuleInfo += "\n" + Local.Experimentinfo_Datasize + ": ";                         //Data size
                            ModuleInfo += Lib.HumanReadableDataSize(DataSize);
                            if (stockExpModule.xmitDataScalar < Science.maxXmitDataScalarForSample)
                            {
                                ModuleInfo += "\n" + Local.Experimentinfo_generatesample;                              //Will generate a sample.
                                ModuleInfo += "\n" + Local.Experimentinfo_Samplesize + " ";                            //Sample size:
                                ModuleInfo += Lib.HumanReadableSampleSize(DataSize);
                            }
                            ModuleInfo += "\n\n";
                            ModuleInfo += Lib.Color(Local.Experimentinfo_Situations, Lib.Kolor.Cyan, true);                            //"Situations:\n"

                            foreach (string s in AvailableSituations())
                            {
                                ModuleInfo += Lib.BuildString("• <b>", s, "</b>\n");
                            }

                            ModuleInfo += "\n";
                            ModuleInfo += stockExpModule.GetInfo();
                        }
                    }
                    else if (module is ModuleGroundExperiment groundExpModule)
                    {
                        if (groundExpModule.experimentId == ExperimentId)
                        {
                            ModuleInfo  = Lib.Color(Title, Lib.Kolor.Cyan, true);
                            ModuleInfo += "\n" + Local.Experimentinfo_Datasize + ": ";                            //Data size
                            ModuleInfo += Lib.HumanReadableDataSize(DataSize);
                            ModuleInfo += "\n\n";
                            ModuleInfo += groundExpModule.GetInfo();
                        }
                    }
                }

                // special cases
                if (ExperimentId == "asteroidSample" || ExperimentId.StartsWith("cometSample_", StringComparison.Ordinal))
                {
                    ModuleInfo  = Local.Experimentinfo_Asteroid;                   //"Asteroid samples can be taken by kerbals on EVA"
                    ModuleInfo += "\n" + Local.Experimentinfo_Samplesize + " ";    //Sample size:
                    ModuleInfo += Lib.HumanReadableSampleSize(DataSize);
                    ModuleInfo += "\n" + Local.Experimentinfo_Samplemass + " ";    //Sample mass:
                    ModuleInfo += Lib.HumanReadableMass(DataSize * Settings.AsteroidSampleMassPerMB);
                }
                else if (IsROC)
                {
                    string        rocType = ExperimentId.Substring(ExperimentId.IndexOf('_') + 1);
                    ROCDefinition rocDef  = ROCManager.Instance.rocDefinitions.Find(p => p.type == rocType);
                    if (rocDef != null)
                    {
                        ModuleInfo  = Lib.Color(rocDef.displayName, Lib.Kolor.Cyan, true);
                        ModuleInfo += "\n- " + Local.Experimentinfo_scannerarm;                        //Analyse with a scanner arm
                        ModuleInfo += "\n  " + Local.Experimentinfo_Datasize + ": ";                   //Data size
                        ModuleInfo += Lib.HumanReadableDataSize(DataSize);

                        if (rocDef.smallRoc)
                        {
                            ModuleInfo += "\n- " + Local.Experimentinfo_smallRoc;                            //Collectable on EVA as a sample"
                            ModuleInfo += "\n" + Local.Experimentinfo_Samplesize + " ";                      //Sample size:
                            ModuleInfo += Lib.HumanReadableSampleSize(DataSize);
                        }
                        else
                        {
                            ModuleInfo += "\n- " + Local.Experimentinfo_smallRoc2;                          //Can't be collected on EVA
                        }

                        foreach (RocCBDefinition body in rocDef.myCelestialBodies)
                        {
                            ModuleInfo += Lib.Color("\n\n" + Local.Experimentinfo_smallRoc3.Format(body.name), Lib.Kolor.Cyan, true);                            //"Found on <<1>>'s :"
                            foreach (string biome in body.biomes)
                            {
                                ModuleInfo += "\n- ";
                                ModuleInfo += biome;
                            }
                        }
                    }
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// If short_strings parameter is true then the strings used for display of the data will be shorter when inflight.
        /// </summary>
        public static void Fileman(this Panel p, Vessel v, bool short_strings = false)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            Vessel_info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(40)), " <color=#cccccc>FILE MANAGER</color>"));
            p.Width(Styles.ScaleWidthFloat(465.0f));
            p.paneltype = Panel.PanelType.data;

            // time-out simulation
            if (p.Timeout(vi))
            {
                return;
            }

            foreach (var idDrivePair in DB.Vessel(v).drives)
            {
                var drive = idDrivePair.Value;

                if (drive.dataCapacity > double.Epsilon)
                {
                    // draw data section
                    p.AddSection(Lib.BuildString("DATA ", drive.name, " ", Lib.HumanReadableDataSize(drive.dataCapacity),
                                                 " (", Lib.HumanReadablePerc(drive.FilesSize() / drive.dataCapacity), ")"));
                    foreach (var pair in drive.files)
                    {
                        string filename = pair.Key;
                        File   file     = pair.Value;
                        Render_file(p, filename, file, drive, short_strings && Lib.IsFlight(), Cache.VesselInfo(v).connection.rate);
                    }
                    if (drive.files.Count == 0)
                    {
                        p.AddContent("<i>no files</i>", string.Empty);
                    }
                }

                if (drive.sampleCapacity > 0)
                {
                    double mass = 0;
                    foreach (var sample in drive.samples.Values)
                    {
                        mass += sample.mass;
                    }

                    // draw samples section
                    p.AddSection(Lib.BuildString("SAMPLES ", drive.name, " ",
                                                 Lib.HumanReadableSampleSize(drive.sampleCapacity),
                                                 " (", Lib.HumanReadablePerc(drive.SamplesSize() / drive.sampleCapacity), ") ",
                                                 Lib.HumanReadableMass(mass)));
                    foreach (var pair in drive.samples)
                    {
                        string filename = pair.Key;
                        Sample sample   = pair.Value;
                        Render_sample(p, filename, sample, drive, short_strings && Lib.IsFlight());
                    }
                    if (drive.samples.Count == 0)
                    {
                        p.AddContent("<i>no samples</i>", string.Empty);
                    }
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// parts that have experiments can't get their module info (what is shown in the VAB tooltip) correctly setup
        /// because the ExperimentInfo database isn't available at loading time, so we recompile their info manually.
        /// </summary>
        public void SetupPrefabs()
        {
            if (PartLoader.LoadedPartsList == null)
            {
                Lib.Log("Dazed and confused: PartLoader.LoadedPartsList == null");
                return;
            }

            foreach (AvailablePart ap in PartLoader.LoadedPartsList)
            {
                if (ap == null || ap.partPrefab == null)
                {
                    Lib.Log("AvailablePart is null or without prefab: " + ap);
                    continue;
                }

                bool partHasExperimentModule = false;

                foreach (PartModule module in ap.partPrefab.Modules)
                {
                    if (module is Experiment expModule)
                    {
                        if (expModule.experiment_id == ExperimentId)
                        {
                            expModule.ExpInfo       = this;                       // works inside the ExperimentInfo ctor, but make sure it's called at the end of it.
                            partHasExperimentModule = true;

                            // get module info for the ExperimentInfo, once
                            if (string.IsNullOrEmpty(ModuleInfo))
                            {
                                ModuleInfo  = Lib.Color(Title, Lib.Kolor.Cyan, true);
                                ModuleInfo += "\n";
                                ModuleInfo += expModule.GetInfo();
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(ModuleInfo))
                    {
                        continue;
                    }

                    if (module is ModuleScienceExperiment stockExpModule)
                    {
                        if (stockExpModule.experimentID == ExperimentId)
                        {
                            ModuleInfo  = Lib.Color(Title, Lib.Kolor.Cyan, true);
                            ModuleInfo += "\nData size: ";
                            ModuleInfo += Lib.HumanReadableDataSize(DataSize);
                            if (stockExpModule.xmitDataScalar < Science.maxXmitDataScalarForSample)
                            {
                                ModuleInfo += "\nWill generate a sample.";
                                ModuleInfo += "\nSample size: ";
                                ModuleInfo += Lib.HumanReadableSampleSize(DataSize);
                            }
                            ModuleInfo += "\n\n";
                            ModuleInfo += Lib.Color("Situations:\n", Lib.Kolor.Cyan, true);

                            foreach (string s in AvailableSituations())
                            {
                                ModuleInfo += Lib.BuildString("• <b>", s, "</b>\n");
                            }

                            ModuleInfo += "\n";
                            ModuleInfo += stockExpModule.GetInfo();
                        }
                    }

#if !KSP15_16
                    else if (module is ModuleGroundExperiment groundExpModule)
                    {
                        if (groundExpModule.experimentId == ExperimentId)
                        {
                            ModuleInfo  = Lib.Color(Title, Lib.Kolor.Cyan, true);
                            ModuleInfo += "\nData size: ";
                            ModuleInfo += Lib.HumanReadableDataSize(DataSize);
                            ModuleInfo += "\n\n";
                            ModuleInfo += groundExpModule.GetInfo();
                        }
                    }
#endif
                }

                // special cases
                if (ExperimentId == "asteroidSample")
                {
                    ModuleInfo  = "Asteroid samples can be taken by kerbals on EVA";
                    ModuleInfo += "\nSample size: ";
                    ModuleInfo += Lib.HumanReadableSampleSize(DataSize);
                    ModuleInfo += "\nSample mass: ";
                    ModuleInfo += Lib.HumanReadableMass(DataSize * Settings.AsteroidSampleMassPerMB);
                }
#if !KSP15_16
                else if (IsROC)
                {
                    string        rocType = ExperimentId.Substring(ExperimentId.IndexOf('_') + 1);
                    ROCDefinition rocDef  = ROCManager.Instance.rocDefinitions.Find(p => p.type == rocType);
                    if (rocDef != null)
                    {
                        ModuleInfo  = Lib.Color(rocDef.displayName, Lib.Kolor.Cyan, true);
                        ModuleInfo += "\n- Analyse with a scanner arm";
                        ModuleInfo += "\n  Data size: ";
                        ModuleInfo += Lib.HumanReadableDataSize(DataSize);

                        if (rocDef.smallRoc)
                        {
                            ModuleInfo += "\n- Collectable on EVA as a sample";
                            ModuleInfo += "\nSample size: ";
                            ModuleInfo += Lib.HumanReadableSampleSize(DataSize);
                        }
                        else
                        {
                            ModuleInfo += "\n- Can't be collected on EVA";
                        }

                        foreach (RocCBDefinition body in rocDef.myCelestialBodies)
                        {
                            ModuleInfo += Lib.Color("\n\nFound on " + body.name + "'s :", Lib.Kolor.Cyan, true);
                            foreach (string biome in body.biomes)
                            {
                                ModuleInfo += "\n- ";
                                ModuleInfo += biome;
                            }
                        }
                    }
                }
#endif


                if (partHasExperimentModule && !ap.name.StartsWith("kerbalEVA"))
                {
                    ap.moduleInfos.Clear();
                    ap.resourceInfos.Clear();
                    try
                    {
                        Lib.ReflectionCall(PartLoader.Instance, "CompilePartInfo", new Type[] { typeof(AvailablePart), typeof(Part) }, new object[] { ap, ap.partPrefab });
                    }
                    catch (Exception ex)
                    {
                        Lib.Log("Could not patch the moduleInfo for part " + ap.name + " - " + ex.Message + "\n" + ex.StackTrace);
                    }
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// If short_strings parameter is true then the strings used for display of the data will be shorter when inflight.
        /// </summary>
        public static void Fileman(this Panel p, Vessel v, bool short_strings = false)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            VesselData vd = v.KerbalismData();

            // if not a valid vessel, leave the panel empty
            if (!vd.IsSimulated)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(40)), " ", Lib.Color(Local.FILEMANAGER_title, Lib.Kolor.LightGrey)));            //"FILE MANAGER"
            p.Width(Styles.ScaleWidthFloat(465.0f));
            p.paneltype = Panel.PanelType.data;

            // time-out simulation
            if (!Lib.IsControlUnit(v) && p.Timeout(vd))
            {
                return;
            }

            List <ObjectPair <uint, Drive> > drives = new List <ObjectPair <uint, Drive> >();

            int    filesCount        = 0;
            double usedDataCapacity  = 0;
            double totalDataCapacity = 0;

            int    samplesCount     = 0;
            int    usedSlots        = 0;
            int    totalSlots       = 0;
            double totalMass        = 0;
            bool   unlimitedData    = false;
            bool   unlimitedSamples = false;

            foreach (PartData partData in vd.PartDatas)
            {
                Drive drive = partData.Drive;
                if (drive == null)
                {
                    continue;
                }

                drives.Add(new ObjectPair <uint, Drive>(partData.FlightId, drive));

                if (!drive.is_private)
                {
                    usedDataCapacity  += drive.FilesSize();
                    totalDataCapacity += drive.dataCapacity;

                    unlimitedData    |= drive.dataCapacity < 0;
                    unlimitedSamples |= drive.sampleCapacity < 0;

                    usedSlots  += drive.SamplesSize();
                    totalSlots += drive.sampleCapacity;
                }

                filesCount   += drive.files.Count;
                samplesCount += drive.samples.Count;
                foreach (var sample in drive.samples.Values)
                {
                    totalMass += sample.mass;
                }
            }

            if (filesCount > 0 || totalDataCapacity > 0)
            {
                var title = Local.FILEMANAGER_DataCapacity + " " + Lib.HumanReadableDataSize(usedDataCapacity);                //"DATA "
                if (!unlimitedData)
                {
                    title += Local.FILEMANAGER_DataAvailable.Format(Lib.HumanReadablePerc((totalDataCapacity - usedDataCapacity) / totalDataCapacity));                                //Lib.BuildString(" (", Lib.HumanReadablePerc((totalDataCapacity - usedDataCapacity) / totalDataCapacity), " available)");
                }
                p.AddSection(title);

                foreach (var drive in drives)
                {
                    foreach (File file in drive.Value.files.Values)
                    {
                        Render_file(p, drive.Key, file, drive.Value, short_strings && Lib.IsFlight(), v);
                    }
                }

                if (filesCount == 0)
                {
                    p.AddContent("<i>" + Local.FILEMANAGER_nofiles + "</i>", string.Empty);                             //no files
                }
            }

            if (samplesCount > 0 || totalSlots > 0)
            {
                var title = Local.FILEMANAGER_SAMPLESMass.Format(Lib.HumanReadableMass(totalMass)) + " " + Lib.HumanReadableSampleSize(usedSlots);                //"SAMPLES " +
                if (totalSlots > 0 && !unlimitedSamples)
                {
                    title += ", " + Lib.HumanReadableSampleSize(totalSlots) + " " + Local.FILEMANAGER_SAMPLESAvailable;                                                    //available
                }
                p.AddSection(title);

                foreach (var drive in drives)
                {
                    foreach (Sample sample in drive.Value.samples.Values)
                    {
                        Render_sample(p, drive.Key, sample, drive.Value, short_strings && Lib.IsFlight());
                    }
                }

                if (samplesCount == 0)
                {
                    p.AddContent("<i>" + Local.FILEMANAGER_nosamples + "</i>", string.Empty);                               //no samples
                }
            }
        }
Exemple #15
0
        public void Update()
        {
            // in flight
            if (Lib.IsFlight())
            {
                Vessel v = FlightGlobals.ActiveVessel;
                if (v == null || EVA.IsDead(v))
                {
                    return;
                }

                // get info from cache
                Vessel_info vi = Cache.VesselInfo(vessel);

                // do nothing if vessel is invalid
                if (!vi.is_valid)
                {
                    return;
                }

                var sampleSize      = (exp.scienceCap * exp.dataScale);
                var recordedPercent = Lib.HumanReadablePerc(dataSampled / sampleSize);
                var eta             = data_rate < double.Epsilon || dataSampled >= sampleSize ? " done" : " T-" + Lib.HumanReadableDuration((sampleSize - dataSampled) / data_rate);

                // update ui
                Events["Toggle"].guiName = Lib.StatusToggle(exp.experimentTitle, !recording ? "stopped"
                                                                            : Lib.Color(issue.Length > 0 ? "#ffff00":"", Lib.HumanReadablePerc(dataSampled / sampleSize) + "..."));
                Events["Toggle"].active = (prepare_cs == null || didPrepare);

                Events["Prepare"].guiName = Lib.BuildString("Prepare <b>", exp.experimentTitle, "</b>");
                Events["Prepare"].active  = !didPrepare && prepare_cs != null && string.IsNullOrEmpty(last_subject_id);

                Events["Reset"].guiName = Lib.BuildString("Reset <b>", exp.experimentTitle, "</b>");
                // we need a reset either if we have recorded data or did a setup
                bool resetActive = sample_mass < float.Epsilon && (reset_cs != null || prepare_cs != null) && !string.IsNullOrEmpty(last_subject_id);
                Events["Reset"].active = resetActive;

                Fields["ExperimentStatus"].guiName   = exp.experimentTitle;
                Fields["ExperimentStatus"].guiActive = true;

                if (issue.Length > 0)
                {
                    ExperimentStatus = Lib.BuildString("<color=#ffff00>", issue, "</color>");
                }
                else if (dataSampled > 0)
                {
                    string a = string.Empty;
                    string b = string.Empty;

                    if (sample_mass < float.Epsilon)
                    {
                        a = Lib.HumanReadableDataSize(dataSampled);
                        b = Lib.HumanReadableDataSize(sampleSize);
                    }
                    else
                    {
                        a = Lib.SampleSizeToSlots(dataSampled).ToString();
                        b = Lib.HumanReadableSampleSize(sampleSize);

                        if (remainingSampleMass > double.Epsilon)
                        {
                            b += " " + Lib.HumanReadableMass(remainingSampleMass) + " left";
                        }
                    }

                    ExperimentStatus = Lib.BuildString(a, "/", b, eta);
                }
                else
                {
                    var size = sample_mass < double.Epsilon ? Lib.HumanReadableDataSize(sampleSize) : Lib.HumanReadableSampleSize(sampleSize);
                    ExperimentStatus = Lib.BuildString("ready ", size, " in ", Lib.HumanReadableDuration(sampleSize / data_rate));
                }
            }
            // in the editor
            else if (Lib.IsEditor())
            {
                // update ui
                Events["Toggle"].guiName = Lib.StatusToggle(exp.experimentTitle, recording ? "recording" : "stopped");
                Events["Reset"].active   = false;
                Events["Prepare"].active = false;
            }
        }
Exemple #16
0
        // specifics support
        public Specifics Specs()
        {
            var specs = new Specifics();
            var exp   = Science.Experiment(experiment_id);

            if (exp == null)
            {
                specs.Add(Localizer.Format("#KERBALISM_ExperimentInfo_Unknown"));
                return(specs);
            }

            specs.Add(Lib.BuildString("<b>", exp.name, "</b>"));
            if (!string.IsNullOrEmpty(experiment_desc))
            {
                specs.Add(Lib.BuildString("<i>", experiment_desc, "</i>"));
            }

            specs.Add(string.Empty);
            double expSize = exp.max_amount;

            if (sample_mass < float.Epsilon)
            {
                specs.Add("Data", Lib.HumanReadableDataSize(expSize));
                specs.Add("Data rate", Lib.HumanReadableDataRate(data_rate));
                specs.Add("Duration", Lib.HumanReadableDuration(expSize / data_rate));
            }
            else
            {
                specs.Add("Sample size", Lib.HumanReadableSampleSize(expSize));
                specs.Add("Sample mass", Lib.HumanReadableMass(sample_mass));
                if (!sample_collecting && Math.Abs(sample_reservoir - sample_mass) > double.Epsilon && sample_mass > double.Epsilon)
                {
                    specs.Add("Experiments", "" + Math.Round(sample_reservoir / sample_mass, 0));
                }
                specs.Add("Duration", Lib.HumanReadableDuration(expSize / data_rate));
            }

            List <string> situations = exp.Situations();

            if (situations.Count > 0)
            {
                specs.Add(string.Empty);
                specs.Add("<color=#00ffff>Situations:</color>", string.Empty);
                foreach (string s in situations)
                {
                    specs.Add(Lib.BuildString("• <b>", s, "</b>"));
                }
            }

            specs.Add(string.Empty);
            specs.Add("<color=#00ffff>Needs:</color>");

            specs.Add("EC", Lib.HumanReadableRate(ec_rate));
            foreach (var p in KerbalismProcess.ParseResources(resources))
            {
                specs.Add(p.Key, Lib.HumanReadableRate(p.Value));
            }

            if (crew_prepare.Length > 0)
            {
                var cs = new CrewSpecs(crew_prepare);
                specs.Add("Preparation", cs ? cs.Info() : "none");
            }
            if (crew_operate.Length > 0)
            {
                var cs = new CrewSpecs(crew_operate);
                specs.Add("Operation", cs ? cs.Info() : "unmanned");
            }
            if (crew_reset.Length > 0)
            {
                var cs = new CrewSpecs(crew_reset);
                specs.Add("Reset", cs ? cs.Info() : "none");
            }

            if (!string.IsNullOrEmpty(requires))
            {
                specs.Add(string.Empty);
                specs.Add("<color=#00ffff>Requires:</color>", string.Empty);
                var tokens = Lib.Tokenize(requires, ',');
                foreach (string s in tokens)
                {
                    specs.Add(Lib.BuildString("• <b>", Science.RequirementText(s), "</b>"));
                }
            }

            return(specs);
        }
Exemple #17
0
        // specifics support
        public Specifics Specs()
        {
            Specifics specs = new Specifics();

            if (redundancy.Length > 0)
            {
                specs.Add("Redundancy", redundancy);
            }
            specs.Add("Repair", new CrewSpecs(repair).Info());



            specs.Add(string.Empty);
            specs.Add("<color=#00ffff>Standard quality</color>");
            if (mtbf > 0)
            {
                specs.Add("MTBF", Lib.HumanReadableDuration(EffectiveMTBF(false, mtbf)));
            }
            if (turnon_failure_probability > 0)
            {
                specs.Add("Ignition failures", Lib.HumanReadablePerc(turnon_failure_probability, "F1"));
            }
            if (rated_operation_duration > 0)
            {
                specs.Add("Rated burn duration", Lib.HumanReadableDuration(EffectiveDuration(false, rated_operation_duration)));
            }
            if (rated_ignitions > 0)
            {
                specs.Add("Rated ignitions", EffectiveIgnitions(false, rated_ignitions).ToString());
            }
            if (mtbf > 0 && rated_radiation > 0)
            {
                specs.Add("Radiation rating", Lib.HumanReadableRadiation(rated_radiation / 3600.0));
            }

            specs.Add(string.Empty);
            specs.Add("<color=#00ffff>High quality</color>");
            if (extra_cost > double.Epsilon)
            {
                specs.Add("Extra cost", Lib.HumanReadableCost(extra_cost * part.partInfo.cost));
            }
            if (extra_mass > double.Epsilon)
            {
                specs.Add("Extra mass", Lib.HumanReadableMass(extra_mass * part.partInfo.partPrefab.mass));
            }
            if (mtbf > 0)
            {
                specs.Add("MTBF", Lib.HumanReadableDuration(EffectiveMTBF(true, mtbf)));
            }
            if (turnon_failure_probability > 0)
            {
                specs.Add("Ignition failures", Lib.HumanReadablePerc(turnon_failure_probability / Settings.QualityScale, "F1"));
            }
            if (rated_operation_duration > 0)
            {
                specs.Add("Rated burn duration", Lib.HumanReadableDuration(EffectiveDuration(true, rated_operation_duration)));
            }
            if (rated_ignitions > 0)
            {
                specs.Add("Rated ignitions", EffectiveIgnitions(true, rated_ignitions).ToString());
            }
            if (mtbf > 0 && rated_radiation > 0)
            {
                specs.Add("Radiation rating", Lib.HumanReadableRadiation(Settings.QualityScale * rated_radiation / 3600.0));
            }

            return(specs);
        }