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