GetSourceSet() публичный Метод

public GetSourceSet ( int type, bool includeSurfaceMountedParts, List allParts, HashSet visited, HashSet allSources, LogMsg log, String indent ) : void
type int
includeSurfaceMountedParts bool
allParts List
visited HashSet
allSources HashSet
log LogMsg
indent String
Результат void
Пример #1
0
        public bool SetResourceDrains(List <PartSim> allParts, List <PartSim> allFuelLines, HashSet <PartSim> drainingParts)
        {
            LogMsg log = null;

            foreach (HashSet <PartSim> sourcePartSet in sourcePartSets.Values)
            {
                sourcePartSet.Clear();
            }

            for (int index = 0; index < this.resourceConsumptions.Types.Count; index++)
            {
                int type = this.resourceConsumptions.Types[index];

                HashSet <PartSim> sourcePartSet;
                if (!sourcePartSets.TryGetValue(type, out sourcePartSet))
                {
                    sourcePartSet = new HashSet <PartSim>();
                    sourcePartSets.Add(type, sourcePartSet);
                }

                switch ((ResourceFlowMode)this.resourceFlowModes[type])
                {
                case ResourceFlowMode.NO_FLOW:
                    if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0)
                    {
                        //sourcePartSet = new HashSet<PartSim>();
                        //MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this");
                        sourcePartSet.Add(partSim);
                    }
                    break;

                case ResourceFlowMode.ALL_VESSEL:
                    for (int i = 0; i < allParts.Count; i++)
                    {
                        PartSim aPartSim = allParts[i];
                        if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0)
                        {
                            sourcePartSet.Add(aPartSim);
                        }
                    }
                    break;

                case ResourceFlowMode.STAGE_PRIORITY_FLOW:

                    foreach (HashSet <PartSim> stagePartSet in stagePartSets.Values)
                    {
                        stagePartSet.Clear();
                    }
                    var maxStage = -1;

                    //Logger.Log(type);
                    for (int i = 0; i < allParts.Count; i++)
                    {
                        var aPartSim = allParts[i];
                        if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
                        {
                            continue;
                        }

                        int stage = aPartSim.DecouplerCount();
                        if (stage > maxStage)
                        {
                            maxStage = stage;
                        }

                        if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
                        {
                            sourcePartSet = new HashSet <PartSim>();
                            stagePartSets.Add(stage, sourcePartSet);
                        }
                        sourcePartSet.Add(aPartSim);
                    }

                    for (int j = 0; j <= maxStage; j++)
                    {
                        HashSet <PartSim> stagePartSet;
                        if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
                        {
                            sourcePartSet = stagePartSet;
                        }
                    }
                    break;

                case ResourceFlowMode.STACK_PRIORITY_SEARCH:
                    visited.Clear();

                    if (SimManager.logOutput)
                    {
                        log = new LogMsg();
                        log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId);
                    }
                    partSim.GetSourceSet(type, allParts, visited, sourcePartSet, log, "");
                    if (SimManager.logOutput)
                    {
                        MonoBehaviour.print(log.buf);
                    }
                    break;

                default:
                    MonoBehaviour.print("SetResourceDrains(" + partSim.name + ":" + partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
                    break;
                }


                if (sourcePartSet.Count > 0)
                {
                    sourcePartSets[type] = sourcePartSet;
                    if (SimManager.logOutput)
                    {
                        log = new LogMsg();
                        log.buf.AppendLine("Source parts for " + ResourceContainer.GetResourceName(type) + ":");
                        foreach (PartSim partSim in sourcePartSet)
                        {
                            log.buf.AppendLine(partSim.name + ":" + partSim.partId);
                        }
                        MonoBehaviour.print(log.buf);
                    }
                }
            }

            // If we don't have sources for all the needed resources then return false without setting up any drains
            for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
            {
                int type = this.resourceConsumptions.Types[i];
                HashSet <PartSim> sourcePartSet;
                if (!sourcePartSets.TryGetValue(type, out sourcePartSet) || sourcePartSet.Count == 0)
                {
                    if (SimManager.logOutput)
                    {
                        MonoBehaviour.print("No source of " + ResourceContainer.GetResourceName(type));
                    }

                    isActive = false;
                    return(false);
                }
            }
            // Now we set the drains on the members of the sets and update the draining parts set
            for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
            {
                int type = this.resourceConsumptions.Types[i];
                HashSet <PartSim> sourcePartSet = sourcePartSets[type];
                // Loop through the members of the set
                double amount = resourceConsumptions[type] / sourcePartSet.Count;
                foreach (PartSim partSim in sourcePartSet)
                {
                    if (SimManager.logOutput)
                    {
                        MonoBehaviour.print(
                            "Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" +
                            partSim.partId);
                    }

                    partSim.resourceDrains.Add(type, amount);
                    drainingParts.Add(partSim);
                }
            }
            return(true);
        }
Пример #2
0
        public bool SetResourceDrains(LogMsg log, List <PartSim> allParts, List <PartSim> allFuelLines, HashSet <PartSim> drainingParts)
        {
            //DumpSourcePartSets(log, "before clear");
            foreach (HashSet <PartSim> sourcePartSet in sourcePartSets.Values)
            {
                sourcePartSet.Clear();
            }
            //DumpSourcePartSets(log, "after clear");

            for (int index = 0; index < this.resourceConsumptionsForMass.Types.Count; index++)
            {
                int type = this.resourceConsumptionsForMass.Types[index];

                HashSet <PartSim> sourcePartSet;
                if (!sourcePartSets.TryGetValue(type, out sourcePartSet))
                {
                    sourcePartSet = new HashSet <PartSim>();
                    sourcePartSets.Add(type, sourcePartSet);
                }

                switch ((ResourceFlowMode)this.resourceFlowModes[type])
                {
                case ResourceFlowMode.NO_FLOW:
                    if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0)
                    {
                        sourcePartSet.Add(partSim);
                    }
                    break;

                case ResourceFlowMode.ALL_VESSEL:
                case ResourceFlowMode.ALL_VESSEL_BALANCE:
                    for (int i = 0; i < allParts.Count; i++)
                    {
                        PartSim aPartSim = allParts[i];
                        if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0)
                        {
                            sourcePartSet.Add(aPartSim);
                        }
                    }
                    break;

                case ResourceFlowMode.STAGE_PRIORITY_FLOW:
                case ResourceFlowMode.STAGE_PRIORITY_FLOW_BALANCE:

                    if (log != null)
                    {
                        log.Append("Find ", ResourceContainer.GetResourceName(type), " sources for ", partSim.name)
                        .AppendLine(":", partSim.partId);
                    }
                    foreach (HashSet <PartSim> stagePartSet in stagePartSets.Values)
                    {
                        stagePartSet.Clear();
                    }
                    var maxStage = -1;

                    for (int i = 0; i < allParts.Count; i++)
                    {
                        var aPartSim = allParts[i];
                        //if (log != null) log.Append(aPartSim.name, ":" + aPartSim.partId, " contains ", aPartSim.resources[type])
                        //                  .AppendLine((aPartSim.resourceFlowStates[type] == 0) ? " (disabled)" : "");
                        if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
                        {
                            continue;
                        }

                        int stage = aPartSim.inverseStage;
                        if (stage > maxStage)
                        {
                            maxStage = stage;
                        }

                        HashSet <PartSim> tempPartSet;
                        if (!stagePartSets.TryGetValue(stage, out tempPartSet))
                        {
                            tempPartSet = new HashSet <PartSim>();
                            stagePartSets.Add(stage, tempPartSet);
                        }
                        tempPartSet.Add(aPartSim);
                    }

                    for (int j = maxStage; j >= -1; j--)
                    {
                        //if (log != null) log.AppendLine("Testing stage ", j);
                        HashSet <PartSim> stagePartSet;
                        if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
                        {
                            //if (log != null) log.AppendLine("Not empty");
                            // We have to copy the contents of the set here rather than copying the set reference or
                            // bad things (tm) happen
                            foreach (PartSim aPartSim in stagePartSet)
                            {
                                sourcePartSet.Add(aPartSim);
                            }
                            break;
                        }
                    }
                    break;

                case ResourceFlowMode.STACK_PRIORITY_SEARCH:
                case ResourceFlowMode.STAGE_STACK_FLOW:
                case ResourceFlowMode.STAGE_STACK_FLOW_BALANCE:
                    visited.Clear();

                    if (log != null)
                    {
                        log.Append("Find ", ResourceContainer.GetResourceName(type), " sources for ", partSim.name)
                        .AppendLine(":", partSim.partId);
                    }

                    partSim.GetSourceSet(type, allParts, visited, sourcePartSet, log, "");
                    break;

                default:
                    if (log != null)
                    {
                        log.Append("SetResourceDrains(", partSim.name, ":", partSim.partId)
                        .AppendLine(") Unexpected flow type for ", ResourceContainer.GetResourceName(type), ")");
                    }
                    break;
                }

                if (log != null && sourcePartSet.Count > 0)
                {
                    log.AppendLine("Source parts for ", ResourceContainer.GetResourceName(type), ":");
                    foreach (PartSim partSim in sourcePartSet)
                    {
                        log.AppendLine(partSim.name, ":", partSim.partId);
                    }
                }

                //DumpSourcePartSets(log, "after " + ResourceContainer.GetResourceName(type));
            }

            // If we don't have sources for all the needed resources then return false without setting up any drains
            for (int i = 0; i < this.resourceConsumptionsForMass.Types.Count; i++)
            {
                int type = this.resourceConsumptionsForMass.Types[i];
                HashSet <PartSim> sourcePartSet;
                if (!sourcePartSets.TryGetValue(type, out sourcePartSet) || sourcePartSet.Count == 0)
                {
                    if (log != null)
                    {
                        log.AppendLine("No source of ", ResourceContainer.GetResourceName(type));
                    }
                    isActive = false;
                    return(false);
                }
            }

            // Now we set the drains on the members of the sets and update the draining parts set
            for (int i = 0; i < this.resourceConsumptionsForMass.Types.Count; i++)
            {
                int type = this.resourceConsumptionsForMass.Types[i];
                HashSet <PartSim> sourcePartSet = sourcePartSets[type];
                ResourceFlowMode  mode          = (ResourceFlowMode)resourceFlowModes[type];
                double            consumption   = resourceConsumptionsForMass[type];
                double            amount        = 0d;
                double            total         = 0d;
                if (mode == ResourceFlowMode.ALL_VESSEL_BALANCE ||
                    mode == ResourceFlowMode.STAGE_PRIORITY_FLOW_BALANCE ||
                    mode == ResourceFlowMode.STAGE_STACK_FLOW_BALANCE ||
                    mode == ResourceFlowMode.STACK_PRIORITY_SEARCH)
                {
                    foreach (PartSim partSim in sourcePartSet)
                    {
                        total += partSim.resources[type];
                    }
                }
                else
                {
                    amount = consumption / sourcePartSet.Count;
                }

                // Loop through the members of the set
                foreach (PartSim partSim in sourcePartSet)
                {
                    if (total != 0d)
                    {
                        amount = consumption * partSim.resources[type] / total;
                    }

                    if (log != null)
                    {
                        log.Append("Adding drain of ", amount, " ", ResourceContainer.GetResourceName(type))
                        .AppendLine(" to ", partSim.name, ":", partSim.partId);
                    }

                    partSim.resourceDrains.Add(type, amount);
                    drainingParts.Add(partSim);
                }
            }
            return(true);
        }
Пример #3
0
        // All functions below this point must not rely on the part member (it may be null)
        //

        public void GetSourceSet(int type, bool includeSurfaceMountedParts, List <PartSim> allParts, HashSet <PartSim> visited, HashSet <PartSim> allSources, LogMsg log, String indent)
        {
            if (log != null)
            {
                log.buf.AppendLine(indent + "GetSourceSet(" + ResourceContainer.GetResourceName(type) + ") for " + name + ":" + partId);
                indent += "  ";
            }

            // Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns as is.
            if (visited.Contains(this))
            {
                if (log != null)
                {
                    log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
                }
                return;
            }

            if (log != null)
            {
                log.buf.AppendLine(indent + "Adding this to visited");
            }

            visited.Add(this);

            // Rule 2: Part performs scan on start of every fuel pipe ending in it. This scan is done in order in which pipes were installed.
            // Then it makes an union of fuel tank sets each pipe scan returned. If the resulting list is not empty, it is returned as result.
            //MonoBehaviour.print("for each fuel line");

            int lastCount = allSources.Count;

            for (int i = 0; i < this.fuelTargets.Count; i++)
            {
                PartSim partSim = this.fuelTargets[i];
                if (partSim != null)
                {
                    if (visited.Contains(partSim))
                    {
                        if (log != null)
                        {
                            log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
                        }
                    }
                    else
                    {
                        if (log != null)
                        {
                            log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
                        }

                        partSim.GetSourceSet(type, includeSurfaceMountedParts, allParts, visited, allSources, log, indent);
                    }
                }
            }

            // check surface mounted fuel targets
            if (includeSurfaceMountedParts)
            {
                for (int i = 0; i < surfaceMountFuelTargets.Count; i++)
                {
                    PartSim partSim = this.surfaceMountFuelTargets[i];
                    if (partSim != null)
                    {
                        if (visited.Contains(partSim))
                        {
                            if (log != null)
                            {
                                log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
                            }
                        }
                        else
                        {
                            if (log != null)
                            {
                                log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
                            }

                            partSim.GetSourceSet(type, true, allParts, visited, allSources, log, indent);
                        }
                    }
                }
            }

            if (allSources.Count > lastCount)
            {
                if (log != null)
                {
                    log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
                }
                return;
            }


            // Rule 3: This rule has been removed and merged with rules 4 and 7 to fix issue with fuel tanks with disabled crossfeed

            // Rule 4: Part performs scan on each of its axially mounted neighbors.
            //  Couplers (bicoupler, tricoupler, ...) are an exception, they only scan one attach point on the single attachment side,
            //  skip the points on the side where multiple points are. [Experiment]
            //  Again, the part creates union of scan lists from each of its neighbor and if it is not empty, returns this list.
            //  The order in which mount points of a part are scanned appears to be fixed and defined by the part specification file. [Experiment]
            if (fuelCrossFeed)
            {
                lastCount = allSources.Count;
                //MonoBehaviour.print("for each attach node");
                for (int i = 0; i < this.attachNodes.Count; i++)
                {
                    AttachNodeSim attachSim = this.attachNodes[i];
                    if (attachSim.attachedPartSim != null)
                    {
                        if (attachSim.nodeType == AttachNode.NodeType.Stack)
                        {
                            if ((string.IsNullOrEmpty(noCrossFeedNodeKey) == false && attachSim.id.Contains(noCrossFeedNodeKey)) == false)
                            {
                                if (visited.Contains(attachSim.attachedPartSim))
                                {
                                    if (log != null)
                                    {
                                        log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
                                    }
                                }
                                else
                                {
                                    if (log != null)
                                    {
                                        log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
                                    }

                                    attachSim.attachedPartSim.GetSourceSet(type, includeSurfaceMountedParts, allParts, visited, allSources, log, indent);
                                }
                            }
                        }
                    }
                }

                if (allSources.Count > lastCount)
                {
                    if (log != null)
                    {
                        log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
                    }
                    return;
                }
            }

            // Rule 5: If the part is fuel container for searched type of fuel (i.e. it has capability to contain that type of fuel and the fuel
            // type was not disabled [Experiment]) and it contains fuel, it returns itself.
            // Rule 6: If the part is fuel container for searched type of fuel (i.e. it has capability to contain that type of fuel and the fuel
            // type was not disabled) but it does not contain the requested fuel, it returns empty list. [Experiment]
            if (resources.HasType(type) && resourceFlowStates[type] > 0.0)
            {
                if (resources[type] > SimManager.RESOURCE_MIN)
                {
                    allSources.Add(this);

                    if (log != null)
                    {
                        log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
                    }
                }

                return;
            }
            else
            {
                if (log != null)
                {
                    log.buf.AppendLine(indent + "Not fuel tank or disabled. HasType = " + resources.HasType(type) + "  FlowState = " + resourceFlowStates[type]);
                }
            }

            // Rule 7: If the part is radially attached to another part and it is child of that part in the ship's tree structure, it scans its
            // parent and returns whatever the parent scan returned. [Experiment] [Experiment]
            if (parent != null && parentAttach == AttachModes.SRF_ATTACH)
            {
                if (fuelCrossFeed)
                {
                    if (visited.Contains(parent))
                    {
                        if (log != null)
                        {
                            log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
                        }
                    }
                    else
                    {
                        lastCount = allSources.Count;
                        this.parent.GetSourceSet(type, includeSurfaceMountedParts, allParts, visited, allSources, log, indent);
                        if (allSources.Count > lastCount)
                        {
                            if (log != null)
                            {
                                log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
                            }
                            return;
                        }
                    }
                }
            }

            // Rule 8: If all preceding rules failed, part returns empty list.
            if (log != null)
            {
                log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
            }

            return;
        }