private void UpdateSunObservationStatus()
        {
            // determine sun surface observation status for all suns in the system
            vesselsPerSun.Clear();
            foreach (var entries in EquipmentStates.states)
            {
                foreach (var e in entries.Value)
                {
                    if (e.id == Configuration.SunObservationEquipment && e.value == EquipmentState.nominal)
                    {
                        Vessel v = FlightGlobals.FindVessel(entries.Key);
                        if (v != null)
                        {
                            var sun = Sim.GetParentStar(v.mainBody);
                            if (!vesselsPerSun.ContainsKey(sun))
                            {
                                vesselsPerSun[sun] = new List <Vessel>();
                            }
                            vesselsPerSun[sun].Add(v);
                        }
                    }
                }
            }

            foreach (var e in vesselsPerSun)
            {
                var sun     = e.Key;
                var vessels = e.Value;
                if (solarSurfaces == null)
                {
                    solarSurfaces = BodySurfaceObservation.CreateVisibleSurfaces();
                }

                var context = new EvaluationContext(GetUniverseEvaluator(), null, sun);
                context.SetTime(Planetarium.GetUniversalTime());
                Vector3d sunPosition = context.BodyPosition(sun);

                var observedSurface = (float)BodySurfaceObservation.VisibleSurface(vessels, context, sunPosition, Configuration.MinSunObservationAngle, solarSurfaces);
                API.SetStormObservationQuality(sun, observedSurface);
                Utils.LogDebug($"Solar surface observation for {sun.displayName}: {(observedSurface * 100.0).ToString("F2")}%");
            }
        }
Exemple #2
0
        protected override void OnUpdate()
        {
            base.OnUpdate();
            if (ParameterCount == 0)
            {
                return;
            }
            if (state != ParameterState.Incomplete)
            {
                return;
            }

            if (!KerbalismContractsMain.KerbalismInitialized)
            {
                return;
            }

            if (lastUpdate == 0)
            {
                lastUpdate = Planetarium.GetUniversalTime();
                return;
            }

            bool childParameterChanged = false;

            if (subRequirementParameters.Count == 0)
            {
                childParameterChanged = true;
                CreateSubParameters();
            }

            var lastUpdateAge = Planetarium.GetUniversalTime() - lastUpdate;

            if (lastUpdateAge < 1.0)
            {
                return;
            }
            lastUpdate = Planetarium.GetUniversalTime();

            vessels.Clear();
            context = CreateContext(lastUpdateAge);

            foreach (var sp in subRequirementParameters)
            {
                sp.ResetContext(context);
            }

            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                if (!Utils.IsVessel(vessel))
                {
                    continue;
                }

                if (!CouldBeCandidate(vessel))
                {
                    continue;
                }

                vessels.Add(vessel);
            }

            if (!hideChildren)
            {
                foreach (var vsp in vesselStatusParameters)
                {
                    vsp.obsolete = true;
                }
            }

            List <Vessel> vesselsMeetingCondition = new List <Vessel>();

            int stepCount = context.steps.Count;

            for (int i = 0; i < stepCount; i++)
            {
                var now = context.steps[i];
                context.SetTime(now);

                vesselsMeetingCondition.Clear();
                bool doLabelUpdate = !hideChildren && i + 1 == stepCount;

                foreach (Vessel vessel in vessels)
                {
                    // Note considering early termination for performance gains:
                    // If we already know that we have enough vessels to satisfy
                    // our requirement, and if we don't have to update labels,
                    // then we don' tneed to test all vessels. However, this
                    // doesn't work when we have complex requirements that need
                    // to consider multiple vessels at once (like body surface
                    // observation percentage). We could change the implementation
                    // to continuously integrate one vessel at a time into the
                    // multi-vessel test and abort as soon as that one is satisfied,
                    // but if that also calculates a number visible to the user
                    // (like percentage of surface observed), that number would
                    // be wrong. So we need to test all vessels, all the time.

                    // if (!doLabelUpdate && vesselsMeetingCondition.Count >= minVessels)
                    //	break;

                    string statusLabel;

                    bool conditionMet = VesselMeetsCondition(vessel, doLabelUpdate, out statusLabel);
                    if (conditionMet)
                    {
                        vesselsMeetingCondition.Add(vessel);
                    }

                    if (doLabelUpdate)
                    {
                        childParameterChanged |= UpdateVesselStatus(vessel, statusLabel, conditionMet);
                    }
                }

                bool allConditionsMet = vesselsMeetingCondition.Count >= minVessels;
                allConditionsMet &= VesselsMeetCondition(vesselsMeetingCondition);

                if (durationParameter == null)
                {
                    SetState(allConditionsMet ? ParameterState.Complete : ParameterState.Incomplete);
                }
                else
                {
                    durationParameter.Update(allConditionsMet, now);
                    SetState(durationParameter.State);
                }

                if (state == ParameterState.Complete)
                {
                    break;
                }
            }

            childParameterChanged |= RemoveObsoleteVesselStatusParameters();
            if (childParameterChanged)
            {
                ContractConfigurator.ContractConfigurator.OnParameterChange.Fire(this.Root, this);
            }
        }