Skip to content

Instantly share code, notes, and snippets.

@syntax-tm
Last active March 19, 2021 16:30
Show Gist options
  • Save syntax-tm/82f775e82065a5ab2d7f159fd56d882c to your computer and use it in GitHub Desktop.
Save syntax-tm/82f775e82065a5ab2d7f159fd56d882c to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
private const string USER_NAME = "username";
// INSTRUCTIONS:
//
// 1. Change the above value in quotes from 'username' to a valid username
// 2. Click 'Run'
//
// You might have to click this more than once due to the max execution
// time for these scripts being lower than the time it takes to run. So running
// it again without a big delay will usually perform the API calls quicker
// since it's a REST API and they should be cached.
//
// tl;dr: Click 'Run' again if nothing shows up
//
// If you have any questions about this or whatever else, you can contact me via:
//
// DuckDice : nonon
// Discord : Gundwn#6651
// don't change anything below here (unless you want to)
private const int COLUMN_WIDTH = 30;
private const int FIAT_COLUMN_WIDTH = 18;
private const int CRYPTO_PRECISION = 8;
private const char USD_SYMBOL = '$';
private const char EURO_SYMBOL = '€';
private const string CURRENCY_URI = "https://duckdice.io/api/currencies";
private const string USER_SEARCH_URI = "https://duckdice.io/api/user/search/{0}";
private const string USER_STATS_URI = "https://duckdice.io/api/user/{0}/{1}";
private static Dictionary<string, DuckDiceCurrency> _currencies = new();
private static ConcurrentDictionary<string, DuckDiceUserStats> _wagered = new();
public static void Main()
{
try
{
var userHash = GetUserHash(USER_NAME);
InitCurrencies();
Parallel.ForEach(_currencies.Keys, symbol =>
{
var currency = _currencies[symbol];
var wagered = GetUserWageredStat(userHash, currency);
_wagered.TryAdd(symbol, wagered);
});
// everything after this is just formatting since there are certain
// assemblies that aren't usable with this online compiler for security reasons
// and the formatting is all done manually (which sucks)
var sb = new StringBuilder();
var sortedKeys = _wagered.Values
.OrderByDescending(w => w.WageredUsd)
.ThenBy(w => w.Currency)
.Select(w => w.Currency);
foreach (var key in sortedKeys)
{
var userStats = _wagered[key];
var amountFmt = ToCryptoFormat(userStats.Wagered, userStats.Currency);
var usdFormat = ToFiatFormat(userStats.WageredUsd, USD_SYMBOL);
var euroFormat = ToFiatFormat(userStats.WageredEuro, EURO_SYMBOL);
sb.AppendLine($"{amountFmt} | {usdFormat} | {euroFormat}");
}
var firstLine = sb.ToString().Split(Environment.NewLine)[0];
var lineLength = firstLine.Length;
var border = string.Empty.PadLeft(lineLength, '─');
var header = $"User: {USER_NAME} ({userHash})".PadLeft(lineLength, ' ');
var usdTotal = _wagered.Values.Sum(w => w.WageredUsd);
var euroTotal = _wagered.Values.Sum(w => w.WageredEuro);
var usdTotalText = ToFiatFormat(usdTotal, USD_SYMBOL);
var euroTotalText = ToFiatFormat(usdTotal, EURO_SYMBOL);
var totalSpacing = string.Empty.PadLeft(COLUMN_WIDTH + 3, ' ');
Console.WriteLine(header);
Console.WriteLine(border);
Console.WriteLine(sb);
Console.WriteLine(border);
Console.WriteLine($"{totalSpacing}{usdTotalText} | {euroTotalText}");
}
catch (Exception e)
{
var message = e is ArgumentException ? e.Message : e.ToString();
Console.WriteLine(message);
}
}
private static string GetUserHash(string userName)
{
try
{
var requestUri = string.Format(USER_SEARCH_URI, userName);
using var client = new HttpClient();
var response = client.GetStringAsync(requestUri).Result;
var doc = JArray.Parse(response);
var user = doc.First(e => e.Value<string>("username").Equals(USER_NAME, StringComparison.InvariantCultureIgnoreCase));
var hash = user.Value<string>("hash");
return hash;
}
catch (Exception e)
{
throw new ArgumentException($"Unable to find the user '{USER_NAME}'. Please check the spelling and try again.", e);
}
}
public static DuckDiceUserStats GetUserWageredStat(string userHash, DuckDiceCurrency currency)
{
var requestUri = string.Format(USER_STATS_URI, userHash, currency.Symbol);
using var client = new HttpClient();
var response = client.GetStringAsync(requestUri).Result;
var doc = JObject.Parse(response);
var wagered = double.Parse(doc["volume"].ToString());
var stats = new DuckDiceUserStats
{
UserHash = userHash,
CurrencyInfo = currency,
Wagered = wagered
};
return stats;
}
private static string ToFiatFormat(double amount, char currencySymbol, int maxChars = FIAT_COLUMN_WIDTH)
{
var amountDisplayText = amount == 0
? "-"
: amount.ToString("N2");
var formattedAmount = amountDisplayText.PadLeft(maxChars, ' ');
var displayAmount = $"{currencySymbol}{formattedAmount}";
return displayAmount;
}
private static string ToCryptoFormat(double amount, string label, int precision = CRYPTO_PRECISION, int maxChars = COLUMN_WIDTH)
{
var amountStringFormat = $"N{precision}";
var amountDisplayText = amount == 0
? "-"
: amount.ToString(amountStringFormat);
var labelFormat = label.PadLeft(4, ' ');
var formattedValue = $"{amountDisplayText} {labelFormat}";
return formattedValue.PadLeft(maxChars, ' ');
}
private static void InitCurrencies()
{
using var client = new HttpClient();
var currencyResponseText = client.GetStringAsync(CURRENCY_URI).Result;
var currencyResponse = JsonConvert.DeserializeObject<DuckDiceCurrency[]>(currencyResponseText);
_currencies = currencyResponse.ToDictionary(currency => currency.Symbol);
}
public class DuckDiceUserStats
{
public string UserHash { get; set; }
public DuckDiceCurrency CurrencyInfo { get; set; }
public double Wagered { get; set; }
public string Currency => CurrencyInfo.Symbol;
public double WageredUsd => Wagered * CurrencyInfo.PriceUsd;
public double WageredEuro => Wagered * CurrencyInfo.PriceEuro;
}
public class DuckDiceCurrency
{
public string Symbol { get; set; }
public string Name { get; set; }
public double PriceUsd { get; set; }
public double PriceEuro { get; set; }
public double PriceBtc { get; set; }
public override string ToString() => Symbol;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment