// 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; } } }
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(); }
// 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); }
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 ); }
// 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 }
// 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); } }
// 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); } }
// 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(); }
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); } }
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); }
// 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); }
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); }
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" ); } }
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(); }
// 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 }
// 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 }