CompatibilityCsv.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using Gommon;
  2. using nietras.SeparatedValues;
  3. using Ryujinx.Ava.Common.Locale;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. namespace Ryujinx.Ava.Utilities.Compat
  9. {
  10. public class CompatibilityCsv
  11. {
  12. public static CompatibilityCsv Shared { get; set; }
  13. public CompatibilityCsv(SepReader reader)
  14. {
  15. var entries = new List<CompatibilityEntry>();
  16. foreach (var row in reader)
  17. {
  18. entries.Add(new CompatibilityEntry(reader.Header, row));
  19. }
  20. Entries = entries.Where(x => x.Status != null)
  21. .OrderBy(it => it.GameName).ToArray();
  22. }
  23. public CompatibilityEntry[] Entries { get; }
  24. }
  25. public class CompatibilityEntry
  26. {
  27. public CompatibilityEntry(SepReaderHeader header, SepReader.Row row)
  28. {
  29. IssueNumber = row[header.IndexOf("issue_number")].Parse<int>();
  30. var titleIdRow = row[header.IndexOf("extracted_game_id")].ToString();
  31. TitleId = !string.IsNullOrEmpty(titleIdRow)
  32. ? titleIdRow
  33. : default(Optional<string>);
  34. var issueTitleRow = row[header.IndexOf("issue_title")].ToString();
  35. if (TitleId.HasValue)
  36. issueTitleRow = issueTitleRow.ReplaceIgnoreCase($" - {TitleId}", string.Empty);
  37. GameName = issueTitleRow.Trim().Trim('"');
  38. IssueLabels = row[header.IndexOf("issue_labels")].ToString().Split(';');
  39. Status = row[header.IndexOf("extracted_status")].ToString().ToLower() switch
  40. {
  41. "playable" => LocaleKeys.CompatibilityListPlayable,
  42. "ingame" => LocaleKeys.CompatibilityListIngame,
  43. "menus" => LocaleKeys.CompatibilityListMenus,
  44. "boots" => LocaleKeys.CompatibilityListBoots,
  45. "nothing" => LocaleKeys.CompatibilityListNothing,
  46. _ => null
  47. };
  48. if (row[header.IndexOf("last_event_date")].TryParse<DateTime>(out var dt))
  49. LastEvent = dt;
  50. if (row[header.IndexOf("events_count")].TryParse<int>(out var eventsCount))
  51. EventCount = eventsCount;
  52. }
  53. public int IssueNumber { get; }
  54. public string GameName { get; }
  55. public Optional<string> TitleId { get; }
  56. public string[] IssueLabels { get; }
  57. public LocaleKeys? Status { get; }
  58. public DateTime LastEvent { get; }
  59. public int EventCount { get; }
  60. public string LocalizedStatus => LocaleManager.Instance[Status!.Value];
  61. public string FormattedTitleId => TitleId.OrElse(new string(' ', 16));
  62. public string FormattedIssueLabels => IssueLabels
  63. .Where(it => !it.StartsWithIgnoreCase("status"))
  64. .Select(FormatLabelName)
  65. .JoinToString(", ");
  66. public override string ToString()
  67. {
  68. var sb = new StringBuilder("CompatibilityEntry: {");
  69. sb.Append($"{nameof(IssueNumber)}={IssueNumber}, ");
  70. sb.Append($"{nameof(GameName)}=\"{GameName}\", ");
  71. sb.Append($"{nameof(TitleId)}={TitleId}, ");
  72. sb.Append($"{nameof(IssueLabels)}=\"{IssueLabels}\", ");
  73. sb.Append($"{nameof(Status)}=\"{Status}\", ");
  74. sb.Append($"{nameof(LastEvent)}=\"{LastEvent}\", ");
  75. sb.Append($"{nameof(EventCount)}={EventCount}");
  76. sb.Append('}');
  77. return sb.ToString();
  78. }
  79. public static string FormatLabelName(string labelName) => labelName.ToLower() switch
  80. {
  81. "audio" => "Audio",
  82. "bug" => "Bug",
  83. "cpu" => "CPU",
  84. "gpu" => "GPU",
  85. "gui" => "GUI",
  86. "help wanted" => "Help Wanted",
  87. "horizon" => "Horizon",
  88. "infra" => "Project Infra",
  89. "invalid" => "Invalid",
  90. "kernel" => "Kernel",
  91. "ldn" => "LDN",
  92. "linux" => "Linux",
  93. "macos" => "macOS",
  94. "question" => "Question",
  95. "windows" => "Windows",
  96. "graphics-backend:opengl" => "Graphics: OpenGL",
  97. "graphics-backend:vulkan" => "Graphics: Vulkan",
  98. "ldn-works" => "LDN Works",
  99. "ldn-untested" => "LDN Untested",
  100. "ldn-broken" => "LDN Broken",
  101. "ldn-partial" => "Partial LDN",
  102. "nvdec" => "NVDEC",
  103. "services" => "NX Services",
  104. "services-horizon" => "Horizon OS Services",
  105. "slow" => "Runs Slow",
  106. "crash" => "Crashes",
  107. "deadlock" => "Deadlock",
  108. "regression" => "Regression",
  109. "opengl" => "OpenGL",
  110. "opengl-backend-bug" => "OpenGL Backend Bug",
  111. "vulkan-backend-bug" => "Vulkan Backend Bug",
  112. "mac-bug" => "Mac-specific Bug(s)",
  113. "amd-vendor-bug" => "AMD GPU Bug",
  114. "intel-vendor-bug" => "Intel GPU Bug",
  115. "loader-allocator" => "Loader Allocator",
  116. "audout" => "AudOut",
  117. "32-bit" => "32-bit Game",
  118. "UE4" => "Unreal Engine 4",
  119. "homebrew" => "Homebrew Content",
  120. "online-broken" => "Online Broken",
  121. _ => Capitalize(labelName)
  122. };
  123. public static string Capitalize(string value)
  124. {
  125. if (value == string.Empty)
  126. return string.Empty;
  127. var firstChar = value[0];
  128. var rest = value[1..];
  129. return $"{char.ToUpper(firstChar)}{rest}";
  130. }
  131. }
  132. }