// Calculates the infection chance for a given integrated exposure.
        public static float GetInfectionChance(GermExposure ge, int total, float resistance)
        {
            /*
             * Allow one exposure count with 0 effects, then use exponential function:
             *
             * Chance to infect = 1.0 - e^(FACTOR * -(totalOverThreshold / threshold))
             *
             * With factor at 0.5:
             * Double exposure count ~ 40 %
             * Triple exposure count ~ 63 %
             * Quadruple exposure count ~ 77 %
             *
             * Resistance adjusts the thresholds
             */
            int threshold = GermExposureTuning.ThresholdsFor(ge.Exposure).GetThreshold(ge.
                                                                                       Vector);
            float adjThres = AdjustedThreshold(threshold, resistance), overTotal = Mathf.Floor(
                total - adjThres);

            // threshold of 1 is instant infection
            return((overTotal > 0.0f) ? ((threshold < 2) ? 1.0f : (1.0f - Mathf.Exp(
                                                                       -GermExposureTuning.CONTRACT_FACTOR * overTotal / adjThres))) : 0.0f);
        }
        // Retrieves the worst chance for germ infection across all vectors.
        internal float GetWorstInfectionChance(ExposureType exposure, float resist)
        {
            float worstChance = 0.0f;

            if (exposure == null)
            {
                throw new ArgumentNullException("exposure");
            }
            foreach (var vector in ALL_VECTORS)
            {
                var ge = new GermExposure(vector, exposure);
                if (integratedExposure.TryGetValue(ge, out int byVector))
                {
                    // Resistance should be calculated by the SMI
                    float chance = GetInfectionChance(ge, byVector, resist);
                    if (chance > worstChance)
                    {
                        worstChance = chance;
                    }
                }
            }
            return(worstChance);
        }
        // Performs the dirty work of counting germs on a Duplicant.
        private void DoInjectDisease(GermExposureMonitor.Instance monitor, Disease disease,
                                     int count, Tag source, GermExposure ge)
        {
            var exposure  = ge.Exposure;
            int threshold = GermExposureTuning.ThresholdsFor(exposure).GetThreshold(ge.Vector);

            if (threshold > 0 && gameObject != null)
            {
                string germ  = ge.GermID;
                var    state = monitor.GetExposureState(germ);
                // Eligible addition to the integrated exposure calculations
                if (integratedExposure.TryGetValue(ge, out int total))
                {
                    total += count;
                }
                else
                {
                    total = count;
                }
#if DEBUG
                PUtil.LogDebug("{0} has {1:D} germs of {2} by {3} (threshold = {4:D})".F(
                                   gameObject.name, count, germ, ge.Vector, threshold));
#endif
                integratedExposure[ge] = total;
                // Resistance is required to move the thresholds which is used for tier
                // calculation
                float resist = GetResistance(exposure), adjThres = AdjustedThreshold(
                    threshold, resist), tier = total / adjThres;
                switch (state)
                {
                case ExposureState.None:
                case ExposureState.Contact:
                    // Update location where they encountered the germ
                    monitor.lastDiseaseSources[disease.id] = new DiseaseSourceInfo(source,
                                                                                   ge.Vector, GetInfectionChance(ge, total, resist), transform.
                                                                                   GetPosition());
                    if (total > adjThres)
                    {
                        if (exposure.infect_immediately)
                        {
                            // The ultimate evil flag
#if DEBUG
                            PUtil.LogDebug("Infecting {0} with {1}".F(gameObject.name, germ));
#endif
                            monitor.InfectImmediately(exposure);
                        }
                        else
                        {
                            // "Exposed to slimelung"
                            monitor.SetExposureState(germ, ExposureState.Exposed);
                            monitor.SetExposureTier(germ, tier);
#if DEBUG
                            PUtil.LogDebug("{0} exposed to {1} tier {2:F1}".F(gameObject.name,
                                                                              germ, tier));
#endif
                        }
                    }
                    else if (state == ExposureState.None)
                    {
                        // "Contact with slimelung"
                        monitor.SetExposureState(germ, ExposureState.Contact);
                    }
                    break;

                case ExposureState.Exposed:
                    // Upgrade the visual tier
                    if (total > threshold && tier > monitor.GetExposureTier(germ))
                    {
                        monitor.SetExposureTier(germ, tier);
#if DEBUG
                        PUtil.LogDebug("{0} exposure of {1} upgraded to {2:F1}".F(gameObject.
                                                                                  name, germ, tier));
#endif
                    }
                    break;

                case ExposureState.Contracted:
                case ExposureState.Sick:
                    // Already sick
                    break;

                default:
                    break;
                }
            }
        }