private TabletopParams CreateFeatureParamsForSection(int section)
        {
            int    numSections          = sectionsProvider.NumSections();
            double sectionLengthSeconds = sectionModel.TotalLength.TotalSeconds;

            //first decide if it has a tabletop at all.
            //the chance of it being something at all rises from 0% to 100%.
            double progression = ((float)section + 1) / numSections; // <= 1

            //if it's a tabletop:
            double topLength =
                randomizer.ProportionAlong(sectionModel.FeatureLengthVariation, progression,
                                           sectionModel.MinFeatureLength.TotalSeconds,
                                           sectionModel.MaxFeatureLength.TotalSeconds);
            double maxRampLength = Math.Min(sectionModel.MaxRampLength.TotalSeconds, (sectionLengthSeconds - topLength) / 2);

            if (sectionModel.MinRampLength.TotalSeconds > maxRampLength)
            {
                throw new InvalidOperationException($"MinRampLength must be <= maxRampLength. MinTabletopLength could be too high.");
            }

            // could feasibly be MinRampLength at the start of the track. Desirable? Yes, because other parameters constrain the dramaticness at the start.
            double rampLength =
                randomizer.ProportionAlong(sectionModel.RampLengthVariation, progression,
                                           maxRampLength,
                                           sectionModel.MinRampLength.TotalSeconds); // Max is first as shorter ramps are more dramatic (nearer the end of the track)
            var result = new TabletopParams
            {
                RampLength   = rampLength,
                TopLength    = topLength,
                RampsUseSin2 = true
            };

            return(result);
        }
Example #2
0
        private double CreateTopFrequency(int section)
        {
            var    numSections = sectionsProvider.NumSections();
            double progression = (float)section / numSections;  // <= 1
            //20% of being a fall, 80% chance a rise
            var isRise         = randomizer.GetRandom() > 1 - pulseFrequency.ChanceOfHigh;
            var frequencyLimit = isRise ? pulseFrequency.High : pulseFrequency.Low;
            var topFrequency   = randomizer.ProportionAlong(pulseFrequency.Variation, progression,
                                                            pulseFrequency.Quiescent,
                                                            frequencyLimit);

            if (topFrequency <= 0)
            {
                throw new InvalidOperationException("TopFrequency must be > 0");
            }

            return(topFrequency);
        }
Example #3
0
        private double Wetness(double t, int n)
        {
            if (wetness == null)
            {
                return(0);
            }

            if (sections == null)
            {
                return(wetness.Maximum);
            }

            // rise in a sin^2 fashion from MinWetness to MaxWetness
            var section = sectionsProvider.Section(n);

            var maxForSection = maxWetnessForSectionCache.GetOrAdd(section, s =>
            {
                var numSections = sectionsProvider.NumSections();
                var progression = (double)s / Math.Max(1, numSections - 1); // <= 1
                var max         = randomizer.ProportionAlong(wetness.Variation, progression,
                                                             wetness.Minimum, wetness.Maximum);
                return(max);
            });

            double value;

            if (wetness.LinkToFeature)
            {
                var isThisFeature = featureChooser.IsFeature(n, nameof(FeatureProbabilityModel.Wetness));
                value = isThisFeature ?
                        featureProvider.FeatureValue(t, n, wetness.Minimum, maxForSection)
                    : wetness.Minimum;
            }
            else
            {
                value = maxForSection;
            }

            return(value);
        }