public void NoMatchJunkString() { bool result = FriendCode.TryParse("aaa", out FriendCode friendCode); Assert.AreEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsFalse(result); }
int applicationFriend = 3; //id2向id1申请好友 private int TransformFriendType(FriendCode code) { switch (code) { case FriendCode.MyFriend: return(myFriend); break; case FriendCode.AddFriend: return(noFriend); break; case FriendCode.FriendApplication: return(applicationFriend); break; default: return(0); break; } }
public void NegativeTestStripFCFromName2() { var(friendCode, stripped) = FriendCode.ParseAndStripFriendCode("0123SomeSquid4567"); Assert.AreEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsNotNull(stripped); Assert.AreEqual("0123SomeSquid4567", stripped); }
public void NegativeTestStripFCFromName3() { var(friendCode, stripped) = FriendCode.ParseAndStripFriendCode("Ludic--<"); Assert.AreEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsNotNull(stripped); Assert.AreEqual("Ludic--<", stripped); }
public void NoMatchJunkDigitsString() { bool result = FriendCode.TryParse("0123456789101112", out FriendCode friendCode); Assert.AreEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsFalse(result); }
public void StripFCInsideName2() { var(friendCode, stripped) = FriendCode.ParseAndStripFriendCode("My name 1234 - 5678 - 9012"); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsNotNull(stripped); Assert.AreEqual("1234-5678-9012", friendCode.ToString()); Assert.AreEqual("My name", stripped); }
public void StripFCInsideName() { var(friendCode, stripped) = FriendCode.ParseAndStripFriendCode(":) Some pleb (SW: 0123-4567-8912)"); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsNotNull(stripped); Assert.AreEqual("0123 4567 8912", friendCode.ToString(" ")); Assert.AreEqual(":) Some pleb", stripped); }
public void FCInsideOtherTextShouldParse() { bool success = FriendCode.TryParse("This is a player name believe it or not with the fc 0123-4567-8912?", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(success); Assert.AreEqual("0123.4567.8912", friendCode.ToString(".")); }
public void MatchFCStringWithLabel2() { bool success = FriendCode.TryParse("SW-1234-5678-4321", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(success); Assert.AreEqual("1234-5678-4321", friendCode.ToString()); }
public void SeparatorTest() { bool success = FriendCode.TryParse("5555.6789 7890", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(success); Assert.AreEqual("5555/6789/7890", friendCode.ToString("/")); }
public void MatchFCString() { bool result = FriendCode.TryParse("3333-4444-5555", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(result); Assert.AreEqual("3333-4444-5555", friendCode.ToString()); }
public void MatchFCStringWithLabel() { bool success = FriendCode.TryParse("SW: 3456.7654.9876", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(success); Assert.AreEqual("3456-7654-9876", friendCode.ToString()); }
public void MatchDigitsString() { bool result = FriendCode.TryParse("111122223333", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(result); Assert.AreEqual("1111-2222-3333", friendCode.ToString()); }
public void NoCodeProperty() { var fc = new FriendCode("1111-2222-3333"); Assert.IsFalse(fc.NoCode); fc = FriendCode.NO_FRIEND_CODE; Assert.IsTrue(fc.NoCode); }
public void JoinSeparatorTest() { bool success = FriendCode.TryParse("123456789", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(success); Assert.AreEqual("000123456789", friendCode.ToString("")); }
public Source Load() { Debug.WriteLine("Loading " + jsonFile); string json = File.ReadAllText(jsonFile); StatInkRoot root = JsonConvert.DeserializeObject <StatInkRoot>(json) ?? new StatInkRoot(); source.Start = new DateTime(root.EndAt?.Time ?? Builtins.UNKNOWN_DATE_TIME_TICKS); List <Player> players = new(); // Don't load the details if they are manual entries. if (!root.Automated || root.Players == default) { return(source); } if (root.Url != null) { source.Uris = new Uri[] { root.Url }; } foreach (var p in root.Players) { var newPlayer = new Player(p.Name ?? Builtins.UNKNOWN_PLAYER, source) { SplatnetId = p.SplatnetId, Top500 = p.Top500 == true, }; if (p.IsMe) { if (root.User?.Profile?.Twitter != null) { newPlayer.AddTwitter(root.User.Profile.Twitter, source); } if (root.User?.Profile?.FriendCode != null) { if (FriendCode.TryParse(root.User.Profile.FriendCode, out FriendCode friendCode)) { newPlayer.AddFCs(friendCode, source); } } } if (p.Weapon?.MainRef != null) { newPlayer.AddWeapons(new string[] { p.Weapon.MainRef }); } players.Add(newPlayer); } source.Players = players.ToArray(); return(source); }
public void ToULongRoundTrip_2() { bool result = FriendCode.TryParse("9999-9999-9998", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(result); Assert.AreEqual("9999-9999-9998", friendCode.ToString()); Assert.AreEqual((ulong)999999999998, friendCode.ToULong()); var fc2 = new FriendCode(999999999998); Assert.AreEqual(fc2, friendCode); }
public void ToULongRoundTrip() { bool result = FriendCode.TryParse("0001-2345-6789", out FriendCode friendCode); Assert.AreNotEqual(FriendCode.NO_FRIEND_CODE, friendCode); Assert.IsTrue(result); Assert.AreEqual("0001-2345-6789", friendCode.ToString()); Assert.AreEqual((ulong)123456789, friendCode.ToULong()); var fc2 = new FriendCode(123456789); Assert.AreEqual(friendCode, fc2); }
public Source Load() { Debug.WriteLine("Loading " + tsvFile); string[] text = File.ReadAllLines(tsvFile); if (text.Length < 1) { throw new ArgumentException("TSV does not have any data. Check format of spreadsheet."); } // Build a map of the incoming data string headerRow = text[0]; string[] columns = headerRow.Split('\t').Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); int numberOfHeaders = columns.Length; PropertyEnum[] resolved = new PropertyEnum[numberOfHeaders]; for (int i = 0; i < numberOfHeaders; ++i) { string header = columns[i].ToLowerInvariant() .Replace("your ", "") .Replace(" ", "") .Replace("_", "") .Replace(":", "") .Replace("-", "") .Replace("'s", "") .Replace("teamcaptain", "captain") .Replace("teammember", "player") ; if (string.IsNullOrWhiteSpace(header)) { Console.WriteLine($"Warning: Unable to resolve header, it is blank after processing: \"{header}\", (was \"{columns[i]}\")"); resolved[i] = PropertyEnum.UNKNOWN; } // Quick case else if (propertyValueStringMap.ContainsKey(header)) { resolved[i] = propertyValueStringMap[header]; } else { // Need to do some searching int playerNum = 0; if (header.Contains("captain")) { playerNum = 1; header = header.Replace("captain", ""); } else { for (playerNum = 10; playerNum > 0; --playerNum) { if (header.Contains(playerNum.ToString())) { header = header.Replace(playerNum.ToString(), ""); break; } } } var matchedKey = propertyValueStringMap.Keys.FirstOrDefault(key => header.StartsWith(key)); if (matchedKey != null) { // For player num = 0 (not found), this will just return the appropriate header. resolved[i] = (playerNum * (int)PropertyEnum.PlayerN_Offset) + propertyValueStringMap[matchedKey]; } else if (playerNum == 0) { resolved[i] = PropertyEnum.UNKNOWN; Console.WriteLine("Warning: Unable to resolve header: " + header); } else { resolved[i] = PropertyEnum.UNKNOWN; Console.WriteLine("Warning: Unable to resolve header for player " + playerNum + ": " + header); } } } // Now read the data... // Most tsv files will be team sheets, but for draft cups and verif they could be player records instead. // Each row therefore might be a single team with players, or a single player entry. List <Team> teams = new List <Team>(); List <Player> players = new List <Player>(); // From 1 as [0] is header row for (int lineIndex = 1; lineIndex < text.Length; ++lineIndex) { string line = text[lineIndex]; if (!line.Contains('\t')) { continue; } string[] cells = line.Split('\t').ToArray(); // Warn if the values exceeds the number of defined headers (but don't bother if we're only one over and it's empty -- trailing tab) if (numberOfHeaders < cells.Length && (numberOfHeaders != cells.Length - 1 || !string.IsNullOrWhiteSpace(cells[cells.Length - 1]))) { Console.WriteLine($"Warning: Line {lineIndex} contains more cells in this row {cells.Length} than headers {numberOfHeaders}."); Debug.WriteLine(line); } SortedDictionary <int, Player> rowPlayers = new SortedDictionary <int, Player>(); Team t = new Team(); for (int i = 0; i < cells.Length && i < numberOfHeaders; ++i) { int playerNum = 0; PropertyEnum resolvedProperty = resolved[i]; if (resolvedProperty > PropertyEnum.PlayerN_Offset) { playerNum = (int)resolved[i] / (int)PropertyEnum.PlayerN_Offset; resolvedProperty = (PropertyEnum)((int)resolved[i] % (int)PropertyEnum.PlayerN_Offset); } string value = cells[i]; if (string.IsNullOrWhiteSpace(value)) { continue; } switch (resolvedProperty) { case PropertyEnum.UNKNOWN: { continue; } case PropertyEnum.Country: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); p.Country = value; break; } case PropertyEnum.DiscordId: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); if (value.Length >= 14 && value.Length < 21) { // First, test is decimal (of length 17+) bool isDecimal = value.Length >= 17 && value.All("0123456789".Contains); if (isDecimal) { p.AddDiscordId(value, source); } // Otherwise test if we can get from a hex string (of length 14+ to give the correct 17 digit decimal) else if (ulong.TryParse(value, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out ulong parsedId)) { p.AddDiscordId(value, source); } else { Console.WriteLine($"Warning: DiscordId was specified ({lineIndex},{i}), but the value could not be parsed from a decimal or hex string. {value}."); Debug.WriteLine(line); } } else { Console.WriteLine($"Warning: DiscordId was specified ({lineIndex},{i}), but the value length does not fit into a discord id. {value}."); Debug.WriteLine(line); } break; } case PropertyEnum.DiscordName: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); if (Discord.DISCORD_NAME_REGEX.IsMatch(value)) { p.AddDiscordUsername(value, source); } else if (FriendCode.TryParse(value, out FriendCode friendCode)) { p.AddFCs(friendCode, source); Console.WriteLine($"Warning: This value was declared as a Discord name but looks like a friend code. Bad data formatting? {value} on ({lineIndex},{i})."); } else { Console.WriteLine($"Warning: DiscordName was specified ({lineIndex},{i}), but the value was not in a Discord format of name#0000. {value}."); Debug.WriteLine(line); } break; } case PropertyEnum.FC: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); if (FriendCode.TryParse(value, out FriendCode friendCode)) { p.AddFCs(friendCode, source); } else { Console.WriteLine($"Warning: FC was specified ({lineIndex},{i}), but the value was not in an FC format of 0000-0000-0000 or 0000 0000 0000. {value}."); Debug.WriteLine(line); } break; } case PropertyEnum.Div: { t.AddDivision(new Division(value, divType, season), source); if (divType == DivType.Unknown) { Console.WriteLine($"Warning: Div was specified ({lineIndex},{i}), but I don't know what type of division this file represents."); } break; } case PropertyEnum.LUTIDiv: { t.AddDivision(new Division(value, DivType.LUTI, season), source); break; } case PropertyEnum.EBTVDiv: { t.AddDivision(new Division(value, DivType.EBTV, season), source); break; } case PropertyEnum.DSBDiv: { t.AddDivision(new Division(value, DivType.DSB, season), source); break; } case PropertyEnum.Timestamp: { // TODO - not supported right now. In future we could customise the source timestamp for this entry. break; } case PropertyEnum.Name: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); var playerName = value.Trim(); playerName = t.Tag?.StripFromPlayer(playerName) ?? playerName; p.AddName(playerName, source); if (FriendCode.TryParse(value, out FriendCode friendCode)) { p.AddFCs(friendCode, source); Console.WriteLine($"Warning: This value was declared as a name but looks like a friend code. Bad data formatting? {value} on ({lineIndex},{i})."); Debug.WriteLine(line); } break; } case PropertyEnum.Role: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); p.AddWeapons(value.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s))); break; } case PropertyEnum.Pronouns: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); p.PronounInformation.SetPronoun(value, source); break; } case PropertyEnum.Tag: { t.AddClanTag(value, source); break; } case PropertyEnum.TeamName: { t.AddName(value, source); break; } case PropertyEnum.Twitter: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); p.AddTwitter(value, source); break; } case PropertyEnum.Twitch: { var p = GetCurrentPlayer(ref rowPlayers, playerNum, tsvFile); p.AddTwitch(value, source); break; } case PropertyEnum.Team_Offset: case PropertyEnum.UnspecifiedPlayer_Offset: case PropertyEnum.PlayerN_Offset: default: { Console.WriteLine($"Warning: Unhandled header {resolvedProperty}. {value}. Line {lineIndex}:"); Debug.WriteLine(line); break; } } } // End of the row, add the data. foreach (var pair in rowPlayers) { // Don't add empty players Player p = pair.Value; if (p.Name.Equals(Builtins.UnknownPlayerName)) { continue; } // Don't add the team to the player if it's not complete (e.g. single player record) if (!t.Name.Equals(Builtins.UnknownTeamName)) { p.TeamInformation.Add(t.Id, source); } players.Add(p); } // Don't bother adding the team if it has no players if (players.Count > 0) { // Don't register a team if that information doesn't exist. if (!t.Name.Equals(Builtins.UnknownTeamName)) { // Recalculate the ClanTag layout if (t.Tag != null) { t.Tag.CalculateTagOption(players[0].Name.Value); } else { ClanTag?newTag = ClanTag.CalculateTagFromNames(players.Select(p => p.Name.Value).ToArray(), source); if (newTag != null) { t.AddClanTag(newTag); } } teams.Add(t); } } } source.Players = players.ToArray(); source.Teams = teams.ToArray(); return(source); }
public Source Load() { Debug.WriteLine("Loading " + jsonFile); string json = File.ReadAllText(jsonFile); BattlefyJsonTeam[] rows = JsonConvert.DeserializeObject <BattlefyJsonTeam[]>(json) ?? Array.Empty <BattlefyJsonTeam>(); List <Team> teams = new(); List <Player> players = new(); foreach (BattlefyJsonTeam row in rows) { if (row.TeamName == null || row.Players == null) { Console.Error.WriteLine("ERROR: JSON did not import a team correctly. Ignoring this team entry. File: " + jsonFile); continue; } if (row.Players.Length < 1) { // Report if the team name doesn't begin with "bye" if (!row.TeamName.StartsWith("bye", StringComparison.OrdinalIgnoreCase)) { Console.Error.WriteLine($"ERROR: JSON does not contain a player for team \"{row.TeamName}\". Ignoring this team entry. File: " + jsonFile); } continue; } // Set the source start time if not already if (source.Start == Builtins.UnknownDateTime && row.CheckInTime != null) { source.Start = new DateTime(row.CheckInTime.Value.Year, row.CheckInTime.Value.Month, row.CheckInTime.Value.DayOfYear); } if (row.Captain == null) { Console.WriteLine($"Warning: JSON does not contain a Team Captain for team \"{row.TeamName}\". Assuming player 1 is captain. File: " + jsonFile); row.Captain = row.Players[0]; } if (string.IsNullOrEmpty(row.Captain.Name)) { Console.Error.WriteLine($"ERROR: The captain for team \"{row.TeamName}\" does not have a name. Ignoring this team entry. File: " + jsonFile); continue; } // Attempt to resolve the team tags ClanTag?teamTag = ClanTag.CalculateTagFromNames(row.Players.Select(p => p.Name).Where(name => name != null && !string.IsNullOrWhiteSpace(name)).ToArray() !, source); Team newTeam = new(row.TeamName, source); if (teamTag != null) { newTeam.AddClanTag(teamTag); } if (row.BattlefyPersistentTeamId != null) { newTeam.AddBattlefyId(row.BattlefyPersistentTeamId, source); } // If we already have a team with this id then merge it. if (newTeam.BattlefyPersistentTeamId != null) { var knownTeam = teams.Find(t => newTeam.BattlefyPersistentTeamId.Equals(t.BattlefyPersistentTeamId)); if (knownTeam != null) { knownTeam.Merge(newTeam); } else { teams.Add(newTeam); } } else { teams.Add(newTeam); } foreach (BattlefyJsonPlayer p in row.Players) { if (p.Name == null) { Console.Error.WriteLine($"ERROR: Player's Name ({p.Name}) not populated. Ignoring this player entry. File: " + jsonFile); continue; } if (p.PersistentPlayerId == null) { Console.WriteLine($"Warning: Player ({p.Name}) does not have a PersistentPlayerId. Did they sub? Ignoring this player entry. File: " + jsonFile); continue; } // Filter the friend code from the name, if found var(parsedFriendCode, strippedName) = FriendCode.ParseAndStripFriendCode(p.Name); if (!parsedFriendCode.NoCode) { p.Name = strippedName; } // Remove tag from player if (teamTag != null) { p.Name = teamTag.StripFromPlayer(p.Name.Trim()); } // Add Discord information, if we have it var newPlayer = new Player(p.Name, new[] { newTeam.Id }, source); if (p.BattlefyName != null && p.BattlefyName == row.Captain.BattlefyName) { if (parsedFriendCode.NoCode && !row.CaptainFriendCode.NoCode) { parsedFriendCode = row.CaptainFriendCode; } if (row.CaptainDiscordName != null) { newPlayer.AddDiscordUsername(row.CaptainDiscordName, source); } } // Add Battlefy if (p.BattlefyName != null && p.BattlefyUserSlug != null && p.PersistentPlayerId != null) { newPlayer.AddBattlefyInformation(p.BattlefyUserSlug, p.BattlefyName, p.PersistentPlayerId, source); } newPlayer.AddFCs(parsedFriendCode, source); players.Add(newPlayer); } } source.Players = players.ToArray(); source.Teams = teams.ToArray(); return(source); }