diff --git a/Bot/Bot.fs b/Bot/Bot.fs index 80c1884..a6997f3 100644 --- a/Bot/Bot.fs +++ b/Bot/Bot.fs @@ -3,11 +3,9 @@ module Degenz.Bot open System.IO open System.Threading.Tasks open DSharpPlus -open DSharpPlus.Entities open DSharpPlus.SlashCommands open Degenz open Emzi0767.Utilities -open Degenz.SlotMachine type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule () diff --git a/Bot/Bot.fsproj b/Bot/Bot.fsproj index 25120a6..ede526a 100644 --- a/Bot/Bot.fsproj +++ b/Bot/Bot.fsproj @@ -76,5 +76,8 @@ + + + - \ No newline at end of file + diff --git a/Bot/Games/Store.fs b/Bot/Games/Store.fs index aa1af10..4b8ef74 100644 --- a/Bot/Games/Store.fs +++ b/Bot/Games/Store.fs @@ -1,6 +1,7 @@ module Degenz.Store open System +open System.Data open System.Threading.Tasks open DSharpPlus.Entities open DSharpPlus @@ -9,6 +10,7 @@ open DSharpPlus.SlashCommands open Degenz open Degenz.Messaging open Degenz.PlayerInteractions +open DataTablePrettyPrinter let checkHasStock (item : StoreItem) player = if item.Stock > 0 || item.LimitStock = false @@ -53,24 +55,28 @@ let getItemEmbeds owned (items : StoreItem list) = |> List.map (fun (id,count) -> items |> List.find (fun i -> i.Item.Id = id) , count ) |> List.map (fun (item,count) -> let embed = DiscordEmbedBuilder() + use table = new DataTable() + table.SetBorder(Border.None) + table.SetShowTableName(false) + let values : ResizeArray = ResizeArray() if not owned && item.LimitStock then - embed.AddField("Stock", $"{item.Stock}", true) |> ignore + values.Add("Stock", $"{item.Stock}") item.Item.Attributes |> List.iter (function - | Buyable price -> embed.AddField("Price 💰", (if price = 0 then "Free" else $"{price} $GBT"), true) |> ignore + | Buyable price -> + values.Add("Price 💰", (if price = 0 then "Free" else $"{price} $GBT")) | Attackable power -> let title = match item.Item.Type with ItemType.Hack -> "$GBT Reward" | _ -> "Power" - embed.AddField($"{title} |", string power, true) |> ignore + values.Add($"{title}", string power) | RateLimitable time -> let title = match item.Item.Type with ItemType.Hack -> "Cooldown" | ItemType.Shield -> "Active For" | _ -> "Expires" let ts = TimeSpan.FromMinutes(int time) let timeStr = if ts.Hours = 0 then $"{ts.Minutes} mins" else $"{ts.Hours} hours" - embed.AddField($"{title} |", timeStr, true) |> ignore + values.Add($"{title}", timeStr) | Stackable max -> - if owned then - embed.AddField($"Total Owned |", $"{count}", true) |> ignore - else - embed.AddField($"Max Allowed |", $"{max}", true) |> ignore + if owned + then values.Add($"Total Owned", $"{count}") + else values.Add($"Max Allowed", $"{max}") | Modifiable effects -> let fx = effects @@ -83,10 +89,23 @@ let getItemEmbeds owned (items : StoreItem list) = $"{f.TargetStat} {str} + {i}" | RateMultiplier i -> $"{f.TargetStat} Multiplier - i") |> String.concat "\n" - embed.AddField($"Effect - Amount ", $"{fx}", true) |> ignore + values.Add($"Effect - Amount", $"{fx}") | _ -> ()) + for title , _ in values do + let column = table.Columns.Add(title) + column.SetWidth(40 / values.Count) + column.SetDataAlignment(TextAlignment.Center) + column.SetHeaderBorder(Border.Bottom) + column.SetDataBorder(Border.Top) + + let arr : obj array = values |> Seq.map snd |> Seq.cast |> Seq.toArray + table.Rows.Add(arr) |> ignore + + let split = table.ToPrettyPrintedString().Split("\n") + let text = split |> Array.skip 1 |> Array.take (split.Length - 3) |> String.concat "\n" embed .WithColor(WeaponClass.getClassEmbedColor item.Item) + .WithDescription($"```{text}```") .WithTitle($"{item.Item.Name}") |> ignore if String.IsNullOrWhiteSpace(item.Item.IconUrl) diff --git a/Bot/paket.references b/Bot/paket.references index 0fd3028..63d3ff0 100644 --- a/Bot/paket.references +++ b/Bot/paket.references @@ -4,4 +4,4 @@ DSharpPlus.Interactivity DSharpPlus.SlashCommands dotenv.net Npgsql.FSharp -mixpanel-csharp +mixpanel-csharp \ No newline at end of file diff --git a/DataTablePrettyPrinter/Border.cs b/DataTablePrettyPrinter/Border.cs new file mode 100644 index 0000000..3d3c701 --- /dev/null +++ b/DataTablePrettyPrinter/Border.cs @@ -0,0 +1,43 @@ +namespace DataTablePrettyPrinter +{ + using System; + using System.Data; + + /// + /// Enumerates the border flags of the text represented by a which is to be drawn on a + /// pretty printed string. + /// + [Flags] + public enum Border + { + /// + /// No border. + /// + None = 0, + + /// + /// Bottom border. + /// + Bottom = 1, + + /// + /// Left border. + /// + Left = 2, + + /// + /// Right border. + /// + Right = 4, + + /// + /// Top border. + /// + Top = 8, + + /// + /// All borders. + /// + All = 15, + } +} diff --git a/DataTablePrettyPrinter/CharExtensions.cs b/DataTablePrettyPrinter/CharExtensions.cs new file mode 100644 index 0000000..dc755af --- /dev/null +++ b/DataTablePrettyPrinter/CharExtensions.cs @@ -0,0 +1,213 @@ +namespace DataTablePrettyPrinter +{ + using System; + + /// + /// An extension class providing utility methods for pretty printing to a string. + /// + internal static class CharExtensions + { + /// + /// Draws a border on a canvas given a bounding box specified by coordinates. + /// + /// + /// + /// The canvas to draw on which is assumed to be large enough. + /// + /// + /// + /// The x coordinate of the beginning of the bounding box to draw. + /// + /// + /// + /// The y coordinate of the beginning of the bounding box to draw. + /// + /// + /// + /// The x coordinate of the end of the bounding box to draw. + /// + /// + /// + /// The y coordinate of the end of the bounding box to draw. + /// + /// + /// + /// The border flags which dictate which border to draw. + /// + internal static void DrawBorder(this char[,] canvas, int x1, int y1, int x2, int y2, Border border) + { + if (border.HasFlag(Border.Top)) + { + canvas.DrawLine(x1, y1, x2, y1); + } + + if (border.HasFlag(Border.Bottom)) + { + canvas.DrawLine(x1, y2, x2, y2); + } + + if (border.HasFlag(Border.Left)) + { + canvas.DrawLine(x1, y1, x1, y2); + } + + if (border.HasFlag(Border.Right)) + { + canvas.DrawLine(x2, y1, x2, y2); + } + } + + /// + /// Draws a line on a canvas given a beginning and an end coordinate. + /// + /// + /// + /// The canvas to draw on which is assumed to be large enough. + /// + /// + /// + /// The x coordinate of the beginning of the line to draw. + /// + /// + /// + /// The y coordinate of the beginning of the line to draw. + /// + /// + /// + /// The x coordinate of the end of the line to draw. + /// + /// + /// + /// The y coordinate of the end of the line to draw. + /// + /// + /// + /// If this line crosses any other line drawn on the canvas then a '+' is inserted on the crossing boundary. + /// + /// + /// + /// Thrown when the line is neither horizontal nor vertical. + /// + internal static void DrawLine(this char[,] canvas, int x1, int y1, int x2, int y2) + { + if (x1 != x2 && y1 != y2) + { + throw new ArgumentException("Cannot draw non-horizontal or non-vertical lines"); + } + + if (x1 == x2) + { + if (y1 > y2) + { + Utilities.Swap(ref y1, ref y2); + } + + for (var y = y1; y <= y2; ++y) + { + canvas[y, x1] = (y == y1 || y == y2 || canvas[y, x1] == '─' || canvas[y, x1] == '+') ? '+' : '|'; + } + } + else + { + if (x1 > x2) + { + Utilities.Swap(ref x1, ref x2); + } + + for (var x = x1; x <= x2; ++x) + { + canvas[y1, x] = (x == x1 || x == x2 || canvas[y1, x] == '|' || canvas[y1, x] == '+') ? ' ' : '─'; + } + } + } + + /// + /// Draws a string on a canvas with alignment specified. + /// + /// + /// + /// The canvas to draw on which is assumed to be large enough. + /// + /// + /// + /// The x coordinate of the beginning of the string to draw. + /// + /// + /// + /// The y coordinate of the beginning of the string to draw. + /// + /// + /// + /// The x coordinate of the end of the string to draw. + /// + /// + /// + /// The y coordinate of the end of the string to draw. + /// + /// + /// + /// The text to draw. + /// + /// + /// + /// The alignment of the to draw. + /// + /// + /// + /// If the text cannot be contained within the bounding box specified by the coordinates then either nothing is + /// drawn or the input string is truncated and '..' is added to the end. + /// + internal static void DrawText(this char[,] canvas, int x1, int y1, int x2, int y2, string text, TextAlignment alignment) + { + // Truncate the text if it will not fit in the text box bounds + if (text.Length > x2 - x1 + 1) + { + if (x2 - x1 >= 1) + { + text = text.Substring(0, x2 - x1 - 1) + ".."; + } + else + { + return; + } + } + + // Update the coordinates based the text alignment + switch (alignment) + { + case TextAlignment.Center: + { + y1 = (y2 + y1) / 2; + x1 += (x2 - x1 + 1 - text.Length) / 2; + + break; + } + + case TextAlignment.Left: + { + y1 = (y2 + y1) / 2; + + break; + } + + case TextAlignment.Right: + { + y1 = (y2 + y1) / 2; + x1 = x2 - text.Length + 1; + + break; + } + + default: + { + throw new InvalidOperationException("Unreachable case reached"); + } + } + + for (var x = x1; x < x1 + text.Length; ++x) + { + canvas[y1, x] = text[x - x1]; + } + } + } +} diff --git a/DataTablePrettyPrinter/DataColumnExtensions.cs b/DataTablePrettyPrinter/DataColumnExtensions.cs new file mode 100644 index 0000000..cffb755 --- /dev/null +++ b/DataTablePrettyPrinter/DataColumnExtensions.cs @@ -0,0 +1,403 @@ +namespace DataTablePrettyPrinter +{ + using System; + using System.Data; + using System.Linq; + + /// + /// An extension class providing utility methods for pretty printing to a string. + /// + public static class DataColumnExtensions + { + /// + /// Gets the border around the data area of the column. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The border around the data area of the column. + /// + public static Border GetDataBorder(this DataColumn column) + { + return column.GetExtendedProperty("DataBorder", Border.All); + } + + /// + /// Sets the border around the data area of the column. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetDataBorder(this DataColumn column, Border value) + { + column.SetExtendedProperty("DataBorder", value); + } + + /// + /// Gets the text alignment of the data in this column. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// Gets the data alignment. + /// + public static TextAlignment GetDataAlignment(this DataColumn column) + { + return column.GetExtendedProperty("DataAlignment", TextAlignment.Left); + } + + /// + /// Sets the text alignment of the data in this column. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetDataAlignment(this DataColumn column, TextAlignment value) + { + column.SetExtendedProperty("DataAlignment", value); + } + + /// + /// Gets the formatting method which given a column and row formats the data of the cell into a string. This + /// API can be used for arbitrary formatting of induvidual data cells. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The method which formats the data cell. + /// + public static Func GetDataTextFormat(this DataColumn column) + { + return column.GetExtendedProperty>("DataTextFormat", (c, r) => string.Format("{0}", r[c])); + } + + /// + /// Sets the formatting method which given a column and row formats the data of the cell into a string. This + /// API can be used for arbitrary formatting of induvidual data cells. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The method used to format the data cell which will be called during pretty printing of the table. + /// + public static void SetDataTextFormat(this DataColumn column, Func value) + { + column.SetExtendedProperty("DataTextFormat", value); + } + + /// + /// Gets the border around the column header area which displays the column names. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The border around the column header area. + /// + public static Border GetHeaderBorder(this DataColumn column) + { + return column.GetExtendedProperty("HeaderBorder", Border.All); + } + + /// + /// Sets the border around the column header area which displays the column names. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetHeaderBorder(this DataColumn column, Border value) + { + column.SetExtendedProperty("HeaderBorder", value); + } + + /// + /// Gets the text alignment. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// Gets the column name text alignment. + /// + public static TextAlignment GetColumnNameAlignment(this DataColumn column) + { + return column.GetExtendedProperty("ColumnNameAlignment", TextAlignment.Center); + } + + /// + /// Sets the text alignment. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetColumnNameAlignment(this DataColumn column, TextAlignment value) + { + column.SetExtendedProperty("ColumnNameAlignment", value); + } + + /// + /// Gets whether to show the . + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// true if the column name is to be shown; false otherwise. + /// + public static bool GetShowColumnName(this DataColumn column) + { + return column.GetExtendedProperty("ShowColumnName", true); + } + + /// + /// Sets whether to show the . + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetShowColumnName(this DataColumn column, bool value) + { + column.SetExtendedProperty("ShowColumnName", value); + } + + /// + /// Gets the width (in characters) of this column as it would appear on the pretty printed table. + /// + /// + /// + /// The input column. + /// + /// + /// + /// The width (in characters) of this column which is retrieved either by user defined value or the aggregate + /// maximum width of any row in the table. + /// + public static int GetWidth(this DataColumn column) + { + if (column.ExtendedProperties.ContainsKey("Width")) + { + return (int)column.ExtendedProperties["Width"]; + } + else + { + var columnNameLength = 1; + + if (column.GetShowColumnName()) + { + columnNameLength = column.ColumnName.Length; + } + + // Linq.Max cannot handle empty sequences + if (column.Table.Rows.Count == 0) + { + return columnNameLength + 2; + } + else + { + return Math.Max(columnNameLength, column.Table.Rows.Cast().Max(r => column.GetDataTextFormat().Invoke(column, r).Length)) + 2; + } + } + } + + /// + /// Sets the width (in characters) of this column as it would appear on the pretty printed table. + /// + /// + /// + /// The input column. + /// + /// + /// + /// The value to set which will be clamped to be at least 1. + /// + public static void SetWidth(this DataColumn column, int value) + { + value = Math.Max(1, value); + + column.SetExtendedProperty("Width", value); + } + + /// + /// Gets the beginning X coordinate of the data area of this column. + /// + /// + /// + /// The input column. + /// + /// + /// + /// The X coordinate of the beginning of the data area. + /// + internal static int GetDataX1(this DataColumn column) + { + var columnIndex = column.Table.Columns.IndexOf(column); + + return column.Table.Columns.Cast().Take(columnIndex).Aggregate(0, (a, c) => a + c.GetWidth() + 1); + } + + /// + /// Gets the end X coordinate of the data area of this column. + /// + /// + /// + /// The input column. + /// + /// + /// + /// The X coordinate of the end of the data area. + /// + internal static int GetDataX2(this DataColumn column) + { + return column.GetDataX1() + 1 + column.GetWidth(); + } + + /// + /// Gets the beginning Y coordinate of the data area of this column. + /// + /// + /// + /// The input column. + /// + /// + /// + /// The Y coordinate of the beginning of the data area. + /// + internal static int GetDataY1(this DataColumn column) + { + // Account for the top border + var y1 = 1; + + // Account for the title and a rule following the title + if (column.Table.GetShowTableName()) + { + y1 += 2; + } + + // Account for the header and a rule following the header + if (column.Table.GetShowColumnHeader()) + { + y1 += 2; + } + + return y1; + } + + /// + /// Gets the end Y coordinate of the data area of this column. + /// + /// + /// + /// The input column. + /// + /// + /// + /// The Y coordinate of the end of the data area. + /// + internal static int GetDataY2(this DataColumn column) + { + return column.GetDataY1() + column.Table.Rows.Cast().Aggregate(0, (a, r) => a + r.GetHeight()); + } + + /// + /// Gets an extended property from the with a default value if it does not exist. + /// + /// + /// + /// The type of the value to get. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The extended property to get. + /// + /// + /// + /// The default value to return if the extended property does not exist. + /// + /// + /// + /// The value of the extended property if it exists; otherwise. + /// + internal static T GetExtendedProperty(this DataColumn column, string property, T defaultValue = default) + { + if (column.ExtendedProperties[property] is T) + { + return (T)column.ExtendedProperties[property]; + } + else + { + return defaultValue; + } + } + + /// + /// Sets an extended property from the . + /// + /// + /// + /// The type of the value to get. + /// + /// + /// + /// The column to pretty print. + /// + /// + /// + /// The extended property to set. + /// + /// + /// + /// The value to set. + /// + internal static void SetExtendedProperty(this DataColumn column, string property, T value) + { + column.ExtendedProperties[property] = value; + } + } +} diff --git a/DataTablePrettyPrinter/DataRowExtensions.cs b/DataTablePrettyPrinter/DataRowExtensions.cs new file mode 100644 index 0000000..5daa93e --- /dev/null +++ b/DataTablePrettyPrinter/DataRowExtensions.cs @@ -0,0 +1,46 @@ +namespace DataTablePrettyPrinter +{ + using System; + using System.Data; + using System.Linq; + + /// + /// An extension class providing utility methods for pretty printing to a string. + /// + internal static class DataRowExtensions + { + /// + /// Gets the width (in characters) of this row as it would appear on the pretty printed table by aggregating + /// the widths of each individual column. + /// + /// + /// + /// The input row. + /// + /// + /// + /// The width (in characters) of this row. + /// + internal static int GetWidth(this DataRow row) + { + return row.Table.Columns.Cast().Aggregate(0, (a, c) => a + c.GetWidth() + 1) - 1; + } + + /// + /// Gets the height (in characters) of this row as it would appear on the pretty printed table by aggregating + /// the heights of each individual column. + /// + /// + /// + /// The input row. + /// + /// + /// + /// The height (in characters) of this row. + /// + internal static int GetHeight(this DataRow row) + { + return 1; + } + } +} diff --git a/DataTablePrettyPrinter/DataTableExtensions.cs b/DataTablePrettyPrinter/DataTableExtensions.cs new file mode 100644 index 0000000..8b93a75 --- /dev/null +++ b/DataTablePrettyPrinter/DataTableExtensions.cs @@ -0,0 +1,308 @@ +namespace DataTablePrettyPrinter +{ + using System; + using System.Data; + using System.Linq; + + /// + /// An extension class providing utility methods for pretty printing to a string. + /// + public static class DataTableExtensions + { + /// + /// Gets the border around the entire table. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The border around the entire table. + /// + public static Border GetBorder(this DataTable table) + { + return table.GetExtendedProperty("Border", Border.All); + } + + /// + /// Sets the border around the entire table. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetBorder(this DataTable table, Border value) + { + table.SetExtendedProperty("Border", value); + } + + /// + /// Gets whether to show the column header section which shows the column names. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// true if the column header is to be shown; false otherwise. + /// + public static bool GetShowColumnHeader(this DataTable table) + { + return table.GetExtendedProperty("ShowColumnHeader", true); + } + + /// + /// Sets whether to show the column header section which shows the column names. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetShowColumnHeader(this DataTable table, bool value) + { + table.SetExtendedProperty("ShowColumnHeader", value); + } + + /// + /// Gets whether to show the . + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// true if the table title is to be shown; false otherwise. + /// + public static bool GetShowTableName(this DataTable table) + { + return table.GetExtendedProperty("ShowTableName", true); + } + + /// + /// Sets whether to show the . + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetShowTableName(this DataTable table, bool value) + { + table.SetExtendedProperty("ShowTableName", value); + } + + /// + /// Gets the text alignment of the title determined by the property. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// Gets the title text alignment. + /// + public static TextAlignment GetTitleTextAlignment(this DataTable table) + { + return table.GetExtendedProperty("TitleTextAlignment", TextAlignment.Center); + } + + /// + /// Sets the text alignment of the title determined by the property. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The value to set. + /// + public static void SetTitleTextAlignment(this DataTable table, TextAlignment value) + { + table.SetExtendedProperty("TitleTextAlignment", value); + } + + /// + /// Converts the into pretty printed string which can be displayed on the console. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The pretty printed table. + /// + public static string ToPrettyPrintedString(this DataTable table) + { + int x2 = table.Columns.Cast().Last().GetDataX2(); + int y2 = table.Columns.Cast().Last().GetDataY2(); + + char[] newLineChars = Environment.NewLine.ToCharArray(); + char[,] canvas = new char[y2 + 1, x2 + 1 + newLineChars.Length]; + + // Fill the table with spaces and new lines at the end of each row + for (var y = 0; y < y2 + 1; ++y) + { + for (var x = 0; x < x2 + 1; ++x) + { + canvas[y, x] = ' '; + } + + for (var i = 0; i < newLineChars.Length; ++i) + { + canvas[y, x2 + 1 + i] = newLineChars[i]; + } + } + + // Draw the table border + canvas.DrawBorder(0, 0, x2, y2, table.GetBorder()); + + // Keep track of the x and y coordinates we are drawing on + int x1 = 0; + int y1 = 0; + + if (table.GetShowTableName()) + { + ++y1; + + var titleAlignment = table.GetTitleTextAlignment(); + canvas.DrawText(2, y1, x2 - 2, y1, table.TableName, titleAlignment); + + ++y1; + } + + // Cache the column widths for performance + var cachedColumnWidths = table.Columns.Cast().Select(c => c.GetWidth()).ToList(); + + if (table.GetShowColumnHeader()) + { + x1 = 0; + + for (var i = 0; i < table.Columns.Count; ++i) + { + // Draw the header border + canvas.DrawBorder(x1, y1, x1 + cachedColumnWidths[i] + 1, y1 + 2, table.Columns[i].GetHeaderBorder()); + + if (table.Columns[i].GetShowColumnName()) + { + // Draw the header name + canvas.DrawText(x1 + 2, y1 + 1, x1 + 1 + cachedColumnWidths[i] - 2, y1 + 1, table.Columns[i].ColumnName, table.Columns[i].GetColumnNameAlignment()); + } + + x1 += cachedColumnWidths[i] + 1; + } + + y1 += 2; + } + + x1 = 0; + + for (var i = 0; i < table.Columns.Count; ++i) + { + // Draw the data border + canvas.DrawBorder(x1, y1, x1 + cachedColumnWidths[i] + 1, y1 + table.Rows.Count + 1, table.Columns[i].GetDataBorder()); + + x1 += cachedColumnWidths[i] + 1; + } + + ++y1; + + for (var i = 0; i < table.Rows.Count; ++i) + { + x1 = 2; + + for (var j = 0; j < table.Columns.Count; ++j) + { + var dataText = table.Columns[j].GetDataTextFormat().Invoke(table.Columns[j], table.Rows[i]); + + // Draw the cell text + canvas.DrawText(x1, y1, x1 + cachedColumnWidths[j] - 3, y1, dataText, table.Columns[j].GetDataAlignment()); + + x1 += cachedColumnWidths[j] + 1; + } + + ++y1; + } + + var buffer = new char[canvas.GetLength(0) * canvas.GetLength(1)]; + Buffer.BlockCopy(canvas, 0, buffer, 0, buffer.Length * sizeof(char)); + + return new string(buffer); + } + + /// + /// Gets an extended property from the with a default value if it does not exist. + /// + /// + /// + /// The type of the value to get. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The extended property to get. + /// + /// + /// + /// The default value to return if the extended property does not exist. + /// + /// + /// + /// The value of the extended property if it exists; otherwise. + /// + internal static T GetExtendedProperty(this DataTable table, string property, T defaultValue = default) + { + if (table.ExtendedProperties[property] is T) + { + return (T)table.ExtendedProperties[property]; + } + else + { + return defaultValue; + } + } + + /// + /// Sets an extended property from the . + /// + /// + /// + /// The type of the value to get. + /// + /// + /// + /// The table to pretty print. + /// + /// + /// + /// The extended property to set. + /// + /// + /// + /// The value to set. + /// + internal static void SetExtendedProperty(this DataTable table, string property, T value) + { + table.ExtendedProperties[property] = value; + } + } +} diff --git a/DataTablePrettyPrinter/DataTablePrettyPrinter.csproj b/DataTablePrettyPrinter/DataTablePrettyPrinter.csproj new file mode 100644 index 0000000..cd337c3 --- /dev/null +++ b/DataTablePrettyPrinter/DataTablePrettyPrinter.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.0 + Filip Jeremic + LICENSE + An extension library of System.Data.DataTable which provides extension methods for fully customizable pretty-printing of DataTable to an ASCII formatted string which can be displayed on the console or any text buffer. + https://github.com/fjeremic/DataTablePrettyPrinter + https://github.com/fjeremic/DataTablePrettyPrinter + GitHub + DataTable;Print;PrettyPrint;Pretty-Print;Console;SQL + 0.2.0 + Release notes: +https://github.com/fjeremic/DataTablePrettyPrinter/releases + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/DataTablePrettyPrinter/GlobalSuppressions.cs b/DataTablePrettyPrinter/GlobalSuppressions.cs new file mode 100644 index 0000000..ee9ff67 --- /dev/null +++ b/DataTablePrettyPrinter/GlobalSuppressions.cs @@ -0,0 +1,11 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1404:Code analysis suppression should have justification")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines")] diff --git a/DataTablePrettyPrinter/TextAlignment.cs b/DataTablePrettyPrinter/TextAlignment.cs new file mode 100644 index 0000000..550eae5 --- /dev/null +++ b/DataTablePrettyPrinter/TextAlignment.cs @@ -0,0 +1,26 @@ +namespace DataTablePrettyPrinter +{ + using System.Data; + + /// + /// Enumerates the alignment of the text represented by a which is to be pretty printing to + /// a string. + /// + public enum TextAlignment + { + /// + /// Text is centered. + /// + Center, + + /// + /// Text is aligned to the left. + /// + Left, + + /// + /// Text is aligned to the right. + /// + Right, + } +} diff --git a/DataTablePrettyPrinter/Utilities.cs b/DataTablePrettyPrinter/Utilities.cs new file mode 100644 index 0000000..a58d3ec --- /dev/null +++ b/DataTablePrettyPrinter/Utilities.cs @@ -0,0 +1,31 @@ +namespace DataTablePrettyPrinter +{ + /// + /// A utility class with miscellaneous methods. + /// + internal static class Utilities + { + /// + /// Swaps the values of and . + /// + /// + /// + /// The type of the values to swap. + /// + /// + /// + /// The value to swap with . + /// + /// + /// + /// The value to swap with . + /// + internal static void Swap(ref T x, ref T y) + { + T z = x; + + x = y; + y = z; + } + } +} diff --git a/DegenzGame.sln b/DegenzGame.sln index c77e294..280f021 100644 --- a/DegenzGame.sln +++ b/DegenzGame.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30114.105 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Bot", "Bot\Bot.fsproj", "{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataTablePrettyPrinter", "DataTablePrettyPrinter\DataTablePrettyPrinter.csproj", "{4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -18,5 +20,13 @@ Global {FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Debug|Any CPU.Build.0 = Debug|Any CPU {FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.ActiveCfg = Release|Any CPU {FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.Build.0 = Release|Any CPU + {44151B85-0D17-4270-AD72-490A6D8D6290}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44151B85-0D17-4270-AD72-490A6D8D6290}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44151B85-0D17-4270-AD72-490A6D8D6290}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44151B85-0D17-4270-AD72-490A6D8D6290}.Release|Any CPU.Build.0 = Release|Any CPU + {4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/paket.dependencies b/paket.dependencies index d60c377..25cbd7d 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -12,4 +12,4 @@ nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01125 nuget MongoDB.Driver nuget dotenv.net 3.1.1 nuget Npgsql.FSharp -nuget mixpanel-csharp 5.0.0 +nuget mixpanel-csharp 5.0.0 \ No newline at end of file