/// <summary> /// Makes summary text /// </summary> /// <param name="previousPopulations">If provided comparisons to previous populations is included</param> /// <param name="playerReadable">if true ids are removed from the output</param> /// <param name="effects">if not null these effects are applied to the population numbers</param> public string MakeSummary(PatchMap previousPopulations = null, bool playerReadable = false, List <ExternalEffect> effects = null) { const bool resolveMoves = true; var builder = new StringBuilder(500); string PatchString(Patch patch) { var builder2 = new StringBuilder(80); if (!playerReadable) { builder2.Append(patch.ID); } builder2.Append(" "); builder2.Append(patch.Name); return(builder2.ToString()); } void OutputPopulationForPatch(Species species, Patch patch, long population) { if (population > 0) { builder.Append(" "); builder.Append(PatchString(patch)); builder.Append(" "); builder.Append(TranslationServer.Translate("POPULATION")); builder.Append(" "); builder.Append(population); } else { builder.Append(" "); builder.Append(" went extinct in "); builder.Append(PatchString(patch)); } if (previousPopulations != null) { builder.Append(" "); builder.Append(TranslationServer.Translate("PREVIOUS")); builder.Append(" "); builder.Append(previousPopulations.GetPatch(patch.ID).GetSpeciesPopulation(species)); } builder.Append("\n"); } foreach (var entry in results.Values) { builder.Append(playerReadable ? entry.Species.FormattedName : entry.Species.FormattedIdentifier); builder.Append(":\n"); if (entry.MutatedProperties != null) { builder.Append(" "); builder.Append(TranslationServer.Translate("RUNRESULT_HAS_A_MUTATION")); if (!playerReadable) { builder.Append(", "); builder.Append(TranslationServer.Translate("RUNRESULT_GENE_CODE")); builder.Append(" "); builder.Append(entry.MutatedProperties.StringCode); } builder.Append("\n"); } if (entry.SpreadToPatches.Count > 0) { builder.Append(" "); builder.Append(TranslationServer.Translate("RUNRESULT_SPREAD_TO_PATCHES")); builder.Append("\n"); foreach (var spreadEntry in entry.SpreadToPatches) { if (playerReadable) { builder.Append(" "); builder.Append(string.Format(CultureInfo.CurrentCulture, TranslationServer.Translate("RUNRESULT_BY_SENDING_POPULATION"), spreadEntry.To.Name, spreadEntry.Population, spreadEntry.From.Name)); } else { builder.Append(" "); builder.Append(spreadEntry.To.Name); builder.Append(" pop: "); builder.Append(spreadEntry.Population); builder.Append(" from: "); builder.Append(spreadEntry.From.Name); } builder.Append("\n"); } } builder.Append(" "); builder.Append(TranslationServer.Translate("RUNRESULT_POP_IN_PATCHES")); builder.Append("\n"); foreach (var patchPopulation in entry.NewPopulationInPatches) { long adjustedPopulation = patchPopulation.Value; if (resolveMoves) { adjustedPopulation += CountSpeciesSpreadPopulation(entry.Species, patchPopulation.Key); } // Apply external effects if (effects != null && previousPopulations != null && previousPopulations.CurrentPatch.ID == patchPopulation.Key.ID) { foreach (var effect in effects) { if (effect.Species == entry.Species) { adjustedPopulation += effect.Constant + (long)(effect.Species.Population * effect.Coefficient) - effect.Species.Population; } } } // As the populations are added to all patches, even when the species is not there, we remove those // from output if there is currently no population in a patch and there isn't one in // previousPopulations var include = false; if (adjustedPopulation > 0) { include = true; } else if (previousPopulations != null) { if (previousPopulations.GetPatch(patchPopulation.Key.ID).GetSpeciesPopulation(entry.Species) > 0) { include = true; } } if (include) { OutputPopulationForPatch(entry.Species, patchPopulation.Key, adjustedPopulation); } } // Also print new patches the species moved to (as the moves don't get // included in newPopulationInPatches if (resolveMoves) { foreach (var spreadEntry in entry.SpreadToPatches) { var found = false; var to = spreadEntry.To; foreach (var populationEntry in entry.NewPopulationInPatches) { if (populationEntry.Key == to) { found = true; break; } } if (!found) { OutputPopulationForPatch(entry.Species, to, CountSpeciesSpreadPopulation(entry.Species, to)); } } } if (GetGlobalPopulation(entry.Species, resolveMoves) <= 0) { builder.Append(" "); builder.Append("went extinct from the planet"); builder.Append("\n"); } if (playerReadable) { builder.Append("\n"); } } return(builder.ToString()); }
/// <summary> /// Makes summary text /// </summary> /// <param name="previousPopulations">If provided comparisons to previous populations is included</param> /// <param name="playerReadable">if true ids are removed from the output</param> /// <param name="effects">if not null these effects are applied to the population numbers</param> /// <returns>The generated summary text</returns> public LocalizedStringBuilder MakeSummary(PatchMap previousPopulations = null, bool playerReadable = false, List <ExternalEffect> effects = null) { const bool resolveMigrations = true; const bool resolveSplits = true; var builder = new LocalizedStringBuilder(500); LocalizedStringBuilder PatchString(Patch patch) { var builder2 = new LocalizedStringBuilder(80); if (!playerReadable) { builder2.Append(patch.ID); } builder2.Append(' '); builder2.Append(new LocalizedString(patch.Name)); return(builder2); } void OutputPopulationForPatch(Species species, Patch patch, long population) { builder.Append(" "); var patchName = PatchString(patch); if (population > 0) { builder.Append(patchName); builder.Append(' '); builder.Append(new LocalizedString("POPULATION")); builder.Append(' '); builder.Append(population); } else { // For some reason this line had one more space padding than the case that the population // wasn't extinct in this patch builder.Append(new LocalizedString("WENT_EXTINCT_IN", patchName)); } if (previousPopulations != null) { builder.Append(' '); builder.Append(new LocalizedString("PREVIOUS")); builder.Append(' '); builder.Append(previousPopulations.GetPatch(patch.ID).GetSpeciesPopulation(species)); } builder.Append('\n'); } foreach (var entry in results.Values.OrderByDescending(s => s.Species.PlayerSpecies) .ThenBy(s => s.Species.FormattedName)) { builder.Append(playerReadable ? entry.Species.FormattedName : entry.Species.FormattedIdentifier); builder.Append(":\n"); if (entry.SplitFrom != null) { builder.Append(' '); builder.Append(new LocalizedString("RUN_RESULT_SPLIT_FROM", playerReadable ? entry.SplitFrom.FormattedName : entry.SplitFrom.FormattedIdentifier)); builder.Append('\n'); } if (entry.NewlyCreated != null) { builder.Append(' '); switch (entry.NewlyCreated.Value) { case NewSpeciesType.FillNiche: builder.Append(new LocalizedString("RUN_RESULT_NICHE_FILL")); break; case NewSpeciesType.SplitDueToMutation: builder.Append(new LocalizedString("RUN_RESULT_SELECTION_PRESSURE_SPLIT")); break; default: GD.PrintErr("Unhandled newly created species type: ", entry.NewlyCreated.Value); builder.Append(entry.NewlyCreated.Value); break; } builder.Append('\n'); } if (entry.SplitOff != null) { if (entry.SplitOffPatches == null) { throw new InvalidOperationException("List of split off patches is null"); } builder.Append(' '); builder.Append(new LocalizedString("RUN_RESULT_SPLIT_OFF_TO", playerReadable ? entry.SplitOff.FormattedName : entry.SplitOff.FormattedIdentifier)); builder.Append('\n'); foreach (var patch in entry.SplitOffPatches) { builder.Append(" "); builder.Append(new LocalizedString(patch.Name)); builder.Append('\n'); } } if (entry.MutatedProperties != null) { builder.Append(' '); builder.Append(new LocalizedString("RUN_RESULT_HAS_A_MUTATION")); if (!playerReadable) { builder.Append(", "); builder.Append(new LocalizedString("RUN_RESULT_GENE_CODE")); builder.Append(' '); builder.Append(entry.MutatedProperties.StringCode); } builder.Append('\n'); } if (entry.SpreadToPatches.Count > 0) { builder.Append(' '); builder.Append(new LocalizedString("RUN_RESULT_SPREAD_TO_PATCHES")); builder.Append('\n'); foreach (var spreadEntry in entry.SpreadToPatches) { if (playerReadable) { builder.Append(" "); builder.Append(new LocalizedString("RUN_RESULT_BY_SENDING_POPULATION", new LocalizedString(spreadEntry.To.Name), spreadEntry.Population, new LocalizedString(spreadEntry.From.Name))); } else { builder.Append(" "); builder.Append(new LocalizedString(spreadEntry.To.Name)); builder.Append(" pop: "); builder.Append(spreadEntry.Population); builder.Append(" from: "); builder.Append(new LocalizedString(spreadEntry.From.Name)); } builder.Append('\n'); } } builder.Append(' '); builder.Append(new LocalizedString("RUN_RESULT_POP_IN_PATCHES")); builder.Append('\n'); foreach (var patchPopulation in entry.NewPopulationInPatches) { long adjustedPopulation = patchPopulation.Value; if (resolveMigrations) { adjustedPopulation += CountSpeciesSpreadPopulation(entry.Species, patchPopulation.Key); } if (resolveSplits) { if (entry.SplitOffPatches?.Contains(patchPopulation.Key) == true) { // All population splits off adjustedPopulation = 0; } } // Apply external effects if (effects != null && previousPopulations != null && previousPopulations.CurrentPatch.ID == patchPopulation.Key.ID) { foreach (var effect in effects) { if (effect.Species == entry.Species) { adjustedPopulation += effect.Constant + (long)(effect.Species.Population * effect.Coefficient) - effect.Species.Population; } } } // As the populations are added to all patches, even when the species is not there, we remove those // from output if there is currently no population in a patch and there isn't one in // previousPopulations var include = false; if (adjustedPopulation > 0) { include = true; } else { if (previousPopulations?.GetPatch(patchPopulation.Key.ID).GetSpeciesPopulation(entry.Species) > 0) { include = true; } } if (include) { OutputPopulationForPatch(entry.Species, patchPopulation.Key, adjustedPopulation); } } // Also print new patches the species moved to (as the moves don't get // included in newPopulationInPatches if (resolveMigrations) { foreach (var spreadEntry in entry.SpreadToPatches) { var found = false; var to = spreadEntry.To; foreach (var populationEntry in entry.NewPopulationInPatches) { if (populationEntry.Key == to) { found = true; break; } } if (!found) { OutputPopulationForPatch(entry.Species, to, CountSpeciesSpreadPopulation(entry.Species, to)); } } } // Print populations from splits // Warning suppressed on resolveSplits to allow keeping the variable // ReSharper disable once RedundantLogicalConditionalExpressionOperand if (resolveSplits && entry.SplitFrom != null) { var splitFrom = results[entry.SplitFrom]; // Skip if the SplitFrom variable was used just to indicate this didn't pop out of thin air if (splitFrom.SplitOff == entry.Species) { foreach (var patchPopulation in splitFrom.SplitOffPatches) { OutputPopulationForPatch(entry.Species, patchPopulation, splitFrom.NewPopulationInPatches[patchPopulation]); } } } if (GetGlobalPopulation(entry.Species, resolveMigrations, resolveSplits) <= 0) { builder.Append(' '); builder.Append(new LocalizedString("WENT_EXTINCT_FROM_PLANET")); builder.Append('\n'); } if (playerReadable) { builder.Append('\n'); } } return(builder); }
/// <summary> /// Makes summary text /// </summary> /// <param name="previousPopulations">If provided comparisons to previous populations is included</param> /// <param name="playerReadable">if true ids are removed from the output</param> /// <param name="effects">if not null these effects are applied to the population numbers</param> public string MakeSummary(PatchMap previousPopulations = null, bool playerReadable = false, List <ExternalEffect> effects = null) { const bool resolveMoves = true; var builder = new StringBuilder(500); string PatchString(Patch patch) { var builder2 = new StringBuilder(80); if (!playerReadable) { builder2.Append(patch.ID); } builder2.Append(" "); builder2.Append(patch.Name); return(builder2.ToString()); } void OutputPopulationForPatch(Species species, Patch patch, int population) { builder.Append(" "); builder.Append(PatchString(patch)); builder.Append(" population: "); builder.Append(Math.Max(population, 0)); if (previousPopulations != null) { builder.Append(" previous: "); builder.Append(previousPopulations.GetPatch(patch.ID).GetSpeciesPopulation(species)); } builder.Append("\n"); } foreach (var entry in results.Values) { builder.Append(playerReadable ? entry.Species.FormattedName : entry.Species.FormattedIdentifier); builder.Append(":\n"); if (entry.MutatedProperties != null) { builder.Append(" has a mutation"); if (!playerReadable) { builder.Append(", gene code: "); builder.Append(entry.MutatedProperties.StringCode); } builder.Append("\n"); } if (entry.SpreadToPatches.Count > 0) { builder.Append(" spread to patches:\n"); foreach (var spreadEntry in entry.SpreadToPatches) { if (playerReadable) { builder.Append(" "); builder.Append(spreadEntry.To.Name); builder.Append(" by sending: "); builder.Append(spreadEntry.Population); builder.Append(" population"); builder.Append(" from patch: "); builder.Append(spreadEntry.From.Name); } else { builder.Append(" "); builder.Append(spreadEntry.To.Name); builder.Append(" pop: "); builder.Append(spreadEntry.Population); builder.Append(" from: "); builder.Append(spreadEntry.From.Name); } builder.Append("\n"); } } builder.Append(" population in patches:\n"); foreach (var patchPopulation in entry.NewPopulationInPatches) { var adjustedPopulation = patchPopulation.Value; if (resolveMoves) { adjustedPopulation += CountSpeciesSpreadPopulation(entry.Species, patchPopulation.Key); } // Apply external effects if (effects != null && previousPopulations != null && previousPopulations.CurrentPatch.ID == patchPopulation.Key.ID) { foreach (var effect in effects) { if (effect.Species == entry.Species) { adjustedPopulation += effect.Amount; } } } // As the populations are added to all patches, even when the species is not there, we remove those // from output if there is currently no population in a patch and there isn't one in // previousPopulations bool include = false; if (adjustedPopulation > 0) { include = true; } else if (previousPopulations != null) { if (previousPopulations.GetPatch(patchPopulation.Key.ID).GetSpeciesPopulation(entry.Species) > 0) { include = true; } } if (include) { OutputPopulationForPatch(entry.Species, patchPopulation.Key, adjustedPopulation); } } // Also print new patches the species moved to (as the moves don't get // included in newPopulationInPatches if (resolveMoves) { foreach (var spreadEntry in entry.SpreadToPatches) { bool found = false; var to = spreadEntry.To; foreach (var populationEntry in entry.NewPopulationInPatches) { if (populationEntry.Key == to) { found = true; break; } } if (!found) { OutputPopulationForPatch(entry.Species, to, CountSpeciesSpreadPopulation(entry.Species, to)); } } } if (playerReadable) { builder.Append("\n"); } } return(builder.ToString()); }