public String GetPropertyNameFor(MethodInfo method) { PropertyAccessor propertyAccessor = AnnotationUtil.GetAnnotation <PropertyAccessor>(method, true); if (propertyAccessor != null) { return(propertyAccessor.PropertyName); } Match matcher = getSetIsPattern.Match(method.Name); if (!matcher.Success) { return(""); } int paramLength = method.GetParameters().Length; String getSetIs = matcher.Groups[1].Value; if (("get_".Equals(getSetIs) || "Get".Equals(getSetIs) || "get".Equals(getSetIs)) && (0 != paramLength || typeof(void).Equals(method.ReturnType))) { return(""); } else if (("set_".Equals(getSetIs) || "Set".Equals(getSetIs) || "set".Equals(getSetIs)) && 1 != paramLength) { return(""); } else if (("Is".Equals(getSetIs) || "is".Equals(getSetIs)) && (0 != paramLength || typeof(void).Equals(method.ReturnType))) { return(""); } String name = matcher.Groups[2].Value; return(StringConversionHelper.UpperCaseFirst(name)); }
/// <summary> /// User command to see information on how to update projects. /// </summary> public void CMD_Update(string[] cmds, SocketMessage message) { if (cmds.Length == 0) { if (!Bot.ChannelToDetails.TryGetValue(message.Channel.Id, out ChannelDetails details) || details.Updates.Length == 0) { SendErrorMessageReply(message, "Unknown input for Update command", "Please specify which project(s) you want the update link for."); return; } foreach (ProjectDetails proj in details.Updates) { SendReply(message, proj.GetUpdateEmbed()); } return; } foreach (string projectName in cmds) { string projectNameLower = projectName.ToLowerFast(); if (Bot.ProjectToDetails.TryGetValue(projectNameLower, out ProjectDetails detail)) { SendReply(message, detail.GetUpdateEmbed()); } else { string closeName = StringConversionHelper.FindClosestString(Bot.ProjectToDetails.Keys, projectName, 20); SendErrorMessageReply(message, "Unknown project name for Update command", $"Unknown project name `{projectName.Replace('`', '\'')}`." + (closeName == null ? "" : $" Did you mean `{closeName}`?")); } } }
/// <summary> /// Admin command to end an existing vote. /// </summary> public void CMD_EndVote(string[] cmds, IUserMessage message) { if (!DemocracyBot.IsAdmin(message.Author)) { return; } FDSSection topicSection = VotingCommands.GetVoteTopicSection(cmds, message, out string topicName); if (topicSection == null) { return; } topicName = topicName.ToLowerFast(); Console.WriteLine($"Trying to end vote for {topicName} at {StringConversionHelper.DateTimeToString(DateTimeOffset.UtcNow, true)}"); FDSSection choicesSection = topicSection.GetSection("Choices"); Bot.ConfigFile.Set("old_topics." + StringConversionHelper.DateTimeToString(DateTimeOffset.UtcNow, true).Replace(".", "_") + "_topic_" + topicName.Replace(".", "_"), topicSection); string realKey = DemocracyBot.VoteTopicsSection.Data.Keys.First(s => s.ToLowerFast() == topicName); DemocracyBot.VoteTopicsSection.Remove(realKey); RefreshTopicData(topicName, topicSection, true); FDSSection userResultsSection = topicSection.GetSection("user_results"); tallyVotes(topicSection, choicesSection, userResultsSection, message, topicName, true); }
/// <summary> /// User command to see a link to the GitHub. /// </summary> public void CMD_Issues(string[] cmds, IUserMessage message) { if (DenizenMetaBot.ProjectToDetails.IsEmpty()) { return; } if (cmds.Length == 0) { if (!DenizenMetaBot.ChannelToDetails.TryGetValue(message.Channel.Id, out ChannelDetails details) || details.Updates.Length == 0) { SendErrorMessageReply(message, "Unknown input for Issues command", $"Please specify which project(s) you want the Issues link for, like `{DenizenMetaBotConstants.COMMAND_PREFIX}issues denizen`."); return; } SendReply(message, details.Updates[0].GetIssuesEmbed()); return; } foreach (string projectName in cmds) { string projectNameLower = projectName.ToLowerFast(); if (DenizenMetaBot.ProjectToDetails.TryGetValue(projectNameLower, out ProjectDetails detail)) { SendReply(message, detail.GetIssuesEmbed()); } else { string closeName = StringConversionHelper.FindClosestString(DenizenMetaBot.ProjectToDetails.Keys, projectName, 20); SendErrorMessageReply(message, "Unknown project name for Issues command", $"Unknown project name `{projectName.Replace('`', '\'')}`." + (closeName == null ? "" : $" Did you mean `{closeName}`?")); } } }
protected FieldInstance EnsureBackingField(IPropertyInfo propertyInfo) { FieldInfo backingField = propertyInfo.BackingField; FieldInstance f_backingField; if (backingField != null) { return(new FieldInstance(backingField)); } else if (propertyInfo.DeclaringType.IsInterface || propertyInfo.DeclaringType.Attributes.HasFlag(TypeAttributes.Abstract)) { String fieldName = StringConversionHelper.LowerCaseFirst(propertyInfo.Name); f_backingField = State.GetAlreadyImplementedField(fieldName); if (f_backingField == null) { // add field f_backingField = new FieldInstance(FieldAttributes.Family, StringConversionHelper.LowerCaseFirst(propertyInfo.Name), NewType.GetType(propertyInfo.PropertyType)); f_backingField = ImplementField(f_backingField); } return(f_backingField); } return(null); }
protected RelationConfigLegathy ReadRelationConfig(XElement relationElement, bool localEntity, bool toOne) { String relationName = XmlConfigUtil.GetRequiredAttribute(relationElement, XmlConstants.NAME, true); try { RelationConfigLegathy relationConfig = new RelationConfigLegathy(relationName, toOne); String linkedEntityName = XmlConfigUtil.GetRequiredAttribute(relationElement, XmlConstants.TARGET_ENTITY); Type linkedEntityType = XmlConfigUtil.GetTypeForName(linkedEntityName); relationConfig.LinkedEntityType = linkedEntityType; bool doDelete = XmlConfigUtil.AttributeIsTrue(relationElement, XmlConstants.DO_DELETE); relationConfig.DoDelete = doDelete; bool mayDelete = XmlConfigUtil.AttributeIsTrue(relationElement, XmlConstants.MAY_DELETE); relationConfig.MayDelete = mayDelete; if (localEntity) { XElement joinTableTag = XmlConfigUtil.GetChildUnique(relationElement, XmlConstants.JOIN_TABLE); if (joinTableTag == null) { String constraintName = XmlConfigUtil.GetAttribute(relationElement, XmlConstants.CONSTRAINT_NAME); if (constraintName.Length == 0 && !IndependentMetaData) { throw new ArgumentException("Either nested element '" + XmlConstants.JOIN_TABLE + "' or attribute '" + XmlConstants.CONSTRAINT_NAME + "' required to map link"); } relationConfig.ConstraintName = constraintName; } else { String joinTableName = XmlConfigUtil.GetRequiredAttribute(joinTableTag, XmlConstants.NAME); relationConfig.JoinTableName = joinTableName; String fromFieldName = XmlConfigUtil.GetChildElementAttribute(joinTableTag, XmlConstants.JOIN_COLUMN, XmlConstants.NAME, "Join column name has to be set exactly once"); relationConfig.FromFieldName = fromFieldName; String toFieldName = XmlConfigUtil.GetChildElementAttribute(joinTableTag, XmlConstants.INV_JOIN_COLUMN, XmlConstants.NAME, null); relationConfig.ToFieldName = toFieldName; String toAttributeName = XmlConfigUtil.GetChildElementAttribute(joinTableTag, XmlConstants.INV_JOIN_ATTR, XmlConstants.NAME, null); toAttributeName = StringConversionHelper.UpperCaseFirst(toAttributeName); relationConfig.ToAttributeName = toAttributeName; if (toFieldName == null && toAttributeName == null) { throw new ArgumentException("Inverse join column or attribute name has to be set"); } } } return(relationConfig); } catch (Exception e) { throw new Exception("Error occured while processing relation '" + relationName + "'", e); } }
/// <summary> /// Tag meta docs user command. /// </summary> public void CMD_Tag(string[] cmds, SocketMessage message) { List <string> secondarySearches = new List <string>(); if (cmds.Length > 0) { cmds[0] = MetaTag.CleanTag(cmds[0]); int dotIndex = cmds[0].IndexOf('.'); if (dotIndex > 0) { string tagBase = cmds[0].Substring(0, dotIndex); string tagSuffix = cmds[0].Substring(dotIndex); if (!tagBase.EndsWith("tag")) { secondarySearches.Add(tagBase + "tag" + tagSuffix); } string tagBaseLow = tagBase.ToLowerFast(); if (tagBaseLow == "player" || tagBaseLow == "npc" || tagBaseLow == "playertag" || tagBaseLow == "npctag") { secondarySearches.Add("entitytag" + tagSuffix); } secondarySearches.Add("elementtag" + tagSuffix); } } int getDistanceTo(MetaTag tag) { int dist1 = StringConversionHelper.GetLevenshteinDistance(cmds[0], tag.CleanedName); int dist2 = StringConversionHelper.GetLevenshteinDistance(cmds[0], tag.AfterDotCleaned); int dist = Math.Min(dist1, dist2); foreach (string secondSearch in secondarySearches) { int dist3 = StringConversionHelper.GetLevenshteinDistance(secondSearch, tag.CleanedName); dist = Math.Min(dist, dist3); } return(dist); } string findClosestTag() { int lowestDistance = 20; string lowestStr = null; foreach (MetaTag tag in Program.CurrentMeta.Tags.Values) { int currentDistance = getDistanceTo(tag); if (currentDistance < lowestDistance) { lowestDistance = currentDistance; lowestStr = tag.CleanedName; } } return(lowestStr); } AutoMetaCommand(Program.CurrentMeta.Tags, MetaDocs.META_TYPE_TAG, cmds, message, secondarySearches, altFindClosest: findClosestTag, altMatchOrderer: (list) => list.OrderBy(getDistanceTo).ToList()); }
// TODO: DurationTag, to represent spans of time. /// <summary>Get a time tag relevant to the specified input, erroring on the command system if invalid input is given (Returns null in that case!)</summary> /// <param name="input">The input text to create a time from.</param> /// <returns>The time tag, or null.</returns> public static TimeTag For(string input) { DateTimeOffset?dt = StringConversionHelper.StringToDateTime(input); if (dt == null) { return(null); } return(new TimeTag(dt.Value)); }
/// <summary> /// Converts a quick string of a Texture Coordinate set to an actual TextureCoordinates. /// </summary> /// <param name="str">The string.</param> /// <returns>The texture coordinates.</returns> public static TextureCoordinates FromString(string str) { TextureCoordinates tc = new TextureCoordinates(); string[] data = str.SplitFast('/'); tc.XScale = StringConversionHelper.StringToFloat(data[0]); tc.YScale = StringConversionHelper.StringToFloat(data[1]); tc.XShift = StringConversionHelper.StringToFloat(data[2]); tc.YShift = StringConversionHelper.StringToFloat(data[3]); tc.XFlip = data[4] == "t"; tc.YFlip = data[5] == "t"; return(tc); }
public MethodInfo GetMethod(Type serviceType) { if (method == null) { method = serviceType.GetMethod(StringConversionHelper.UpperCaseFirst(MethodName), ParamTypes); if (method == null) { method = serviceType.GetMethod(StringConversionHelper.LowerCaseFirst(MethodName), ParamTypes); } if (method == null) { throw new Exception("No matching method found on type " + serviceType.FullName + "'"); } } return(method); }
/// <summary> /// User command to get some predefined informational output. /// </summary> public void CMD_Info(string[] cmds, IUserMessage message) { if (DenizenMetaBot.InformationalData.IsEmpty()) { return; } if (cmds.Length == 0) { SendErrorMessageReply(message, "Command Syntax Incorrect", "`!info <info item or 'list'>`"); return; } if (cmds.Length > 5) { SendErrorMessageReply(message, "Command Syntax Incorrect", "Please request no more than 5 info items at a time."); return; } foreach (string searchRaw in cmds) { string commandSearch = searchRaw.ToLowerFast().Trim(); if (commandSearch == "list" || commandSearch == "all") { string fullList = "`" + string.Join("`, `", DenizenMetaBot.InformationalDataNames) + "`"; SendReply(message, new EmbedBuilder().WithThumbnailUrl(Constants.INFO_ICON).WithTitle("Available Info Names").WithDescription($"Available info names: {fullList}").Build()); } else if (DenizenMetaBot.InformationalData.TryGetValue(commandSearch, out string infoOutput)) { infoOutput = infoOutput.Trim(); if (infoOutput.StartsWith("NO_BOX:")) { infoOutput = infoOutput.Substring("NO_BOX:".Length).Trim(); message.Channel.SendMessageAsync("+++ Info `" + commandSearch + "`: " + infoOutput); } else { SendReply(message, new EmbedBuilder().WithThumbnailUrl(Constants.INFO_ICON).WithTitle($"Info: {commandSearch}").WithDescription(infoOutput).Build()); } } else { string closeName = StringConversionHelper.FindClosestString(DenizenMetaBot.InformationalData.Keys, commandSearch, 20); SendErrorMessageReply(message, "Cannot Display Info", "Unknown info name." + (closeName == null ? "" : $" Did you mean `{closeName}`?")); } } }
/// <summary>User command to see information on how to update projects.</summary> public void CMD_Update(CommandData command) { if (DenizenMetaBot.ProjectToDetails.IsEmpty()) { return; } if (command.CleanedArguments.Length == 0) { ulong chanId = command.Message.Channel is SocketThreadChannel thread ? thread.ParentChannel.Id : command.Message.Channel.Id; if (!DenizenMetaBot.ChannelToDetails.TryGetValue(chanId, out ChannelDetails details) || details.Updates.Length == 0) { SendErrorMessageReply(command.Message, "Unknown input for Update command", $"Please specify which project(s) you want the update link for, like `{DenizenMetaBotConstants.COMMAND_PREFIX}update denizen`."); return; } foreach (ProjectDetails proj in details.Updates) { SendReply(command.Message, proj.GetUpdateEmbed()); } return; } if (command.CleanedArguments.Length > 5) { SendErrorMessageReply(command.Message, "Command Syntax Incorrect", "Please request no more than 5 info items at a time."); return; } foreach (string projectName in command.CleanedArguments) { string projectNameLower = projectName.ToLowerFast(); if (DenizenMetaBot.ProjectToDetails.TryGetValue(projectNameLower, out ProjectDetails detail)) { SendReply(command.Message, detail.GetUpdateEmbed()); } else { string closeName = StringConversionHelper.FindClosestString(DenizenMetaBot.ProjectToDetails.Keys, projectName, 20); SendErrorMessageReply(command.Message, "Unknown project name for Update command", $"Unknown project name `{projectName.Replace('`', '\'')}`." + (closeName == null ? "" : $" Did you mean `{closeName}`?")); } } }
public void CMD_VoteStatus(string[] cmds, IUserMessage message) { if (!DemocracyBot.IsAdmin(message.Author)) { return; } FDSSection topicSection = VotingCommands.GetVoteTopicSection(cmds, message, out string topicName); if (topicSection == null) { return; } topicName = topicName.ToLowerFast(); Console.WriteLine($"Trying get vote status for {topicName} at {StringConversionHelper.DateTimeToString(DateTimeOffset.UtcNow, true)}"); FDSSection choicesSection = topicSection.GetSection("Choices"); string realKey = DemocracyBot.VoteTopicsSection.Data.Keys.First(s => s.ToLowerFast() == topicName); RefreshTopicData(topicName, topicSection, false); FDSSection userResultsSection = topicSection.GetSection("user_results"); tallyVotes(topicSection, choicesSection, userResultsSection, message, topicName, false); }
/// <summary> /// Mechanism meta docs user command. /// </summary> public void CMD_Mechanism(string[] cmds, SocketMessage message) { List <string> secondarySearches = new List <string>(); if (cmds.Length > 0) { int dotIndex = cmds[0].IndexOf('.'); if (dotIndex > 0) { secondarySearches.Add(cmds[0].Substring(0, dotIndex) + "tag" + cmds[0].Substring(dotIndex)); } } int closeness = AutoMetaCommand(Program.CurrentMeta.Mechanisms, MetaDocs.META_TYPE_MECHANISM, cmds, message, secondarySearches); if (closeness > 0) { string closeCmd = StringConversionHelper.FindClosestString(Program.CurrentMeta.Commands.Keys, cmds[0].ToLowerFast(), 7); if (closeCmd != null) { SendGenericPositiveMessageReply(message, "Possible Confusion", $"Did you mean to search for `command {closeCmd}`?"); } } }
/// <summary> /// Mechanism meta docs user command. /// </summary> public void CMD_Mechanism(string[] cmds, IUserMessage message) { List <string> secondarySearches = new List <string>(); if (cmds.Length > 0) { int dotIndex = cmds[0].IndexOf('.'); if (dotIndex > 0) { secondarySearches.Add(cmds[0].Substring(0, dotIndex) + "tag" + cmds[0].Substring(dotIndex)); } } int closeness = AutoMetaCommand(MetaDocs.CurrentMeta.Mechanisms, MetaDocs.META_TYPE_MECHANISM, cmds, message, secondarySearches); if (closeness > 0) { string closeCmd = StringConversionHelper.FindClosestString(MetaDocs.CurrentMeta.Commands.Keys, cmds[0].ToLowerFast(), 7); if (closeCmd != null) { SendDidYouMeanReply(message, "Possible Confusion", $"Did you mean to search for `command {closeCmd}`?", $"{DenizenMetaBotConstants.COMMAND_PREFIX}command {closeCmd}"); } } }
/// <summary> /// Command meta docs user command. /// </summary> public void CMD_Command(string[] cmds, SocketMessage message) { void singleReply(MetaCommand cmd) { if (cmds.Length >= 2) { string outputType = cmds[1].ToLowerFast(); if (outputType.StartsWith("u")) { SendReply(message, cmd.GetUsagesEmbed().Build()); } else if (outputType.StartsWith("t")) { SendReply(message, cmd.GetTagsEmbed().Build()); } else { SendErrorMessageReply(message, "Bad Command Syntax", "Second argument is unknown.\n\nUsage: `command [name] [usage/tags]`."); } } else { SendReply(message, cmd.GetEmbed().Build()); } } int closeness = AutoMetaCommand(Program.CurrentMeta.Commands, MetaDocs.META_TYPE_COMMAND, cmds, message, altSingleOutput: singleReply); if (closeness > 0) { string closeMech = StringConversionHelper.FindClosestString(Program.CurrentMeta.Mechanisms.Keys.Select(s => s.After('.')), cmds[0].ToLowerFast(), 10); if (closeMech != null) { SendGenericPositiveMessageReply(message, "Possible Confusion", $"Did you mean to search for `mechanism {closeMech}`?"); } } }
/// <summary> /// Loads an animation by name. /// </summary> /// <param name="name">The name.</param> /// <param name="Files">The file system.</param> /// <returns>The animation.</returns> SingleAnimation LoadAnimation(string name, FileEngine Files) { if (Files.TryReadFileText("animations/" + name + ".anim", out string fileText)) { SingleAnimation created = new SingleAnimation() { Name = name }; string[] data = fileText.SplitFast('\n'); int entr = 0; for (int i = 0; i < data.Length; i++) { if (data[i].StartsWith("//")) { continue; } string type = data[i]; if (data.Length <= i + 1 || data[i + 1] != "{") { break; } List <KeyValuePair <string, string> > entries = new List <KeyValuePair <string, string> >(); for (i += 2; i < data.Length; i++) { if (data[i].Trim().StartsWith("//")) { continue; } if (data[i] == "}") { break; } string[] dat = data[i].SplitFast(':'); if (dat.Length <= 1) { SysConsole.Output(OutputType.WARNING, "Invalid key dat: " + dat[0]); } else { string key = dat[0].Trim(); string value = dat[1].Substring(0, dat[1].Length - 1).Trim(); entries.Add(new KeyValuePair <string, string>(key, value)); } } bool isgeneral = type == "general" && entr == 0; SingleAnimationNode node = null; if (!isgeneral) { node = new SingleAnimationNode() { Name = type.ToLowerFast() }; } foreach (KeyValuePair <string, string> entry in entries) { if (isgeneral) { if (entry.Key == "length") { created.Length = StringConversionHelper.StringToDouble(entry.Value); } else { SysConsole.Output(OutputType.WARNING, "Unknown GENERAL key: " + entry.Key); } } else { if (entry.Key == "positions") { string[] poses = entry.Value.SplitFast(' '); for (int x = 0; x < poses.Length; x++) { if (poses[x].Length > 0) { string[] posdata = poses[x].SplitFast('='); node.PosTimes.Add(StringConversionHelper.StringToDouble(posdata[0])); node.Positions.Add(new Location(StringConversionHelper.StringToFloat(posdata[1]), StringConversionHelper.StringToFloat(posdata[2]), StringConversionHelper.StringToFloat(posdata[3]))); } } } else if (entry.Key == "rotations") { string[] rots = entry.Value.SplitFast(' '); for (int x = 0; x < rots.Length; x++) { if (rots[x].Length > 0) { string[] posdata = rots[x].SplitFast('='); node.RotTimes.Add(StringConversionHelper.StringToDouble(posdata[0])); node.Rotations.Add(new BEPUutilities.Quaternion(StringConversionHelper.StringToFloat(posdata[1]), StringConversionHelper.StringToFloat(posdata[2]), StringConversionHelper.StringToFloat(posdata[3]), StringConversionHelper.StringToFloat(posdata[4]))); } } } else if (entry.Key == "parent") { node.ParentName = entry.Value.ToLowerFast(); } else if (entry.Key == "offset") { string[] posdata = entry.Value.SplitFast('='); node.Offset = new Location(StringConversionHelper.StringToFloat(posdata[0]), StringConversionHelper.StringToFloat(posdata[1]), StringConversionHelper.StringToFloat(posdata[2])); } else { SysConsole.Output(OutputType.WARNING, "Unknown NODE key: " + entry.Key); } } } if (!isgeneral) { created.Nodes.Add(node); created.node_map.Add(node.Name, node); } entr++; } foreach (SingleAnimationNode node in created.Nodes) { for (int i = 0; i < created.Nodes.Count; i++) { if (created.Nodes[i].Name == node.ParentName) { node.Parent = created.Nodes[i]; break; } } } created.Engine = this; return(created); } else { throw new Exception("Invalid animation file - file not found: animations/" + name + ".anim"); } }
protected void PopulateDropdownLists() { float minValue = 1F; float stepValue = 1f; int totSteps = 25; ListItem item; GfxUnit unit = (GfxUnit)Enum.Parse(typeof(GfxUnit), this.ddlUnit.SelectedValue); switch (unit) { case GfxUnit.Pixel: stepValue = 20F; break; case GfxUnit.Point: stepValue = 15F; break; case GfxUnit.Pica: stepValue = 1F; break; case GfxUnit.Inch: stepValue = 0.2F; break; case GfxUnit.Mm: stepValue = 5F; break; case GfxUnit.Cm: stepValue = 0.5F; break; } minValue = stepValue; this.ddlConstraint_Fixed_Width.Items.Clear(); this.ddlConstraint_Fixed_Height.Items.Clear(); for (int i = 0; i < totSteps; i++) { float value = minValue + Convert.ToSingle(i) * stepValue; string valueString = StringConversionHelper.SingleToString(value); item = new ListItem(valueString, valueString); if (i == 14) { item.Selected = true; } this.ddlConstraint_Fixed_Width.Items.Add(item); item = new ListItem(valueString, valueString); if (i == 9) { item.Selected = true; } this.ddlConstraint_Fixed_Height.Items.Add(item); } this.ddlConstraint_FixedAspectRatio_Min.Items.Clear(); this.ddlConstraint_FixedAspectRatio_Max.Items.Clear(); for (int i = 0; i < totSteps; i++) { float value = minValue + Convert.ToSingle(i) * stepValue; string valueString = StringConversionHelper.SingleToString(value); item = new ListItem(valueString, valueString); if (i == 0) { item.Selected = true; } this.ddlConstraint_FixedAspectRatio_Min.Items.Add(item); item = new ListItem(valueString, valueString); if (i == (totSteps - 1)) { item.Selected = true; } this.ddlConstraint_FixedAspectRatio_Max.Items.Add(item); } this.ddlConstraint_Free_Width_Min.Items.Clear(); this.ddlConstraint_Free_Width_Max.Items.Clear(); this.ddlConstraint_Free_Height_Min.Items.Clear(); this.ddlConstraint_Free_Height_Max.Items.Clear(); for (int i = 0; i < totSteps; i++) { float value = minValue + Convert.ToSingle(i) * stepValue; string valueString = StringConversionHelper.SingleToString(value); item = new ListItem(valueString, valueString); if (i == 0) { item.Selected = true; } this.ddlConstraint_Free_Width_Min.Items.Add(item); item = new ListItem(valueString, valueString); if (i == (totSteps - 1)) { item.Selected = true; } this.ddlConstraint_Free_Width_Max.Items.Add(item); item = new ListItem(valueString, valueString); if (i == 0) { item.Selected = true; } this.ddlConstraint_Free_Height_Min.Items.Add(item); item = new ListItem(valueString, valueString); if (i == (totSteps - 1)) { item.Selected = true; } this.ddlConstraint_Free_Height_Max.Items.Add(item); } minValue = 0F; totSteps = 101; this.ddlMarginsH.Items.Clear(); item = new ListItem("Auto", ""); item.Selected = true; this.ddlMarginsH.Items.Add(item); this.ddlMarginsV.Items.Clear(); item = new ListItem("Auto", ""); item.Selected = true; this.ddlMarginsV.Items.Add(item); for (int i = 0; i < totSteps; i++) { float value = minValue + Convert.ToSingle(i) * stepValue; string valueString = StringConversionHelper.SingleToString(value); item = new ListItem(valueString, valueString); this.ddlMarginsH.Items.Add(item); item = new ListItem(valueString, valueString); this.ddlMarginsV.Items.Add(item); } if (this.ddlConstraint_FixedAspectRatio_X.Items.Count == 0) { totSteps = 100; for (int i = 1; i <= totSteps; i++) { string valueString = StringConversionHelper.Int32ToString(i); item = new ListItem(valueString, valueString); if (i == 16) { item.Selected = true; } this.ddlConstraint_FixedAspectRatio_X.Items.Add(item); item = new ListItem(valueString, valueString); if (i == 9) { item.Selected = true; } this.ddlConstraint_FixedAspectRatio_Y.Items.Add(item); } } }
/// <summary> /// Automatically processes a meta search command. /// </summary> /// <typeparam name="T">The meta object type.</typeparam> /// <param name="docs">The docs mapping.</param> /// <param name="type">The meta type.</param> /// <param name="cmds">The command args.</param> /// <param name="message">The Discord message object.</param> /// <param name="secondarySearches">A list of secondary search strings if the first fails.</param> /// <param name="secondaryMatcher">A secondary matching function if needed.</param> /// <param name="altSingleOutput">An alternate method of processing the single-item-result.</param> /// <param name="altFindClosest">Alternate method to find the closest result.</param> /// <returns>How close of an answer was gotten (0 = perfect, -1 = no match needed, 1000 = none).</returns> public int AutoMetaCommand <T>(Dictionary <string, T> docs, MetaType type, string[] cmds, SocketMessage message, List <string> secondarySearches = null, Func <T, bool> secondaryMatcher = null, Action <T> altSingleOutput = null, Func <string> altFindClosest = null, Func <List <T>, List <T> > altMatchOrderer = null) where T : MetaObject { if (CheckMetaDenied(message)) { return(-1); } if (cmds.Length == 0) { SendErrorMessageReply(message, $"Need input for '{type.Name}' command", $"Please specify a {type.Name} to search, like `!{type.Name} Some{type.Name}Here`. Or, use `!{type.Name} all` to view all documented {type.Name.ToLowerFast()}s."); return(-1); } string search = cmds[0].ToLowerFast(); if (search == "all") { SendGenericPositiveMessageReply(message, $"All {type.Name}s", $"Find all {type.Name}s at {Constants.DOCS_URL_BASE}{type.WebPath}/"); return(-1); } if (altSingleOutput == null) { altSingleOutput = (singleObj) => SendReply(message, singleObj.GetEmbed().Build()); } if (altFindClosest == null) { altFindClosest = () => { string initialPossibleResult = StringConversionHelper.FindClosestString(docs.Keys, search, out int lowestDistance, 20); string lowestStr = null; foreach (string possibleName in docs.Values.Where(o => o.HasMultipleNames).SelectMany(o => o.MultiNames)) { int currentDistance = StringConversionHelper.GetLevenshteinDistance(search, possibleName); if (currentDistance < lowestDistance) { lowestDistance = currentDistance; lowestStr = possibleName; } } return(lowestStr); }; } if (altMatchOrderer == null) { altMatchOrderer = (list) => list.OrderBy((mat) => StringConversionHelper.GetLevenshteinDistance(search, mat.CleanName)).ToList(); } if (docs.TryGetValue(search, out T obj)) { string multiNameData = string.Join("', '", obj.MultiNames); Console.WriteLine($"Meta-Command for '{type.Name}' found perfect match for search '{search}': '{obj.CleanName}', multi={obj.HasMultipleNames}='{multiNameData}'"); altSingleOutput(obj); return(0); } if (secondarySearches != null) { secondarySearches = secondarySearches.Select(s => s.ToLowerFast()).ToList(); foreach (string secondSearch in secondarySearches) { if (docs.TryGetValue(secondSearch, out obj)) { Console.WriteLine($"Meta-Command for '{type.Name}' found perfect match for secondary search '{secondSearch}': '{obj.CleanName}', multi={obj.HasMultipleNames}"); altSingleOutput(obj); return(0); } } } List <T> matched = new List <T>(); List <T> strongMatched = new List <T>(); int tryProcesSingleMatch(T objVal, string objName, int min) { if (objName.Contains(search)) { Console.WriteLine($"Meta-Command for '{type.Name}' found a strong match (main contains) for search '{search}': '{objName}'"); strongMatched.Add(objVal); return(2); } if (secondarySearches != null) { foreach (string secondSearch in secondarySearches) { if (objName.Contains(secondSearch)) { Console.WriteLine($"Meta-Command for '{type.Name}' found a strong match (secondary contains) for search '{secondSearch}': '{objName}'"); strongMatched.Add(objVal); return(2); } } } if (min < 1 && secondaryMatcher != null && secondaryMatcher(objVal)) { Console.WriteLine($"Meta-Command for '{type.Name}' found a weak match (secondaryMatcher) for search '{search}': '{objName}'"); matched.Add(objVal); return(1); } return(min); } foreach (KeyValuePair <string, T> objPair in docs) { if (objPair.Value.HasMultipleNames) { int matchQuality = 0; foreach (string name in objPair.Value.MultiNames) { matchQuality = tryProcesSingleMatch(objPair.Value, name, matchQuality); if (matchQuality == 2) { break; } } } else { tryProcesSingleMatch(objPair.Value, objPair.Key, 0); } } if (strongMatched.Count > 0) { matched = strongMatched; } if (matched.Count == 0) { string closeName = altFindClosest(); SendErrorMessageReply(message, $"Cannot Find Searched {type.Name}", $"Unknown {type.Name.ToLowerFast()}." + (closeName == null ? "" : $" Did you mean `{closeName}`?")); return(closeName == null ? 1000 : StringConversionHelper.GetLevenshteinDistance(search, closeName)); } else if (matched.Count > 1) { matched = altMatchOrderer(matched); string suffix = "."; if (matched.Count > 20) { matched = matched.GetRange(0, 20); suffix = ", ..."; } string listText = string.Join("`, `", matched.Select((m) => m.Name)); SendErrorMessageReply(message, $"Cannot Specify Searched {type.Name}", $"Multiple possible {type.Name.ToLowerFast()}s: `{listText}`{suffix}"); return(StringConversionHelper.GetLevenshteinDistance(search, matched[0].CleanName)); } else // Count == 1 { obj = matched[0]; Console.WriteLine($"Meta-Command for '{type.Name}' found imperfect single match for search '{search}': '{obj.CleanName}', multi={obj.HasMultipleNames}"); altSingleOutput(obj); return(0); } }
/// <summary> /// Meta docs total search command. /// </summary> public void CMD_Search(string[] cmds, SocketMessage message) { if (CheckMetaDenied(message)) { return; } if (cmds.Length == 0) { SendErrorMessageReply(message, "Need input for Search command", "Please specify some text to search, like `!search someobjecthere`."); return; } for (int i = 0; i < cmds.Length; i++) { cmds[i] = cmds[i].ToLowerFast(); } string fullSearch = string.Join(' ', cmds); List <MetaObject> strongMatch = new List <MetaObject>(); List <MetaObject> partialStrongMatch = new List <MetaObject>(); List <MetaObject> weakMatch = new List <MetaObject>(); List <MetaObject> partialWeakMatch = new List <MetaObject>(); foreach (MetaObject obj in Program.CurrentMeta.AllMetaObjects()) { if (obj.CleanName.Contains(fullSearch)) { strongMatch.Add(obj); continue; } foreach (string word in cmds) { if (obj.CleanName.Contains(word)) { partialStrongMatch.Add(obj); goto fullContinue; } } if (obj.Searchable.Contains(fullSearch)) { weakMatch.Add(obj); continue; } if (fullSearch.Contains(obj.CleanName)) { partialWeakMatch.Add(obj); continue; } foreach (string word in cmds) { if (obj.Searchable.Contains(word)) { partialWeakMatch.Add(obj); goto fullContinue; } } fullContinue: continue; } if (strongMatch.IsEmpty() && partialStrongMatch.IsEmpty() && weakMatch.IsEmpty() && partialWeakMatch.IsEmpty()) { SendErrorMessageReply(message, "Search Command Has No Results", "Input search text could not be found."); return; } string suffix = "."; void listWrangle(string typeShort, string typeLong, List <MetaObject> objs) { objs = objs.OrderBy((obj) => StringConversionHelper.GetLevenshteinDistance(fullSearch, obj.CleanName)).ToList(); suffix = "."; if (objs.Count > 20) { objs = objs.GetRange(0, 20); suffix = ", ..."; } string listText = string.Join("`, `", objs.Select((obj) => $"!{obj.Type.Name} {obj.CleanName}")); SendGenericPositiveMessageReply(message, $"{typeShort} Search Results", $"{typeShort} ({typeLong}) search results: `{listText}`{suffix}"); } if (strongMatch.Any()) { listWrangle("Best", "very close", strongMatch); } if (partialStrongMatch.Any()) { listWrangle("Probable", "close but imperfect", partialStrongMatch); if (strongMatch.Any()) { return; } } if (weakMatch.Any()) { listWrangle("Possible", "might be related", weakMatch); if (strongMatch.Any() || partialStrongMatch.Any()) { return; } } if (partialWeakMatch.Any()) { listWrangle("Weak", "if nothing else, some chance of being related", partialWeakMatch); } }
/// <summary> /// Admin command to end an existing vote. /// </summary> public void CMD_EndVote(string[] cmds, IUserMessage message) { if (!DemocracyBot.IsAdmin(message.Author)) { return; } FDSSection topicSection = VotingCommands.GetVoteTopicSection(cmds, message, out string topicName); if (topicSection == null) { return; } topicName = topicName.ToLowerFast(); Console.WriteLine($"Trying to end vote for {topicName} at {StringConversionHelper.DateTimeToString(DateTimeOffset.UtcNow, true)}"); FDSSection choicesSection = topicSection.GetSection("Choices"); Bot.ConfigFile.Set("old_topics." + StringConversionHelper.DateTimeToString(DateTimeOffset.UtcNow, true).Replace(".", "_") + "_topic_" + topicName.Replace(".", "_"), topicSection); string realKey = DemocracyBot.VoteTopicsSection.Data.Keys.First(s => s.ToLowerFast() == topicName); DemocracyBot.VoteTopicsSection.Remove(realKey); RefreshTopicData(topicName, topicSection, true); FDSSection userResultsSection = topicSection.GetSection("user_results"); if (userResultsSection == null || userResultsSection.GetRootKeys().IsEmpty()) { SendGenericNegativeMessageReply(message, $"Vote For Topic {topicName} Failed", "No votes were cast."); DemocracyBot.Save(); return; } List <List <string> > voteSets = new List <List <string> >(50); foreach (string userId in userResultsSection.GetRootKeys()) { List <string> choices = userResultsSection.GetStringList(userId); if (choices != null && !choices.IsEmpty() && !(choices.Count == 1 && choices[0] == "none")) { voteSets.Add(choices); } } if (voteSets.IsEmpty()) { SendGenericNegativeMessageReply(message, $"Vote For Topic {topicName} Failed", "No votes were cast."); DemocracyBot.Save(); return; } int usersWhoVotedTotal = voteSets.Count; Dictionary <string, int> votesTracker = new Dictionary <string, int>(128); string winner = voteSets[0][0]; string secondPlace = voteSets[0][0]; int discards = 0; bool haveWinner = false; string winnerStats = "(error: stats missing)"; string secondPlaceStats = "(error: second place missing)"; string gatherStats(string choice, string type) { int numberHadFirst = 0; int positionTotal = 0; int numberHadAtAll = 0; foreach (string userId in userResultsSection.GetRootKeys()) { List <string> choices = userResultsSection.GetStringList(userId); if (choices != null && !choices.IsEmpty()) { int index = choices.IndexOf(choice); if (index != -1) { numberHadAtAll++; positionTotal += index + 1; if (index == 0) { numberHadFirst++; } } } } return($"Options that were discarded due to low support: {discards}\n" + $"Users whose votes were discarded due to supporting only unpopular options: {usersWhoVotedTotal - voteSets.Count}\nUsers who listed the {type} first: {numberHadFirst}\n" + $"Users who listed the {type} at all: {numberHadAtAll}\nAverage ranking of the {type}: {positionTotal / (float)numberHadAtAll:0.0}"); } while (true) { votesTracker.Clear(); foreach (List <string> voteSet in voteSets) { string vote = voteSet[0]; if (!votesTracker.TryGetValue(vote, out int count)) { count = 0; } votesTracker[vote] = count + 1; } if (votesTracker.Count == 0) { Console.WriteLine("Something went funky in vote counting... tracker is empty without a clear winner!"); break; } string best = voteSets[0][0], worst = voteSets[0][0]; int bestCount = 0, worstCount = int.MaxValue; foreach (KeyValuePair <string, int> voteResult in votesTracker) { if (voteResult.Value > bestCount) { best = voteResult.Key; bestCount = voteResult.Value; } if (voteResult.Value < worstCount) { worst = voteResult.Key; worstCount = voteResult.Value; } } if (bestCount * 2 > voteSets.Count) { if (!haveWinner) { winner = best; winnerStats = gatherStats(winner, "winner"); haveWinner = true; for (int i = 0; i < voteSets.Count; i++) { if (voteSets[i].Contains(winner)) { voteSets[i].Remove(winner); if (voteSets[i].IsEmpty()) { voteSets.RemoveAt(i--); } } } worst = winner; } else { secondPlace = best; secondPlaceStats = gatherStats(secondPlace, "runner up"); break; } } for (int i = 0; i < voteSets.Count; i++) { if (voteSets[i][0] == worst) { voteSets[i].RemoveAt(0); if (voteSets[i].IsEmpty()) { voteSets.RemoveAt(i--); } } } if (!haveWinner) { discards++; } } SendGenericPositiveMessageReply(message, $"Vote Results For **{topicName}: {topicSection.GetString("Topic")}**", $"**__Winner__**: **{winner}**: `{choicesSection.GetString(winner)}`" + $"\n\n**Stats:**\nUsers who voted, in total: {usersWhoVotedTotal}\n{winnerStats}\n\n" + $"**__Runner Up__**: **{secondPlace}**: `{choicesSection.GetString(secondPlace)}`\n**Stats For Runner Up**:\n{secondPlaceStats}"); DemocracyBot.Save(); }