protected virtual void RenderNode(ICanvas canvas, TreeNode <NodeData> node, Font font) { // Cross-out the species if it's extinct. string speciesName = TaxonFormatter.GetString(node.Value.Data.Species); bool isHighlighted = node.Value.Data.IsAncestor && !node.Children.Any(child => child.Value.Data.IsAncestor); if (node.Value.Data.Species.Status.IsExinct && StringUtilities.GetMarkupProperties(speciesName).HasFlag(MarkupProperties.Strikethrough)) { using (Brush brush = new SolidBrush(TextColor)) using (Pen pen = new Pen(brush, 1.0f)) { canvas.DrawLine(pen, new PointF(node.Value.Bounds.X, (float)Math.Round(node.Value.Bounds.Y + node.Value.Bounds.Height / 2.0f)), new PointF(node.Value.Bounds.X + (node.Value.Bounds.Width - 10.0f), (float)Math.Round(node.Value.Bounds.Y + node.Value.Bounds.Height / 2.0f))); } } // Draw the name of the species. RenderText(canvas, StringUtilities.StripMarkup(speciesName), new PointF(node.Value.Bounds.X, node.Value.Bounds.Y), font, isHighlighted ? HighlightColor : TextColor); // Draw child nodes. RenderChildNodes(canvas, node, font); }
public async Task Prey([Remainder] string speciesName) { speciesName = StringUtilities.StripOuterQuotes(speciesName); ISpecies species = await GetSpeciesOrReplyAsync(speciesName); if (species.IsValid()) { // Get the preyed-upon species. IEnumerable <IPredationInfo> preySpecies = (await Db.GetPreyAsync(species)) .OrderBy(info => info.Species.GetShortName()); if (preySpecies.Count() > 0) { List <string> lines = new List <string>(); foreach (IPredationInfo preyInfo in preySpecies) { string line = TaxonFormatter.GetString(preyInfo.Species); if (!string.IsNullOrEmpty(preyInfo.Notes)) { line += (string.Format(" ({0})", preyInfo.Notes.ToLowerInvariant())); } lines.Add(line); } string title = string.Format("Species preyed upon by {0} ({1})", TaxonFormatter.GetString(species, false), preySpecies.Count()); IEnumerable <Discord.Messaging.IEmbed> pages = EmbedUtilities.CreateEmbedPages(string.Empty, lines, columnsPerPage: 2, options: EmbedPaginationOptions.AddPageNumbers); Discord.Messaging.IPaginatedMessage message = new Discord.Messaging.PaginatedMessage(pages); message.SetTitle(title); await ReplyAsync(message); } else { await ReplyInfoAsync(string.Format("**{0}** does not prey upon any other species.", species.GetShortName())); } } }
public async Task Predates([Remainder] string speciesName) { speciesName = StringUtilities.StripOuterQuotes(speciesName); ISpecies species = await GetSpeciesOrReplyAsync(speciesName); if (species.IsValid()) { IEnumerable <IPredationInfo> predatorSpecies = (await Db.GetPredatorsAsync(species)) .Where(info => !info.Species.IsExtinct()) .OrderBy(info => info.Species.GetShortName()); if (predatorSpecies.Count() > 0) { Discord.Messaging.IEmbed embed = new Discord.Messaging.Embed(); List <string> lines = new List <string>(); foreach (IPredationInfo info in predatorSpecies) { string lineText = TaxonFormatter.GetString(info.Species); if (!string.IsNullOrEmpty(info.Notes)) { lineText += string.Format(" ({0})", info.Notes.ToLowerInvariant()); } lines.Add(lineText); } embed.Title = string.Format("Predators of {0} ({1})", TaxonFormatter.GetString(species, false), lines.Count()); embed.Description = string.Join(Environment.NewLine, lines); await ReplyAsync(embed); } else { await ReplyInfoAsync(string.Format("**{0}** has no extant natural predators.", species.GetShortName())); } } }
private async Task <IEnumerable <string> > GetNoPredatorIdeasAsync() { // Checks for species with no predators (that aren't themselves predators) List <string> ideas = new List <string>(); string query = @"SELECT * FROM Species WHERE id NOT IN (SELECT species_id FROM Extinctions) AND id NOT IN (SELECT eats_id FROM Predates) AND id NOT IN (SELECT species_id FROM Predates)" ; using (SQLiteCommand cmd = new SQLiteCommand(query)) foreach (DataRow row in await Db.GetRowsAsync(cmd)) { ISpecies species = await Db.CreateSpeciesFromDataRowAsync(row, GetSpeciesOptions.Default | GetSpeciesOptions.IgnoreStatus); ideas.Add($"There are no species that feed on {TaxonFormatter.GetString(species, false).ToBold()}. Why not make one?"); } return(ideas.ToArray()); }
private async Task ReplySetTaxonDescriptionAsync(ITaxon taxon) { if (taxon.IsValid()) { IMessage message = new Message($"Reply with the description for {taxon.GetRank().GetName()} **{TaxonFormatter.GetString(taxon, false)}**."); IResponsiveMessageResponse response = await ResponsiveMessageService.GetResponseAsync(Context, message); if (!response.Canceled) { await ReplySetTaxonDescriptionAsync(taxon, await GetDescriptionFromMessageAsync(response.Message)); } } }
public async Task Relationships([Remainder] string speciesName) { // Get the species from the DB. speciesName = StringUtilities.StripOuterQuotes(speciesName); ISpecies sp = await GetSpeciesOrReplyAsync(speciesName); if (!sp.IsValid()) { return; } // Get relationships and build the embed. SortedDictionary <string, List <string> > items = new SortedDictionary <string, List <string> >(); // Get relationships where this species is the one acting upon another. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM SpeciesRelationships LEFT JOIN Relationships ON SpeciesRelationships.relationship_id = Relationships.id WHERE species1_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); foreach (DataRow row in await Db.GetRowsAsync(cmd)) { long other_species_id = row.Field <long>("species2_id"); ISpecies other_species = await Db.GetSpeciesAsync(other_species_id); Relationship relationship = Relationship.FromDataRow(row); if (other_species is null) { continue; } if (!items.ContainsKey(relationship.BeneficiaryName(plural: true))) { items[relationship.BeneficiaryName(plural: true)] = new List <string>(); } items[relationship.BeneficiaryName(plural: true)].Add(TaxonFormatter.GetString(other_species)); } } // Get relationships where this species is the one being acted upon. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM SpeciesRelationships LEFT JOIN Relationships ON SpeciesRelationships.relationship_id = Relationships.id WHERE species2_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); foreach (DataRow row in await Db.GetRowsAsync(cmd)) { long other_species_id = row.Field <long>("species1_id"); ISpecies other_species = await Db.GetSpeciesAsync(other_species_id); Relationship relationship = Relationship.FromDataRow(row); if (other_species is null) { continue; } if (!items.ContainsKey(relationship.BenefactorName(plural: true))) { items[relationship.BenefactorName(plural: true)] = new List <string>(); } items[relationship.BenefactorName(plural: true)].Add(TaxonFormatter.GetString(other_species)); } } // Get any prey/predator relationships. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Predates WHERE species_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); foreach (DataRow row in await Db.GetRowsAsync(cmd)) { long other_species_id = row.Field <long>("eats_id"); ISpecies other_species = await Db.GetSpeciesAsync(other_species_id); if (other_species is null) { continue; } if (!items.ContainsKey("prey")) { items["prey"] = new List <string>(); } items["prey"].Add(TaxonFormatter.GetString(other_species)); } } using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Predates WHERE eats_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", sp.Id); foreach (DataRow row in await Db.GetRowsAsync(cmd)) { long other_species_id = row.Field <long>("species_id"); ISpecies other_species = await Db.GetSpeciesAsync(other_species_id); if (other_species is null) { continue; } if (!items.ContainsKey("predators")) { items["predators"] = new List <string>(); } items["predators"].Add(TaxonFormatter.GetString(other_species)); } } // If the species does not have any relationships with other species, state so. if (items.Count() <= 0) { await BotUtils.ReplyAsync_Info(Context, string.Format("**{0}** does not have any relationships with other species.", sp.GetShortName())); return; } // Build the embed. EmbedBuilder embed = new EmbedBuilder(); int relationship_count = 0; foreach (string key in items.Keys) { items[key].Sort((lhs, rhs) => lhs.CompareTo(rhs)); embed.AddField(string.Format("{0} ({1})", StringUtilities.ToTitleCase(key), items[key].Count()), string.Join(Environment.NewLine, items[key]), inline: true); relationship_count += items[key].Count(); } embed.WithTitle(string.Format("Relationships involving {0} ({1})", TaxonFormatter.GetString(sp, false), relationship_count)); await ReplyAsync("", false, embed.Build()); }
private TreeNode <NodeData> BuildTree(CladogramNode cladogramRoot) { TreeNode <NodeData> root = cladogramRoot.Copy(cladogramNodeData => new NodeData { Data = cladogramNodeData }); using (Font font = GetFont()) { // Measure the size of each node. float horizontalPadding = 5.0f; root.PostOrderTraverse(node => { SizeF size = DrawingUtilities.MeasureText(StringUtilities.StripMarkup(TaxonFormatter.GetString(node.Value.Data.Species)), font); node.Value.Bounds = new RectangleF(node.Value.Bounds.X, node.Value.Bounds.Y, size.Width + horizontalPadding, size.Height); }); // Calculate node positions. CalculateNodePositions(root); // Calculate the size of the tree. RectangleF bounds = CalculateTreeBounds(root); // Shift the tree so that the entire thing is visible. float minX = 0.0f; root.PostOrderTraverse(node => { if (node.Value.Bounds.X < minX) { minX = bounds.X; } }); ShiftTree(root, -minX, 0.0f); return(root); } }
// Private members private async Task ShowGalleryAsync(ISpecies species) { IEnumerable <IPicture> pictures = await Db.GetPicturesAsync(species); await ReplyGalleryAsync(TaxonFormatter.GetString(species, false), pictures); }
public async Task Stats() { // Get this user's gotchi. Gotchi gotchi = await Db.GetGotchiAsync(Context.User.ToCreator()); if (await this.ReplyValidateGotchiAsync(gotchi)) { ISpecies sp = await Db.GetSpeciesAsync(gotchi.SpeciesId); if (sp.IsValid()) { // Calculate stats for this gotchi. // If the user is currently in battle, show their battle stats instead. GotchiStats stats; GotchiBattleState battle_state = GotchiBattleState.GetBattleStateByUserId(Context.User.Id); if (!(battle_state is null)) { stats = battle_state.GetGotchiStats(gotchi); } else { stats = await new GotchiStatsCalculator(Db, Global.GotchiContext).GetStatsAsync(gotchi); } // Create the embed. EmbedBuilder stats_page = new EmbedBuilder(); stats_page.WithTitle(string.Format("{0}'s {2}, **Level {1}** (Age {3})", Context.User.Username, stats.Level, TaxonFormatter.GetString(sp, false), gotchi.Age)); stats_page.WithThumbnailUrl(sp.GetPictureUrl()); stats_page.WithFooter(string.Format("{0} experience points until next level", stats.ExperienceToNextLevel)); stats_page.AddField("❤ Hit points", stats.Hp, inline: true); stats_page.AddField("💥 Attack", stats.Atk, inline: true); stats_page.AddField("🛡 Defense", stats.Def, inline: true); stats_page.AddField("💨 Speed", stats.Spd, inline: true); await ReplyAsync(embed : stats_page.Build()); } }
private async Task ShowZoneAsync(IZone zone) { if (await this.ReplyValidateZoneAsync(zone)) { // Get all species living in this zone. List <ISpecies> speciesList = new List <ISpecies>((await Db.GetSpeciesAsync(zone)).Where(species => !species.IsExtinct())); speciesList.Sort((lhs, rhs) => TaxonFormatter.GetString(lhs, false).CompareTo(TaxonFormatter.GetString(rhs, false))); // Starting building a paginated message. // The message will have a paginated species list, and a toggle button to display the species sorted by role. string description = zone.GetDescriptionOrDefault(); if (!speciesList.Any()) { description += "\n\nThis zone does not contain any species."; } List <IEmbed> embedPages = new List <IEmbed>(); if (zone.Fields.Any()) { embedPages.Add(new Embed()); foreach (IZoneField field in zone.Fields) { if (!string.IsNullOrWhiteSpace(field.GetName()) && !string.IsNullOrWhiteSpace(field.GetValue())) { embedPages.Last().AddField(field.GetName(), field.GetValue(), true); } } embedPages.Last().Description = description; } embedPages.AddRange(EmbedUtilities.CreateEmbedPages(string.Format("Extant species in this zone ({0}):", speciesList.Count()), speciesList, formatter: TaxonFormatter)); // Add title, decription, etc., to all pages. if (!embedPages.Any()) { embedPages.Add(new Embed()); } IZoneType type = await Db.GetZoneTypeAsync(zone.TypeId) ?? new ZoneType(); string aliases = zone.Aliases.Any() ? string.Format("({0})", string.Join(", ", zone.Aliases.Select(alias => alias.ToTitle()))) : string.Empty; string title = string.Format("{0} {1} {2}", type.Icon, zone.GetFullName(), aliases).Trim(); System.Drawing.Color color = type.Color; foreach (IEmbed page in embedPages) { page.Title = title; page.ThumbnailUrl = zone.Pictures.FirstOrDefault()?.Url; page.Color = color; // Add the zone description to all pages if the zone doesn't have any fields (because the info page will be missing). if (!zone.Fields.Any()) { page.Description = description; } } IPaginatedMessage message = new PaginatedMessage(embedPages); message.AddPageNumbers(); // This page will have species organized by role. // Only bother with the role page if species actually exist in this zone. if (speciesList.Count() > 0) { IEmbed rolesPage = new Embed { Title = title, ThumbnailUrl = zone.GetPictureUrl(), Color = color }; Dictionary <string, List <ISpecies> > rolesMap = new Dictionary <string, List <ISpecies> >(); foreach (ISpecies species in speciesList) { IEnumerable <Common.Roles.IRole> roles_list = await Db.GetRolesAsync(species); if (roles_list.Count() <= 0) { if (!rolesMap.ContainsKey("no role")) { rolesMap["no role"] = new List <ISpecies>(); } rolesMap["no role"].Add(species); continue; } foreach (Common.Roles.IRole role in roles_list) { if (!rolesMap.ContainsKey(role.GetName())) { rolesMap[role.GetName()] = new List <ISpecies>(); } rolesMap[role.GetName()].Add(species); } } // Sort the list of species belonging to each role. foreach (List <ISpecies> i in rolesMap.Values) { i.Sort((lhs, rhs) => TaxonFormatter.GetString(lhs, false).CompareTo(TaxonFormatter.GetString(rhs, false))); } // Create a sorted list of keys so that the roles are in order. List <string> sorted_keys = new List <string>(rolesMap.Keys); sorted_keys.Sort(); foreach (string i in sorted_keys) { StringBuilder lines = new StringBuilder(); foreach (ISpecies j in rolesMap[i]) { lines.AppendLine(TaxonFormatter.GetString(j)); } rolesPage.AddField(string.Format("{0}s ({1})", StringUtilities.ToTitleCase(i), rolesMap[i].Count()), lines.ToString(), inline: true); } // Add the page to the builder. message.AddReaction("🇷", async(args) => { if (args.Emoji != "🇷") { return; } args.Message.PaginationEnabled = !args.ReactionAdded; if (args.ReactionAdded) { args.Message.CurrentPage = new Message() { Embed = rolesPage } } ; else { args.Message.CurrentPage = null; } await Task.CompletedTask; }); } await ReplyAsync(message); } }
private async Task <IEnumerable <string> > GetEmptyLineageIdeasAsync() { // Checks for species with empty lineage List <string> ideas = new List <string>(); using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Species WHERE id NOT IN (SELECT species_id FROM Ancestors) AND id NOT IN (SELECT ancestor_id FROM Ancestors) AND id NOT IN (SELECT species_id FROM Extinctions)")) foreach (DataRow row in await Db.GetRowsAsync(cmd)) { ideas.Add(string.Format("Species **{0}** does not have any descendants. Why not derive one?", TaxonFormatter.GetString(await Db.CreateSpeciesFromDataRowAsync(row), false))); } return(ideas.ToArray()); }