using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using Godot; using Godot.Collections; using openF1Manager.scripts; public static class ApiModelSerializer { public static string ToQueryString(object model, string baseAddress) { var query = System.Web.HttpUtility.ParseQueryString(string.Empty); foreach (var (key, value) in EnumerateKeyValues(model)) { if (!string.IsNullOrWhiteSpace(value)) query[key] = value; } var queryString = query.ToString(); return string.IsNullOrEmpty(queryString) ? baseAddress : $"{baseAddress}?{queryString}"; } public static void PopulateFromDictionary(object model, Godot.Collections.Dictionary dict) { var type = model.GetType(); foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (!prop.CanWrite) continue; var attr = prop.GetCustomAttribute(); var key = attr?.Key ?? ToSnakeCase(prop.Name); // Try snake_case first, then camelCase fallbacks if (!TryGet(dict, key, out var str) && !TryGet(dict, SnakeToCamel(key), out str)) continue; // You can add type conversions if needed; here we only set strings if (prop.PropertyType == typeof(string) || prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(int) || prop.PropertyType == typeof(float)) prop.SetValue(model, str); } } private static bool TryGet(Dictionary dict, string key, out string value) { if (dict.ContainsKey(key) && dict[key].VariantType != Variant.Type.Nil) { value = dict[key].ToString(); return true; } value = string.Empty; return false; } private static IEnumerable<(string Key, string Value)> EnumerateKeyValues(object model) { var type = model.GetType(); foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (!prop.CanRead) continue; var value = prop.GetValue(model)?.ToString(); var attr = prop.GetCustomAttribute(); var key = attr?.Key ?? ToSnakeCase(prop.Name); yield return (key, value); } } private static string ToSnakeCase(string name) { var sb = new StringBuilder(); for (int i = 0; i < name.Length; i++) { var c = name[i]; sb.Append(i > 0 && char.IsUpper(c) ? "_" + char.ToLower(c) : c.ToString()); } return sb.ToString(); } private static string SnakeToCamel(string name) { var sb = new StringBuilder(); sb.Append(char.ToLower(name[0])); for (int i = 1; i < name.Length; i++) { var c = name[i]; sb.Append(char.IsUpper(c) ? char.ToLower(c) : c); } return sb.ToString(); } }