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); }
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); }
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); } }