Exemple #1
0
        // analyze a sample
        private static void Analyze(Vessel v, string filename, double amount)
        {
            // get vessel drive
            Drive drive = DB.Vessel(v).drive;

            // get sample
            Sample sample = drive.samples[filename];

            // analyze, and produce data
            amount = Math.Min(amount, sample.size);
            bool completed = amount >= sample.size - double.Epsilon;

            drive.Delete_sample(filename, amount);
            drive.Record_file(filename, amount);

            // if the analysis is completed
            if (completed)
            {
                // inform the user
                Message.Post(Lib.BuildString(Lib.Color("cyan", Localizer.Format("#KERBALISM_Laboratory_Analysis"), true), "\n",
                                             Localizer.Format("#KERBALISM_Laboratory_Analyzed", Lib.Bold(v.vesselName), Lib.Bold(Science.Experiment(filename).name))), localized_results);

                // record landmark event
                if (!Lib.Landed(v))
                {
                    DB.landmarks.space_analysis = true;
                }
            }
        }
Exemple #2
0
        void Start()
        {
            // get dialog
            dialog = gameObject.GetComponentInParent <ExperimentsResultDialog>();
            if (dialog == null)
            {
                Destroy(gameObject); return;
            }

            // prevent rendering
            dialog.gameObject.SetActive(false);

            // for each page
            // - some mod may collect multiple experiments at once
            while (dialog.pages.Count > 0)
            {
                // get page
                var page = dialog.pages[0];

                // get science data
                ScienceData data = page.pageData;

                // collect and deduce all info necessary
                MetaData meta = new MetaData(data, page.host);

                // record data in the drive
                Drive drive = DB.Vessel(meta.vessel).drive;
                if (!meta.is_sample)
                {
                    drive.Record_file(data.subjectID, data.dataAmount);
                }
                else
                {
                    drive.Record_sample(data.subjectID, data.dataAmount);
                }

                // render experiment inoperable if necessary
                if (!meta.is_rerunnable)
                {
                    meta.experiment.SetInoperable();
                }

                // dump the data
                page.OnDiscardData(data);

                // inform the user
                Message.Post
                (
                    Lib.BuildString("<b>", Science.Experiment(data.subjectID).fullname, "</b> recorded"),
                    !meta.is_rerunnable ? Localizer.Format("#KERBALISM_Science_inoperable") : string.Empty
                );
            }

            // dismiss the dialog
            dialog.Dismiss();
        }
Exemple #3
0
        // store a file on a vessel
        public static void StoreFile(Vessel v, string subject_id, double amount)
        {
            if (!Cache.VesselInfo(v).is_valid)
            {
                return;
            }
            Drive drive = DB.Vessel(v).drive;

            drive.Record_file(subject_id, amount);
        }
Exemple #4
0
        void Record(MetaData meta, ScienceData data, bool send)
        {
            // if amount is zero, warn the user and do nothing else
            if (data.dataAmount <= double.Epsilon)
            {
                Message.Post("There is no more useful data here");
                return;
            }

            // if this is a sample and we are trying to send it, warn the user and do nothing else
            if (meta.is_sample && send)
            {
                Message.Post("We can't transmit a sample", "It needs to be recovered, or analyzed in a lab");
                return;
            }

            // record data in the drive
            Drive drive = DB.Vessel(meta.vessel).drive;

            if (!meta.is_sample)
            {
                drive.Record_file(data.subjectID, data.dataAmount);
            }
            else
            {
                drive.Record_sample(data.subjectID, data.dataAmount);
            }

            // flag for sending if specified
            if (!meta.is_sample && send)
            {
                drive.Send(data.subjectID, true);
            }

            // render experiment inoperable if necessary
            if (!meta.is_rerunnable)
            {
                meta.experiment.SetInoperable();
            }

            // dismiss the dialog and popups
            Dismiss(data);

            // inform the user
            Message.Post
            (
                Lib.BuildString("<b>", Science.Experiment(data.subjectID).fullname, "</b> recorded"),
                !meta.is_rerunnable ? Localizer.Format("#KERBALISM_Science_inoperable") : string.Empty
            );
        }
Exemple #5
0
        // move all data to another drive
        public bool Move(Drive destination, bool moveSamples = false)
        {
            bool result = true;

            // copy files
            var filesList = new List <string>();

            foreach (var p in files)
            {
                if (destination.Record_file(p.Key, p.Value.size))
                {
                    destination.files[p.Key].buff += p.Value.buff;                     //< move the buffer along with the size
                    filesList.Add(p.Key);
                }
                else
                {
                    result = false;
                }
            }
            foreach (var id in filesList)
            {
                files.Remove(id);
            }

            if (moveSamples)
            {
                // copy samples
                var samplesList = new List <string>();
                foreach (var p in samples)
                {
                    if (destination.Record_sample(p.Key, p.Value.size, p.Value.mass))
                    {
                        samplesList.Add(p.Key);
                    }
                    else
                    {
                        result = false;
                    }
                }
                foreach (var id in samplesList)
                {
                    samples.Remove(id);
                }
            }

            return(result);            // true if everything was moved, false otherwise
        }
Exemple #6
0
        // TODO do something about limited capacity...
        // EVAs returning should get a warning if needed
        // TODO : this should not be used for EVA boarding, too much information is lost in the conversion
        public void ReturnData(ScienceData data)
        {
            SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(data.subjectID);

            if (subjectData == null)
            {
                return;
            }

            if (data.baseTransmitValue > Science.maxXmitDataScalarForSample || data.transmitBonus > Science.maxXmitDataScalarForSample)
            {
                drive.Record_file(subjectData, data.dataAmount);
            }
            else
            {
                drive.Record_sample(subjectData, data.dataAmount, subjectData.ExpInfo.MassPerMB * data.dataAmount);
            }
        }
Exemple #7
0
        // TODO do something about limited capacity...
        // EVAs returning should get a warning if needed
        public void ReturnData(ScienceData data)
        {
            // store the data
            bool result = false;

            if (data.baseTransmitValue > float.Epsilon || data.transmitBonus > double.Epsilon)
            {
                result = drive.Record_file(data.subjectID, data.dataAmount);
            }
            else
            {
                var experimentInfo = Science.Experiment(data.subjectID);
                var sampleMass     = Science.GetSampleMass(data.subjectID);
                var mass           = sampleMass / experimentInfo.max_amount * data.dataAmount;

                result = drive.Record_sample(data.subjectID, data.dataAmount, mass);
            }
        }
Exemple #8
0
        // move all data to another drive
        public void Move(Drive destination)
        {
            // copy files
            foreach (var p in files)
            {
                destination.Record_file(p.Key, p.Value.size);
                destination.files[p.Key].buff += p.Value.buff;                 //< move the buffer along with the size
            }

            // copy samples
            foreach (var p in samples)
            {
                destination.Record_sample(p.Key, p.Value.size);
            }

            // clear source drive
            files.Clear();
            samples.Clear();
        }
Exemple #9
0
        public void ReturnData(ScienceData data)
        {
            // get drive
            Drive drive = DB.Vessel(vessel).drive;

            // if not the preferred drive
            if (drive.location != part.flightID)
            {
                return;
            }

            // store the data
            if (data.baseTransmitValue > float.Epsilon || data.transmitBonus > double.Epsilon)
            {
                drive.Record_file(data.subjectID, data.dataAmount);
            }
            else
            {
                drive.Record_sample(data.subjectID, data.dataAmount);
            }
        }
Exemple #10
0
        private static bool DoRecord(Experiment experiment, string subject_id, Vessel vessel, Resource_info ec, uint hdId,
                                     Vessel_resources resources, List <KeyValuePair <string, double> > resourceDefs,
                                     double remainingSampleMass, double dataSampled,
                                     out double sampledOut, out double remainingSampleMassOut)
        {
            // default output values for early returns
            sampledOut             = dataSampled;
            remainingSampleMassOut = remainingSampleMass;

            var exp = Science.Experiment(subject_id);

            if (Done(exp, dataSampled))
            {
                return(true);
            }

            double elapsed   = Kerbalism.elapsed_s;
            double chunkSize = Math.Min(experiment.data_rate * elapsed, exp.max_amount);
            double massDelta = experiment.sample_mass * chunkSize / exp.max_amount;

            Drive drive = GetDrive(experiment, vessel, hdId, chunkSize, subject_id);

            // on high time warp this chunk size could be too big, but we could store a sizable amount if we process less
            bool   isFile      = experiment.sample_mass < float.Epsilon;
            double maxCapacity = isFile ? drive.FileCapacityAvailable() : drive.SampleCapacityAvailable(subject_id);

            Drive warpCacheDrive = null;

            if (isFile)
            {
                if (drive.GetFileSend(subject_id))
                {
                    warpCacheDrive = Cache.WarpCache(vessel);
                }
                if (warpCacheDrive != null)
                {
                    maxCapacity += warpCacheDrive.FileCapacityAvailable();
                }
            }

            double factor = Rate(vessel, chunkSize, maxCapacity, elapsed, ec, experiment.ec_rate, resources, resourceDefs);

            if (factor < double.Epsilon)
            {
                return(false);
            }

            chunkSize *= factor;
            massDelta *= factor;
            elapsed   *= factor;

            bool stored = false;

            if (chunkSize > double.Epsilon)
            {
                if (isFile)
                {
                    if (warpCacheDrive != null)
                    {
                        double s = Math.Min(chunkSize, warpCacheDrive.FileCapacityAvailable());
                        stored = warpCacheDrive.Record_file(subject_id, s, true);

                        if (chunkSize > s)                        // only write to persisted drive if the data cannot be transmitted in this tick
                        {
                            stored &= drive.Record_file(subject_id, chunkSize - s, true);
                        }
                    }
                    else
                    {
                        stored = drive.Record_file(subject_id, chunkSize, true);
                    }
                }
                else
                {
                    stored = drive.Record_sample(subject_id, chunkSize, massDelta);
                }
            }

            if (!stored)
            {
                return(false);
            }

            // consume resources
            ec.Consume(experiment.ec_rate * elapsed, "experiment");
            foreach (var p in resourceDefs)
            {
                resources.Consume(vessel, p.Key, p.Value * elapsed, "experiment");
            }

            dataSampled += chunkSize;
            dataSampled  = Math.Min(dataSampled, exp.max_amount);
            sampledOut   = dataSampled;
            if (!experiment.sample_collecting)
            {
                remainingSampleMass -= massDelta;
                remainingSampleMass  = Math.Max(remainingSampleMass, 0);
            }
            remainingSampleMassOut = remainingSampleMass;
            return(true);
        }
Exemple #11
0
        // analyze a sample
        private static Status Analyze(Vessel v, SubjectData subject, double amount)
        {
            Sample sample      = null;
            Drive  sampleDrive = null;

            foreach (var d in Drive.GetDrives(v, true))
            {
                if (d.samples.ContainsKey(subject) && d.samples[subject].analyze)
                {
                    sample      = d.samples[subject];
                    sampleDrive = d;
                    break;
                }
            }

            bool completed = false;

            if (sample != null)
            {
                completed = amount > sample.size;
                amount    = Math.Min(amount, sample.size);
            }

            Drive fileDrive = Drive.FileDrive(v.KerbalismData(), amount);

            if (fileDrive == null)
            {
                return(Status.NO_STORAGE);
            }

            if (sample != null)
            {
                bool recorded = fileDrive.Record_file(subject, amount, false);

                double massRemoved = 0.0;
                if (recorded)
                {
                    massRemoved = sampleDrive.Delete_sample(subject, amount);
                }
                else
                {
                    Message.Post(
                        Lib.Color(Lib.BuildString(Localizer.Format("#KERBALISM_Laboratory_Analysis"), " stopped"), Lib.Kolor.Red),
                        "Not enough space on hard drive"
                        );

                    return(Status.NO_STORAGE);
                }

                // return sample mass to experiment if needed
                if (massRemoved > 0.0)
                {
                    RestoreSampleMass(v, subject, massRemoved);
                }
            }

            // if the analysis is completed
            if (completed)
            {
                if (!PreferencesScience.Instance.analyzeSamples)
                {
                    // only inform the user if auto-analyze is turned off
                    // otherwise we could be spamming "Analysis complete" messages
                    Message.Post(Lib.BuildString(Lib.Color(Localizer.Format("#KERBALISM_Laboratory_Analysis"), Lib.Kolor.Science, true), "\n",
                                                 Localizer.Format("#KERBALISM_Laboratory_Analyzed", Lib.Bold(v.vesselName), Lib.Bold(subject.FullTitle))), localized_results);
                }

                if (PreferencesScience.Instance.transmitScience)
                {
                    fileDrive.Send(subject.Id, true);
                }

                // record landmark event
                if (!Lib.Landed(v))
                {
                    DB.landmarks.space_analysis = true;
                }
            }

            return(Status.RUNNING);
        }
Exemple #12
0
        private static bool DoRecord(Experiment experiment, string subject_id, Vessel vessel, Resource_info ec, uint hdId,
                                     Vessel_resources resources, List <KeyValuePair <string, double> > resourceDefs,
                                     double remainingSampleMass, double dataSampled,
                                     out double sampledOut, out double remainingSampleMassOut)
        {
            var exp = Science.Experiment(subject_id);

            if (Done(exp, dataSampled))
            {
                sampledOut             = dataSampled;
                remainingSampleMassOut = remainingSampleMass;
                return(true);
            }

            double elapsed   = Kerbalism.elapsed_s;
            double chunkSize = Math.Min(experiment.data_rate * elapsed, exp.max_amount);
            double massDelta = experiment.sample_mass * chunkSize / exp.max_amount;

            Drive drive = GetDrive(experiment, vessel, hdId, chunkSize, subject_id);

            // on high time warp this chunk size could be too big, but we could store a sizable amount if we process less
            bool   isFile      = experiment.sample_mass < float.Epsilon;
            double maxCapacity = isFile ? drive.FileCapacityAvailable() : drive.SampleCapacityAvailable(subject_id);

            if (maxCapacity < chunkSize)
            {
                double factor = maxCapacity / chunkSize;
                chunkSize *= factor;
                massDelta *= factor;
                elapsed   *= factor;
            }

            foreach (var p in resourceDefs)
            {
                resources.Consume(vessel, p.Key, p.Value * elapsed, "experiment");
            }

            bool stored = false;

            if (isFile)
            {
                stored = drive.Record_file(subject_id, chunkSize, true);
            }
            else
            {
                stored = drive.Record_sample(subject_id, chunkSize, massDelta);
            }

            if (stored)
            {
                // consume ec
                ec.Consume(experiment.ec_rate * elapsed, "experiment");
                dataSampled += chunkSize;
                dataSampled  = Math.Min(dataSampled, exp.max_amount);
                sampledOut   = dataSampled;
                if (!experiment.sample_collecting)
                {
                    remainingSampleMass -= massDelta;
                    remainingSampleMass  = Math.Max(remainingSampleMass, 0);
                }
                remainingSampleMassOut = remainingSampleMass;
                return(true);
            }

            sampledOut             = dataSampled;
            remainingSampleMassOut = remainingSampleMass;
            return(false);
        }
Exemple #13
0
        void Record(MetaData meta, ScienceData data, bool send)
        {
            // if amount is zero, warn the user and do nothing else
            if (data.dataAmount <= double.Epsilon)
            {
                Message.Post("There is no more useful data here");
                return;
            }

            // if this is a sample and we are trying to send it, warn the user and do nothing else
            if (meta.is_sample && send)
            {
                Message.Post("We can't transmit a sample", "It needs to be recovered, or analyzed in a lab");
                return;
            }

            // record data in the drive
            bool recorded = false;

            if (!meta.is_sample)
            {
                Drive drive = Drive.FileDrive(meta.vessel, data.dataAmount);
                recorded = drive.Record_file(data.subjectID, data.dataAmount);
            }
            else
            {
                Drive drive = Drive.SampleDrive(meta.vessel, data.dataAmount, data.subjectID);

                var experimentInfo = Science.Experiment(data.subjectID);
                var sampleMass     = Science.GetSampleMass(data.subjectID);
                var mass           = sampleMass / experimentInfo.max_amount * data.dataAmount;

                recorded = drive.Record_sample(data.subjectID, data.dataAmount, mass);
            }

            if (recorded)
            {
                // flag for sending if specified
                if (!meta.is_sample && send)
                {
                    foreach (var d in Drive.GetDrives(meta.vessel))
                    {
                        d.Send(data.subjectID, true);
                    }
                }

                // render experiment inoperable if necessary
                if (!meta.is_rerunnable)
                {
                    meta.experiment.SetInoperable();
                }

                // dismiss the dialog and popups
                Dismiss(data);

                var exp = Science.Experiment(data.subjectID);
                // inform the user
                Message.Post(
                    Lib.BuildString("<b>", exp.FullName(data.subjectID), "</b> recorded"),
                    !meta.is_rerunnable ? Localizer.Format("#KERBALISM_Science_inoperable") : string.Empty
                    );
            }
            else
            {
                var exp = Science.Experiment(data.subjectID);
                Message.Post(
                    Lib.Color("red", Lib.BuildString(exp.FullName(data.subjectID), " can not be stored")),
                    "Not enough space on hard drive"
                    );
            }
        }
Exemple #14
0
        void Start()
        {
            // get dialog
            dialog = gameObject.GetComponentInParent <ExperimentsResultDialog>();
            if (dialog == null)
            {
                Destroy(gameObject); return;
            }

            // prevent rendering
            dialog.gameObject.SetActive(false);

            // for each page
            // - some mod may collect multiple experiments at once
            while (dialog.pages.Count > 0)
            {
                // get page
                var page = dialog.pages[0];

                // get science data
                ScienceData data = page.pageData;

                // collect and deduce all info necessary
                MetaData meta = new MetaData(data, page.host);

                // ignore non-collectable experiments
                if (!meta.is_collectable)
                {
                    page.OnKeepData(data);
                    continue;
                }

                // record data
                bool recorded = false;
                if (!meta.is_sample)
                {
                    Drive drive = Drive.FileDrive(meta.vessel, data.dataAmount);
                    recorded = drive.Record_file(data.subjectID, data.dataAmount);
                }
                else
                {
                    Drive drive = Drive.SampleDrive(meta.vessel, data.dataAmount, data.subjectID);

                    var experimentInfo = Science.Experiment(data.subjectID);
                    var sampleMass     = Science.GetSampleMass(data.subjectID);
                    var mass           = sampleMass / experimentInfo.max_amount * data.dataAmount;

                    recorded = drive.Record_sample(data.subjectID, data.dataAmount, mass);
                }

                if (recorded)
                {
                    // render experiment inoperable if necessary
                    if (!meta.is_rerunnable)
                    {
                        meta.experiment.SetInoperable();
                    }

                    // dump the data
                    page.OnDiscardData(data);

                    // inform the user
                    var exp = Science.Experiment(data.subjectID);
                    Message.Post(
                        Lib.BuildString("<b>", exp.FullName(data.subjectID), "</b> recorded"),
                        !meta.is_rerunnable ? Localizer.Format("#KERBALISM_Science_inoperable") : string.Empty
                        );
                }
                else
                {
                    var exp = Science.Experiment(data.subjectID);
                    Message.Post(
                        Lib.Color("red", Lib.BuildString(exp.FullName(data.subjectID), " can not be stored")),
                        "Not enough space on hard drive"
                        );
                }
            }

            // dismiss the dialog
            dialog.Dismiss();
        }
Exemple #15
0
        // move all data to another drive
        public bool Move(Drive destination, bool moveSamples)
        {
            bool result = true;

            // copy files
            List <SubjectData> filesList = new List <SubjectData>();

            foreach (File file in files.Values)
            {
                double size = Math.Min(file.size, destination.FileCapacityAvailable());
                if (destination.Record_file(file.subjectData, size, true, file.useStockCrediting))
                {
                    file.size -= size;
                    file.subjectData.RemoveDataCollectedInFlight(size);
                    if (file.size < double.Epsilon)
                    {
                        filesList.Add(file.subjectData);
                    }
                    else
                    {
                        result = false;
                        break;
                    }
                }
                else
                {
                    result = false;
                    break;
                }
            }
            foreach (SubjectData id in filesList)
            {
                files.Remove(id);
            }

            if (!moveSamples)
            {
                return(result);
            }

            // move samples
            List <SubjectData> samplesList = new List <SubjectData>();

            foreach (Sample sample in samples.Values)
            {
                double size = Math.Min(sample.size, destination.SampleCapacityAvailable(sample.subjectData));
                if (size < double.Epsilon)
                {
                    result = false;
                    break;
                }

                double mass = sample.mass * (sample.size / size);
                if (destination.Record_sample(sample.subjectData, size, mass, sample.useStockCrediting))
                {
                    sample.size -= size;
                    sample.subjectData.RemoveDataCollectedInFlight(size);
                    sample.mass -= mass;

                    if (sample.size < double.Epsilon)
                    {
                        samplesList.Add(sample.subjectData);
                    }
                    else
                    {
                        result = false;
                        break;
                    }
                }
                else
                {
                    result = false;
                    break;
                }
            }
            foreach (var id in samplesList)
            {
                samples.Remove(id);
            }

            return(result);            // true if everything was moved, false otherwise
        }
Exemple #16
0
        // move all data to another drive
        public bool Move(Drive destination, bool moveSamples)
        {
            bool result = true;

            // copy files
            var filesList = new List <string>();

            foreach (var p in files)
            {
                double size = Math.Min(p.Value.size, destination.FileCapacityAvailable());
                if (destination.Record_file(p.Key, size, true))
                {
                    destination.files[p.Key].buff += p.Value.buff;                     //< move the buffer along with the size
                    p.Value.buff  = 0;
                    p.Value.size -= size;
                    if (p.Value.size < double.Epsilon)
                    {
                        filesList.Add(p.Key);
                    }
                    else
                    {
                        result = false;
                        break;
                    }
                }
                else
                {
                    result = false;
                    break;
                }
            }
            foreach (var id in filesList)
            {
                files.Remove(id);
            }

            if (!moveSamples)
            {
                return(result);
            }

            // move samples
            var samplesList = new List <string>();

            foreach (var p in samples)
            {
                double size = Math.Min(p.Value.size, destination.SampleCapacityAvailable(p.Key));
                if (size < double.Epsilon)
                {
                    result = false;
                    break;
                }

                double mass = p.Value.mass * (p.Value.size / size);
                if (destination.Record_sample(p.Key, size, mass))
                {
                    p.Value.size -= size;
                    p.Value.mass -= mass;
                    p.Value.size  = Math.Max(0, p.Value.size);
                    p.Value.mass  = Math.Max(0, p.Value.mass);

                    if (p.Value.size < double.Epsilon)
                    {
                        samplesList.Add(p.Key);
                    }
                    else
                    {
                        result = false;
                        break;
                    }
                }
                else
                {
                    result = false;
                    break;
                }
            }
            foreach (var id in samplesList)
            {
                samples.Remove(id);
            }

            return(result);            // true if everything was moved, false otherwise
        }