Esempio n. 1
0
        public static AntennasByFrequency GetNodeAntennaCache(CommNode node, short freq)
        {
            AntennasByFrequency node_Antennas;

            if (node.isHome)
            {
                node_Antennas = new AntennasByFrequency()
                {
                    antennaPower = node.antennaTransmit.power,
                    relayPower   = node.antennaRelay.power
                };
            }
            else
            {
                Vessel v = FindCorrespondingVessel(node);
                if (AntennaInfo(v).antennasByFreq.Keys.Contains(freq))
                {
                    node_Antennas = AntennaInfo(v).antennasByFreq[freq];
                }
                else
                {
                    node_Antennas = new AntennasByFrequency()
                    {
                        antennaPower = 0, relayPower = 0, antennaRate = 0, relayRate = 0, AntennasList = new List <AntennaPartInfo>()
                    };
                }
            }
            return(node_Antennas);
        }
Esempio n. 2
0
        private void AntennaCalc(List <AntennaPartInfo> antennas)
        {
            Dictionary <short, AntennaFreqCompare> freqAntennaInfo = new Dictionary <short, AntennaFreqCompare>();
            List <AntennaPartInfo> antennasList;

            //freqAdaptorsDict = new Dictionary<short, AntennaValues>();
            antennasByFreq = new Dictionary <short, AntennasByFrequency>();

            string tAntennaName = null;
            string tRelayName   = null;

            // Separate antennas in freq groups
            for (short index = 0; index < antennas.Count; index++)
            {
                // Create a new freq Key per freq
                if (!freqAntennaInfo.ContainsKey(antennas[index].frequency))
                {
                    // Use to verify if all antennas are the same.
                    // Every new freq, tAntennaName needs be define to identify if list has all equal antennas
                    tAntennaName = antennas[index].name;
                    if (antennas[index].antennaType == AntennaType.RELAY)
                    {
                        tRelayName = tAntennaName;
                    }

                    // Initial values
                    AntennaFreqCompare newValues = new AntennaFreqCompare
                    {
                        allAntennasEqual = true,
                        allRelaysEqual   = true,
                        AntennasList     = new List <AntennaPartInfo> {
                            antennas[index]
                        }
                    };

                    freqAntennaInfo.Add(antennas[index].frequency, newValues);
                }
                // Update values for existing freq Key adding new antenna
                else
                {
                    // Verify if new antenna\relay is equal previous antenna
                    freqAntennaInfo[antennas[index].frequency].allAntennasEqual &= tAntennaName == antennas[index].name;
                    if (antennas[index].antennaType == AntennaType.RELAY)
                    {
                        if (tRelayName == null)
                        {
                            tRelayName = antennas[index].name;
                        }
                        freqAntennaInfo[antennas[index].frequency].allRelaysEqual &= tRelayName == antennas[index].name;
                    }
                    freqAntennaInfo[antennas[index].frequency].AntennasList.Add(antennas[index]);
                }
            }

            // Calc the range for each fraq group
            foreach (short freq in freqAntennaInfo.Keys)
            {
                antennasList = new List <AntennaPartInfo>();

                double strongestAntenna    = 0;                                       // Strongest Antenna
                double antennaSum          = 0;                                       // Sum of all Antennas
                double antennaComb         = 0;                                       // Sum of all Antennas Combinability
                double antennaCombExponent = 0;                                       // Average Weighted Combinability Exponent
                double antennaRateSum      = 0;                                       // Sum of rate for freq antenna group

                double strongestRelay    = 0;                                         // Strongest Relay
                double relaySum          = 0;                                         // Sum of all Relay
                double relayComb         = 0;                                         // Sum of all Relay Combinability
                double relayCombExponent = 0;                                         // Average Weighted Combinability Exponent
                double relayRateSum      = 0;                                         // Sum of rate for freq antenna group

                bool allAntennaEqual = freqAntennaInfo[freq].allAntennasEqual;        // If all antennas is Equal, antennaCombinableExponent = 1
                bool allRelayEqual   = freqAntennaInfo[freq].allRelaysEqual;          // If all relay is Equal, antennaCombinableExponent = 1

                double AntennaXModified;                                              // (AntennaPower || RelayPower) * rangeModifier

                foreach (AntennaPartInfo info in freqAntennaInfo[freq].AntennasList)
                {
                    //  Skip invalid antennas
                    if (info.deployState != ModuleDeployablePart.DeployState.EXTENDED)
                    {
                        continue;
                    }

                    antennasList.Add(info);

                    //  Sum rate for the group
                    antennaRateSum += info.rate;

                    //  Antenna Power X CommNet rangeModifier
                    AntennaXModified = Math.Round(info.antennaPower * rangeModifier, 1);

                    //  Strongest antenna
                    strongestAntenna = (strongestAntenna < AntennaXModified ? AntennaXModified : strongestAntenna);

                    //  Total Antenna Power
                    antennaSum += AntennaXModified;

                    //  Average Weighted Combinability
                    //  If all antennas are Equal, CombinableExponent = 1, I guess this is the right because this way I can have the exactly the same result to signalStrength
                    if (info.antennaCombinable)
                    {
                        antennaComb += Math.Round(AntennaXModified * ((allAntennaEqual) ? 1 : info.antennaCombinableExponent), 1);
                    }

                    //  If connected through Relay, accept only AntennaType = Relay to calc
                    if (info.antennaType == AntennaType.RELAY)
                    {
                        //  Sum relay rate for the group
                        relayRateSum += info.rate;

                        //  Strongest antenna
                        strongestRelay = (strongestRelay < AntennaXModified ? AntennaXModified : strongestRelay);

                        //  Total Antenna Power
                        relaySum += AntennaXModified;

                        //  Average Weighted Combinability
                        if (info.antennaCombinable)
                        {
                            relayComb += Math.Round(AntennaXModified * ((allRelayEqual) ? 1 : info.antennaCombinableExponent), 1);
                        }
                    }
                }
                //  Average Weighted Combinability Exponent
                antennaCombExponent = antennaComb / antennaSum;
                relayCombExponent   = relayComb / relaySum;

                //  Formula source = https://wiki.kerbalspaceprogram.com/wiki/CommNet
                //  Vessel Antenna Power = Strongest Antenna Power * ( Sum of Antenna's Powers / Strongest Antenna Power ) ^ ( Average Weighted Combinability Exponent for Vessel )
                //  Vessel Antenna Power = mainAntenna * (AntennaComb/AntennaSum) ^ AntennaCombExponent;
                //AntennaValues netAntennaValues = new AntennaValues
                //{
                //  antennaPower = Math.Ceiling(strongestAntenna * Math.Pow((antennaSum / strongestAntenna), antennaCombExponent)),
                //  antennaRate = antennaRateSum,
                //  relayPower = Math.Ceiling(strongestRelay * Math.Pow((relaySum / strongestRelay), relayCombExponent)),
                //  relayRate = relayRateSum
                //};

                double aPower = Math.Ceiling(strongestAntenna * Math.Pow((antennaSum / strongestAntenna), antennaCombExponent));
                double rPower = Math.Ceiling(strongestRelay * Math.Pow((relaySum / strongestRelay), relayCombExponent));

                AntennasByFrequency byFrequency = new AntennasByFrequency
                {
                    antennaPower = aPower,
                    relayPower   = rPower,
                    antennaRate  = antennaRateSum,
                    relayRate    = relayRateSum,
                    AntennasList = antennasList
                };

                //freqAdaptorsDict.Add(freq, netAntennaValues);
                antennasByFreq.Add(freq, byFrequency);
            }
        }
        //Edit the connectivity between two potential nodes
        protected override bool SetNodeConnection(CommNode a, CommNode b)
        {
            //stop links between ground stations
            if (a.isHome && b.isHome)
            {
                Disconnect(a, b, true);
                return(false);
            }

            List <short> aFreqs, bFreqs;

            //each CommNode has at least some frequencies?
            try
            {
                aFreqs = Cache.GetFrequencies(a);
                bFreqs = Cache.GetFrequencies(b);
            }
            catch (NullReferenceException e) // either CommNode could be a kerbal on EVA
            {
                Lib.Debug("Connection issue between '{0}' and '{1}'", a.name, b.name);
                Disconnect(a, b, true);
                return(false);
            }

            //share same frequency?
            for (int i = 0; i < aFreqs.Count; i++)
            {
                if (bFreqs.Contains(aFreqs[i]))
                {
                    AntennasByFrequency a_Antennas = Cache.GetNodeAntennaCache(a, aFreqs[i]);
                    AntennasByFrequency b_Antennas = Cache.GetNodeAntennaCache(b, aFreqs[i]);

                    if (a_Antennas.antennaPower + a_Antennas.relayPower == 0.0 || b_Antennas.antennaPower + b_Antennas.relayPower == 0.0)
                    {
                        Disconnect(a, b, true);
                        return(false);
                    }
                    Vector3d precisePosition1 = a.precisePosition;
                    Vector3d precisePosition2 = b.precisePosition;

                    double num      = (precisePosition2 - precisePosition1).sqrMagnitude;
                    double distance = a.distanceOffset + b.distanceOffset;
                    if (distance != 0.0)
                    {
                        distance = Math.Sqrt(num) + distance;
                        num      = distance <= 0.0 ? (distance = 0.0) : distance * distance;
                    }
                    bool bothRelay = CommNetScenario.RangeModel.InRange(a_Antennas.relayPower, b_Antennas.relayPower, num);
                    bool aCanRelay = bothRelay;
                    bool bCanRelay = bothRelay;
                    if (!bothRelay)
                    {
                        aCanRelay = CommNetScenario.RangeModel.InRange(a_Antennas.relayPower, b_Antennas.antennaPower, num);
                        bCanRelay = CommNetScenario.RangeModel.InRange(a_Antennas.antennaPower, b_Antennas.relayPower, num);
                    }
                    if (!aCanRelay && !bCanRelay)
                    {
                        Disconnect(a, b, true);
                        return(false);
                    }
                    if (num == 0.0 && (bothRelay || aCanRelay || bCanRelay))
                    {
                        return(TryConnectFreq(a, b, 1E-07, aCanRelay, bCanRelay, bothRelay, aFreqs[i]));
                    }
                    if (distance == 0.0)
                    {
                        distance = Math.Sqrt(num);
                    }
                    if (TestOcclusion(precisePosition1, a.occluder, precisePosition2, b.occluder, distance))
                    {
                        return(TryConnectFreq(a, b, distance, aCanRelay, bCanRelay, bothRelay, aFreqs[i]));
                    }

                    Disconnect(a, b, true);
                    return(false);
                }
            }

            Disconnect(a, b, true);
            return(false);
        }
        // TODO: Create rule to disconnect vessels without EC
        protected virtual bool TryConnectFreq(CommNode a, CommNode b, double distance, bool aCanRelay, bool bCanRelay, bool bothRelay, short freq = 0)
        {
            bool   flag = false;
            double num1 = a.GetSignalStrengthMultiplier(b) * b.GetSignalStrengthMultiplier(a);
            double num2;

            AntennasByFrequency a_Antennas = Cache.GetNodeAntennaCache(a, freq);
            AntennasByFrequency b_Antennas = Cache.GetNodeAntennaCache(b, freq);

            if (bothRelay)
            {
                double normalizedRange = CommNetScenario.RangeModel.GetNormalizedRange(a_Antennas.relayPower, b_Antennas.relayPower, distance);
                if (normalizedRange > 0.0)
                {
                    num2 = Math.Sqrt(a.antennaRelay.rangeCurve.Evaluate(normalizedRange) * b.antennaRelay.rangeCurve.Evaluate(normalizedRange)) * num1;
                    if (num2 > 0.0)
                    {
                        flag = true;
                    }
                }
                else
                {
                    bothRelay = false;
                    num2      = 0.0;
                }
            }
            else
            {
                num2 = 0.0;
            }
            double num3;

            if (aCanRelay)
            {
                double normalizedRange = CommNetScenario.RangeModel.GetNormalizedRange(a_Antennas.relayPower, b_Antennas.antennaPower, distance);
                if (normalizedRange > 0.0)
                {
                    num3 = Math.Sqrt(a.antennaRelay.rangeCurve.Evaluate(normalizedRange) * b.antennaTransmit.rangeCurve.Evaluate(normalizedRange)) * num1;
                    if (num3 > 0.0)
                    {
                        flag = true;
                    }
                }
                else
                {
                    aCanRelay = false;
                    num3      = 0.0;
                }
            }
            else
            {
                aCanRelay = false;
                num3      = 0.0;
            }
            double num4;

            if (bCanRelay)
            {
                double normalizedRange = CommNetScenario.RangeModel.GetNormalizedRange(a_Antennas.antennaPower, b_Antennas.relayPower, distance);
                if (normalizedRange > 0.0)
                {
                    num4 = Math.Sqrt(b.antennaRelay.rangeCurve.Evaluate(normalizedRange) * a.antennaTransmit.rangeCurve.Evaluate(normalizedRange)) * num1;
                    if (num4 > 0.0)
                    {
                        flag = true;
                    }
                }
                else
                {
                    bCanRelay = false;
                    num4      = 0.0;
                }
            }
            else
            {
                bCanRelay = false;
                num4      = 0.0;
            }
            if (flag)
            {
                CommLink commLink = Connect(a, b, distance);
                commLink.strengthRR = num2;
                commLink.strengthAR = num3;
                commLink.strengthBR = num4;
                commLink.aCanRelay  = aCanRelay;
                commLink.bCanRelay  = bCanRelay;
                commLink.bothRelay  = bothRelay;

                // flag frequency as connected
                //Cache.GetNodeAntennaCache(a, freq).countConnections += 1;
                //Cache.GetNodeAntennaCache(b, freq).countConnections += 1;
                return(true);
            }

            Disconnect(a, b, true);
            //if (Cache.GetNodeAntennaCache(a, freq).countConnections > 0) Cache.GetNodeAntennaCache(a, freq).countConnections -= 1;
            //if (Cache.GetNodeAntennaCache(b, freq).countConnections > 0) Cache.GetNodeAntennaCache(b, freq).countConnections -= 1;
            return(false);
        }
Esempio n. 5
0
        public static void NetMan(this Panel p, Vessel v)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            Vessel_Info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 20), " <color=#cccccc>NETWORK INFO</color>"));

            // time-out simulation
#if !DEBUG
            if (p.Timeout(vi))
            {
                return;
            }
#endif

            p.SetSection("ADAPTORS");
            p.Set_IsFreqSelector(true);

            // store all devices
            var devices = new Dictionary <uint, NetDevice>();

            // store device being added
            NetDevice adap;

            // loaded vessel
            if (v.loaded)
            {
                foreach (NetworkAdaptor m in Lib.FindModules <NetworkAdaptor>(v))
                {
                    adap = new NetAdaptorDevice(m);

                    // add the device
                    // - multiple same-type components in the same part will have the same id, and are ignored
                    if (!devices.ContainsKey(adap.Id()))
                    {
                        devices.Add(adap.Id(), adap);
                    }
                }
            }
            else
            {
                // store data required to support multiple modules of same type in a part
                var PD = new Dictionary <string, Lib.module_prefab_data>();

                // for each part
                foreach (ProtoPartSnapshot proto in v.protoVessel.protoPartSnapshots)
                {
                    // get part prefab (required for module properties)
                    Part part_prefab = PartLoader.getPartInfoByName(proto.partName).partPrefab;

                    // get all module prefabs
                    var module_prefabs = part_prefab.FindModulesImplementing <PartModule>();

                    // clear module indexes
                    PD.Clear();

                    // for each module
                    foreach (ProtoPartModuleSnapshot m in proto.modules)
                    {
                        // get the module prefab
                        // if the prefab doesn't contain this module, skip it
                        PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD);
                        if (!module_prefab)
                        {
                            continue;
                        }

                        // if the module is disabled, skip it
                        // note: this must be done after ModulePrefab is called, so that indexes are right
                        if (!Lib.Proto.GetBool(m, "isEnabled"))
                        {
                            continue;
                        }

                        if (m.moduleName == "NetworkAdaptor")
                        {
                            adap = new ProtoNetAdaptorDevice(m, proto.flightID, v);

                            // add the device
                            // - multiple same-type components in the same part will have the same id, and are ignored
                            if (!devices.ContainsKey(adap.Id()))
                            {
                                devices.Add(adap.Id(), adap);
                            }
                        }
                    }
                }
            }

            // dict order by device name
            // for each device
            foreach (var pair in devices.OrderBy(x => x.Value.Name()))
            {
                // render device entry
                NetDevice dev = pair.Value;
                // Get how many antennas share the same freq
                AntennasByFrequency x = null;
                if (vi.antenna.antennasByFreq.ContainsKey(dev.InfoFreq()))
                {
                    x = vi.antenna.antennasByFreq[dev.InfoFreq()];
                }

                p.SetContent(dev.Name(), dev.InfoRate(), string.Empty, null, () => Highlighter.Set(dev.Part(), Color.cyan), dev.InfoFreq());
                p.SetIcon(Icons.left_freq, "Decrease", () =>
                {
                    if (dev.InfoFreq() > 0) // && x != null
                    {
                        //if (x.antCount == 1 && x.countConnections > 0)
                        //{
                        //  Lib.Popup(
                        //    "Warning!",
                        //    Lib.BuildString("This is the last antenna on '", dev.InfoFreq().ToString(),
                        //                    "' frequency.\nYou will lost connection in this frequency.\nDo you really want to remove this frequency from this vessel?"),
                        //    new DialogGUIButton("Remove", () => dev.ChangeFreq(-1)),
                        //    new DialogGUIButton("Keep it", () => { }));
                        //}
                        //else
                        dev.ChangeFreq(-1);
                    }
                });
                p.SetIcon(Icons.right_freq, "Increase", () =>
                {
                    if (dev.InfoFreq() < 99) // && x != null
                    {
                        //if (x.antCount == 1 && x.countConnections > 0)
                        //{
                        //  Lib.Popup(
                        //    "Warning!",
                        //    Lib.BuildString("This is the last antenna on '", dev.InfoFreq().ToString(),
                        //                    "' frequency.\nYou will lost connection in this frequency.\nDo you really want to remove this frequency from this vessel?"),
                        //    new DialogGUIButton("Remove", () => dev.ChangeFreq(+1)),
                        //    new DialogGUIButton("Keep it", () => { }));
                        //}
                        //else
                        dev.ChangeFreq(+1);
                    }
                });
            }

            p.SetSection("FREQUENCY(S) DETAIL");
            foreach (short key in vi.antenna.antennasByFreq.Keys)
            {
                double range = vi.antenna.antennasByFreq[key].antennaPower;
                double rate  = vi.antenna.antennasByFreq[key].antennaRate;

                Render_ConnectionDetail(p, range, rate, key);
            }
        }