public static IVesselRelayPersistence GetVesselRelayPersistenceForProtoVessel(Vessel vessel)
        {
            var relayVessel = new VesselRelayPersistence(vessel);
            int totalCount  = 0;

            double totalDiameter          = 0;
            double totalAperture          = 0;
            double totalPowerCapacity     = 0;
            double minimumRelayWavelength = 1;
            double maximumRelayWavelenght = 0;

            foreach (var protoPart in vessel.protoVessel.protoPartSnapshots)
            {
                foreach (var protoModule in protoPart.modules)
                {
                    if (protoModule.moduleName != "MicrowavePowerTransmitter" && protoModule.moduleName != "PhasedArrayTransmitter" && protoModule.moduleName != "BeamedPowerLaserTransmitter")
                    {
                        continue;
                    }

                    bool inRelayMode = bool.Parse(protoModule.moduleValues.GetValue("relay"));

                    bool isMergingBeams = false;
                    if (protoModule.moduleValues.HasValue("mergingBeams"))
                    {
                        isMergingBeams = bool.Parse(protoModule.moduleValues.GetValue("mergingBeams"));
                    }

                    // filter on transmitters
                    if (inRelayMode || isMergingBeams)
                    {
                        var wavelength    = double.Parse(protoModule.moduleValues.GetValue("wavelength"));
                        var isMirror      = bool.Parse(protoModule.moduleValues.GetValue("isMirror"));
                        var aperture      = double.Parse(protoModule.moduleValues.GetValue("aperture"));
                        var powerCapacity = double.Parse(protoModule.moduleValues.GetValue("power_capacity"));

                        var diameter = protoModule.moduleValues.HasValue("diameter") ? double.Parse(protoModule.moduleValues.GetValue("diameter")) : aperture;

                        totalCount++;
                        totalAperture      += aperture;
                        totalDiameter      += diameter;
                        totalPowerCapacity += powerCapacity;

                        var relayWavelenghtMin = double.Parse(protoModule.moduleValues.GetValue("minimumRelayWavelenght"));
                        if (relayWavelenghtMin < minimumRelayWavelength)
                        {
                            minimumRelayWavelength = relayWavelenghtMin;
                        }

                        var relayWavelenghtMax = double.Parse(protoModule.moduleValues.GetValue("maximumRelayWavelenght"));
                        if (relayWavelenghtMax > maximumRelayWavelenght)
                        {
                            maximumRelayWavelenght = relayWavelenghtMax;
                        }

                        var relayData = relayVessel.SupportedTransmitWavelengths.FirstOrDefault(m => m.wavelength == wavelength);
                        if (relayData == null)
                        {
                            string partId = protoModule.moduleValues.GetValue("partId");

                            relayVessel.SupportedTransmitWavelengths.Add(new WaveLengthData()
                            {
                                partId                = new Guid(partId),
                                count                 = 1,
                                apertureSum           = aperture,
                                powerCapacity         = powerCapacity,
                                wavelength            = wavelength,
                                minWavelength         = relayWavelenghtMin,
                                maxWavelength         = relayWavelenghtMax,
                                isMirror              = isMirror,
                                atmosphericAbsorption = double.Parse(protoModule.moduleValues.GetValue("atmosphericAbsorption"))
                            });
                        }
                        else
                        {
                            relayData.count++;
                            relayData.apertureSum   += aperture;
                            relayData.powerCapacity += powerCapacity;
                        }
                    }
                }
            }

            relayVessel.Aperture               = (totalAperture / totalCount) * Approximate.Sqrt(totalCount);
            relayVessel.Diameter               = totalDiameter / totalCount;
            relayVessel.PowerCapacity          = totalPowerCapacity;
            relayVessel.IsActive               = totalCount > 0;
            relayVessel.MinimumRelayWavelenght = minimumRelayWavelength;
            relayVessel.MaximumRelayWavelenght = maximumRelayWavelenght;

            return(relayVessel);
        }
        public static IVesselRelayPersistence getVesselRelayPersistenceForVessel(Vessel vessel)
        {
            // find all active tranmitters configured for relay
            var relays = vessel.FindPartModulesImplementing <BeamedPowerTransmitter>().Where(m => m.IsRelay || m.mergingBeams).ToList();

            if (relays.Count == 0)
            {
                return(null);
            }

            var relayPersistance = new VesselRelayPersistence(vessel);

            relayPersistance.IsActive = true;

            if (relayPersistance.IsActive)
            {
                return(relayPersistance);
            }

            foreach (var relay in relays)
            {
                var transmitData = relayPersistance.SupportedTransmitWavelengths.FirstOrDefault(m => m.wavelength == relay.wavelength);
                if (transmitData == null)
                {
                    // Add guid if missing
                    relay.partId = string.IsNullOrEmpty(relay.partId)
                        ? Guid.NewGuid().ToString()
                        : relay.partId;

                    relayPersistance.SupportedTransmitWavelengths.Add(new WaveLengthData()
                    {
                        partId                = new Guid(relay.partId),
                        count                 = 1,
                        apertureSum           = relay.aperture,
                        powerCapacity         = relay.power_capacity,
                        wavelength            = relay.Wavelength,
                        minWavelength         = relay.minimumRelayWavelenght,
                        maxWavelength         = relay.maximumRelayWavelenght,
                        isMirror              = relay.isMirror,
                        atmosphericAbsorption = relay.CombinedAtmosphericAbsorption
                    });
                }
                else
                {
                    transmitData.count++;
                    transmitData.apertureSum   += relay.aperture;
                    transmitData.powerCapacity += relay.power_capacity;
                }
            }

            relayPersistance.Aperture               = relays.Average(m => m.aperture) * Approximate.Sqrt(relays.Count);
            relayPersistance.Diameter               = relays.Average(m => m.diameter);
            relayPersistance.PowerCapacity          = relays.Sum(m => m.getPowerCapacity());
            relayPersistance.MinimumRelayWavelenght = relays.Min(m => m.minimumRelayWavelenght);
            relayPersistance.MaximumRelayWavelenght = relays.Max(m => m.maximumRelayWavelenght);

            return(relayPersistance);
        }