Example #1
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();
        }
Example #2
0
        // store a sample on a vessel
        public static void StoreSample(Vessel v, string subject_id, double amount)
        {
            if (!Cache.VesselInfo(v).is_valid)
            {
                return;
            }
            Drive drive = DB.Vessel(v).drive;

            drive.Record_sample(subject_id, amount);
        }
Example #3
0
        static bool Prefix(ModuleComet __instance, ref ScienceExperiment ___experiment)
        {
            // Patch only if science is enabled
            if (!Features.Science)
            {
                return(true);
            }

            // stock ModuleAsteroid.performSampleExperiment code : get situation and check availablility
            ExperimentSituations experimentSituation = ScienceUtil.GetExperimentSituation(__instance.vessel);
            string message = string.Empty;

            if (!ScienceUtil.RequiredUsageExternalAvailable(__instance.vessel, FlightGlobals.ActiveVessel, (ExperimentUsageReqs)__instance.experimentUsageMask, ___experiment, ref message))
            {
                ScreenMessages.PostScreenMessage("<b><color=orange>" + message + "</color></b>", 6f, ScreenMessageStyle.UPPER_LEFT);
                return(false);
            }

            if (!___experiment.IsAvailableWhile(experimentSituation, __instance.vessel.mainBody))
            {
                ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_230133", ___experiment.experimentTitle), 5f, ScreenMessageStyle.UPPER_CENTER);
                return(false);
            }

            // stock ModuleAsteroid.performSampleExperiment code : create subject
            ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(___experiment, experimentSituation, __instance.part.partInfo.name + __instance.part.flightID, __instance.part.partInfo.title, __instance.vessel.mainBody, string.Empty, string.Empty);

            // put the data on the EVA kerbal drive.
            if (FlightGlobals.ActiveVessel == null)
            {
                return(false);
            }
            double size  = ___experiment.baseValue * ___experiment.dataScale;
            Drive  drive = Drive.SampleDrive(FlightGlobals.ActiveVessel.KerbalismData(), size);

            if (drive != null)
            {
                double      mass        = size * Settings.AsteroidSampleMassPerMB;
                SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(subject.id, null, __instance.part.partInfo.title);
                drive.Record_sample(subjectData, size, mass, true);
                Message.Post(Lib.BuildString("<b><color=ffffff>", subject.title, "</color></b>\n", (mass * 1000.0).ToString("F1"), "<b><i> Kg of sample stored</i></b>"));
            }
            else
            {
                Message.Post("Not enough sample storage available");
            }

            // don't call TakeSampleEVAEvent() (this will also prevent the call to ModuleAsteroid.performSampleExperiment)
            return(false);
        }
Example #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
            );
        }
Example #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
        }
Example #6
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);
            }
        }
Example #7
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);
            }
        }
Example #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();
        }
Example #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);
            }
        }
Example #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)
        {
            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);
        }
Example #11
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();
        }
Example #12
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
        }
Example #13
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
        }
Example #14
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 (meta.subjectData == null)
            {
                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;
            bool partial_record = false;

            if (!meta.is_sample)
            {
                var remaining = MiniHijacker.RecordData(data, meta);
                if (remaining > 0)
                {
                    partial_record = true;
                }
                recorded = remaining < data.dataAmount;
            }
            else
            {
                Drive drive = Drive.SampleDrive(meta.vessel.KerbalismData(), data.dataAmount, meta.subjectData);
                if (drive != null)
                {
                    recorded = drive.Record_sample(meta.subjectData, data.dataAmount, meta.subjectData.ExpInfo.MassPerMB * data.dataAmount, true);
                }
            }

            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 && !partial_record)
                {
                    meta.experiment.SetInoperable();
                }

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

                if (!partial_record)
                {
                    // inform the user
                    Message.Post(
                        Lib.BuildString("<b>", meta.subjectData.FullTitle, "</b> recorded"),
                        !meta.is_rerunnable ? Local.Science_inoperable : string.Empty
                        );
                }
            }
            else
            {
                Message.Post(
                    Lib.Color(Lib.BuildString(meta.subjectData.FullTitle, " can not be stored"), Lib.Kolor.Red),
                    "Not enough space on hard drive"
                    );
            }
        }
Example #15
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, page.xmitDataScalar);

                if (meta.subjectData == null)
                {
                    continue;
                }

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

                bool recorded       = false;
                bool partial_record = false;

                if (!meta.is_sample)
                {
                    var remaining = RecordData(data, meta);
                    if (remaining > 0)
                    {
                        partial_record = true;
                    }
                    recorded = remaining < data.dataAmount;
                }
                else
                {
                    Drive drive = Drive.SampleDrive(meta.vessel.KerbalismData(), data.dataAmount, meta.subjectData);
                    if (drive != null)
                    {
                        recorded = drive.Record_sample(meta.subjectData, data.dataAmount, meta.subjectData.ExpInfo.MassPerMB * data.dataAmount, true);
                    }
                }

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

                        // inform the user
                        Message.Post(
                            Lib.BuildString("<b>", meta.subjectData.FullTitle, "</b> recorded"),
                            !meta.is_rerunnable ? Local.Science_inoperable : string.Empty
                            );
                    }

                    // dump the data
                    page.OnDiscardData(data);
                }
                else
                {
                    Message.Post(
                        Lib.Color(Lib.BuildString(meta.subjectData.FullTitle, " can not be stored"), Lib.Kolor.Red),
                        "Not enough space on hard drive"
                        );
                }
            }

            // dismiss the dialog
            dialog.Dismiss();
        }
Example #16
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);
        }
Example #17
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"
                    );
            }
        }