public Bet(LCSTeam winner, LCSTeam loser, decimal wager, ulong discordId) { Victor = winner; Loser = loser; Wager = wager; DiscordID = discordId; }
public FutureMatch GetNextMatchForTeam(LCSTeam team) { var nextMatchesForTeam = this.Where(match => DateTime.Now < match.ScheduledTime + TimeSpan.FromMinutes(FUTURE_BUFFER_MINS) && (match.Team1.Equals(team) || match.Team2.Equals(team))); if (nextMatchesForTeam.Count() == 0) { return(null); } return(nextMatchesForTeam.First()); }
/// <summary> /// Downloads the list of occurred LCS matches from lol.gamepedia.com /// </summary> /// <returns>A MatchRecord object containing the list of occurred LCS matches</returns> public static MatchRecord GetOnlineMatchRecord() { // Get HTML document string page_content; using (WebClient client = new WebClient()) { page_content = client.DownloadString(URL_RECORD); } HtmlDocument html = new HtmlDocument(); html.LoadHtml(page_content); HtmlNodeCollection raw_matches = html.DocumentNode.SelectNodes("//tr[contains(@class, 'mdv-allweeks mdv-week')]"); // Get occurred mathes from HTML document MatchRecord record = new MatchRecord(); foreach (HtmlNode node in raw_matches) { if (node.InnerLength > 1000) // Match has occurred { HtmlNodeCollection teams = node.SelectNodes(".//span[@class='teamname']"); LCSTeam team1 = LCSTeam.ParseTeam(teams[0].InnerText); LCSTeam team2 = LCSTeam.ParseTeam(teams[1].InnerText); if (!string.IsNullOrEmpty(team1.Name) && !string.IsNullOrEmpty(team2.Name)) // Both teams in Match detected { HtmlNode win = node.SelectSingleNode(".//td[@class='md-winner']"); if (win != null) // Winner was found for this match { LCSTeam winner = LCSTeam.ParseTeam(win.InnerText); if (winner.Equals(team1) || winner.Equals(team2)) // Make sure we detected the winning team correctly { LCSTeam other; if (winner.Equals(team1)) { other = team2; } else { other = team1; } record.Add(new MatchResult(winner, other)); } } } } } return(record); }
public static Schedule GetOnlineSchedule() { Schedule result = new Schedule(); string page_content; using (WebClient client = new WebClient()) { page_content = client.DownloadString(URL_SCHEDULE); } HtmlDocument html = new HtmlDocument(); html.LoadHtml(page_content); HtmlNode raw_schedule = html.DocumentNode.SelectSingleNode("//div[@class='mw-parser-output']/pre"); // Select schedule block foreach (string line in raw_schedule.InnerText.Split('\n')) { Match regex_schedule = REGEX_MATCHSCHEDULE.Match(line); if (regex_schedule.Success) { string t1 = regex_schedule.Groups[1].Value; string t2 = regex_schedule.Groups[2].Value; string year = regex_schedule.Groups[3].Value; string month = regex_schedule.Groups[4].Value; string day = regex_schedule.Groups[5].Value; string hour = regex_schedule.Groups[6].Value; string minute = regex_schedule.Groups[7].Value; DateTime match_utctime = DateTime.Parse($"{month}/{day}/{year} {hour}:{minute}:00", CultureInfo.InvariantCulture); DateTime match_time = match_utctime + TimeZoneInfo.Local.GetUtcOffset(match_utctime + TimeZoneInfo.Local.BaseUtcOffset); LCSTeam team1 = LCSTeam.ParseTeam(t1); LCSTeam team2 = LCSTeam.ParseTeam(t2); FutureMatch scheduled_match = new FutureMatch(team1, team2, match_time); result.Add(scheduled_match); } } if (result.Count == 0) { Console.WriteLine("Failed to parse schedule."); return(null); } return(result); }
public MatchResult(LCSTeam winner, LCSTeam loser) { Victor = winner; Loser = loser; }
public FutureMatch(LCSTeam t1, LCSTeam t2, DateTime time) { Team1 = t1; Team2 = t2; ScheduledTime = time; }
public Prediction(LCSTeam winner, LCSTeam loser, ulong discordId) { Victor = winner; Loser = loser; DiscordID = discordId; }
public async Task ProcessCommand(ulong discordId, SocketTextChannel replyChannel, string command, IList <string> args) { if (!Scoreboard.ContainsKey(discordId)) { string name = ResolvePlayerName(discordId); Scoreboard[discordId] = new PlayerScore(discordId, name); Scoreboard.SaveToFile(SavePath); Console.WriteLine($"New player registered: {name} (DiscordID {discordId})"); } command = command.ToLower().Trim(); switch (command) { // Singlet commands case "score": case "money": case "myscore": if (Scoreboard.ContainsKey(discordId)) { var myScore = Scoreboard[discordId]; await SayInChannel(replyChannel, $"Score for {myScore.Name}:\n{myScore.Money:c} after {myScore.BetCount} bets ({myScore.MoneyFromBets:+$0.00;-$0.00;$0}). " + $"Prediction record: {myScore.PredictionsRight} - {myScore.PredictionsWrong} (+${myScore.MoneyFromPredictions})"); } else { await SayInChannel(replyChannel, $"You are not a registered player yet. Place a Bet or Prediction to start. " + $"You'll start with ${PlayerScore.STARTING_MONEY}."); } break; case "scores": case "allscores": case "scoreboard": if (Scoreboard.Count == 0) { await SayInChannel(replyChannel, "The scoreboard is empty - there are no registered players yet."); } else { string scoreMessage = "Scoreboard:\n"; var sortedScores = Scoreboard.Values.ToList(); sortedScores.Sort((item1, item2) => item1.CompareTo(item2)); int place = 1; foreach (var playerScore in sortedScores) { scoreMessage += $"{place++}. {playerScore.Name}: {playerScore.Money:c} ({playerScore.BetCount} bets, {playerScore.MoneyFromBets:+$0.00;-$0.00;$0}) " + $"Predictions: {playerScore.PredictionsRight} - {playerScore.PredictionsWrong} (+${playerScore.MoneyFromPredictions})\n"; } await SayInChannel(replyChannel, scoreMessage); } break; case "games": case "upcoming": case "schedule": var futureGames = Schedule.Where(match => DateTime.Now < match.ScheduledTime + TimeSpan.FromMinutes(10)); if (futureGames.Count() <= 0) { await SayInChannel(replyChannel, "There are no games left in the season."); } else { string scheduleMessage = "Upcoming LCS games:\n"; foreach (var futureGame in futureGames.Take(futureGames.Count() >= 5 ? 5 : futureGames.Count())) { scheduleMessage += futureGame.ToString() + "\n"; } await SayInChannel(replyChannel, scheduleMessage); } break; case "mybets": case "bets": var myBets = Bets.Where(bet => bet.DiscordID == discordId).ToList(); var myPredictions = Predictions.Where(pred => pred.DiscordID == discordId).ToList(); if (myBets.Count + myPredictions.Count == 0) { await SayInChannel(replyChannel, "You do not have any active bets or predictions."); } else { string betsString = ""; if (myBets.Count > 0) { betsString += "Your active bets:\n"; myBets.ForEach(bet => betsString += $"{bet.Wager:c} on {bet.Victor} beating {bet.Loser}\n"); } if (myPredictions.Count > 0) { betsString += "Your predictions:\n"; myPredictions.ForEach(pred => betsString += $"{pred.Victor} will beat {pred.Loser}\n"); } await SayInChannel(replyChannel, betsString); } break; case "allbets": if (Bets.Count + Predictions.Count == 0) { await SayInChannel(replyChannel, "There are no active bets or predictions."); } else { string betString = ""; if (Bets.Count > 0) { betString += "All active bets:\n"; Bets.ForEach(bet => betString += $"{ResolvePlayerName(bet.DiscordID)} bet {bet.Wager} on {bet.Victor} beating {bet.Loser}.\n"); } if (Predictions.Count > 0) { betString += "Active predictions:\n"; Predictions.ForEach(pred => betString += $"{ResolvePlayerName(pred.DiscordID)} thinks {pred.Victor} will beat {pred.Loser}.\n"); } await SayInChannel(replyChannel, betString); } break; // Parameterized commands case "nextgame": case "next": if (args.Count() == 0) { await SayInChannel(replyChannel, "Enter a team to check the next game for (!next <Team>) or a pair of teams to find their next match (!next <Team1> <Team2>)"); } else if (args.Count() > 2) { await SayInChannel(replyChannel, "Usage: !next <Team> or !next <Team1> <Team2>"); } else if (args.Count() == 1) { LCSTeam team_check = LCSTeam.ParseTeam(args[0]); if (team_check.ID == LCSTeam.TeamID.Unknown) { await SayInChannel(replyChannel, $"Unknown LCS team '{args[0]}'"); } else { var nextMatchCheck = Schedule.GetNextMatchForTeam(team_check); if (nextMatchCheck == null) { await SayInChannel(replyChannel, $"{team_check} has no matches left in the season."); } else { await SayInChannel(replyChannel, $"Next match for {team_check}: {nextMatchCheck}"); } } } else // Checking for match between two teams { LCSTeam check1 = LCSTeam.ParseTeam(args[0]); if (check1.ID == LCSTeam.TeamID.Unknown) { await SayInChannel(replyChannel, $"Unknown LCS team '{args[0]}'"); break; } LCSTeam check2 = LCSTeam.ParseTeam(args[1]); if (check2.ID == LCSTeam.TeamID.Unknown) { await SayInChannel(replyChannel, $"Unknown LCS team '{args[1]}'"); break; } var nextMatchup = Schedule.GetNextMatchForMatchup(check1, check2); if (nextMatchup == null) { await SayInChannel(replyChannel, $"{check1} and {check2} are not playing each other for the rest of the season."); } else { await SayInChannel(replyChannel, $"{check1} next plays {check2} at {nextMatchup.ScheduledTime:h:mm tt M/dd}"); } } break; case "predict": if (args.Count() == 0) { await SayInChannel(replyChannel, "Enter a team to predict. (!predict <Team>)"); } else if (args.Count() != 1) { await SayInChannel(replyChannel, "Usage: !predict <Team>"); } else { LCSTeam team_pred = LCSTeam.ParseTeam(args[0]); if (team_pred.ID == LCSTeam.TeamID.Unknown) { await SayInChannel(replyChannel, $"Unknown LCS team '{args[0]}'"); } else { var nextScheduledMatch_pred = Schedule.GetNextMatchForTeam(team_pred); if (nextScheduledMatch_pred == null) { await SayInChannel(replyChannel, $"Team {team_pred} has no games left in the season."); } else if (DateTime.Now > nextScheduledMatch_pred.ScheduledTime + TimeSpan.FromMinutes(BETBUFFER_MINS)) // If next game is within this hour { await SayInChannel(replyChannel, $"{team_pred} is currently playing! ({nextScheduledMatch_pred}) " + $"Wait until afer the current match to make a prediction."); } else { LCSTeam loser; if (nextScheduledMatch_pred.Team1.Equals(team_pred)) { loser = nextScheduledMatch_pred.Team2; } else { loser = nextScheduledMatch_pred.Team1; } // Update existing bets bool updatedPred = false; for (int i = 0; i < Predictions.Count; i++) { if (Predictions[i].DiscordID == discordId) // Of my predictions... { if (Predictions[i].Victor.Equals(team_pred) && Predictions[i].Loser.Equals(loser)) // Predicting same victory combo { await SayInChannel(replyChannel, $"You already predicted that {Predictions[i].Victor} will beat {Predictions[i].Loser} ({nextScheduledMatch_pred})"); updatedPred = true; break; } else if (Predictions[i].Loser.Equals(team_pred) && Predictions[i].Victor.Equals(loser)) // Betting on opposite victory combo { Predictions[i] = new Prediction(team_pred, loser, discordId); // Create new Bet await SayInChannel(replyChannel, $"Prediction changed: {Predictions[i].Victor} will beat {Predictions[i].Loser} ({nextScheduledMatch_pred})"); updatedPred = true; break; } } } if (!updatedPred) // Create new bet if no bets were modified { Prediction pred = new Prediction(team_pred, loser, discordId); Predictions.Add(pred); await SayInChannel(replyChannel, $"Prediction made: {pred.Victor} will beat {pred.Loser} ({nextScheduledMatch_pred.ScheduledTime:ddd M/d h:mm tt})"); } } } } break; case "placebet": case "makebet": case "bet": // Parse and verify arguments if (args.Count() != 2) { await SayInChannel(replyChannel, "Usage: !bet <Team> <Wager>"); break; } decimal wager; int argWagerIndex = 0; if (!decimal.TryParse(args[argWagerIndex].Trim('$'), out wager)) { argWagerIndex = 1; if (!decimal.TryParse(args[argWagerIndex].Trim('$'), out wager)) { await SayInChannel(replyChannel, "Please enter an amount of money. (!bet <Team> <Wager>)"); break; } } if (wager <= 0) { await SayInChannel(replyChannel, "Wager must be greater than $0."); break; } int argTeamIndex = argWagerIndex == 0 ? 1 : 0; LCSTeam team = LCSTeam.ParseTeam(args[argTeamIndex]); if (team.ID == LCSTeam.TeamID.Unknown) { await SayInChannel(replyChannel, $"Unknown LCS team '{args[argTeamIndex]}'"); break; } // Get match timing var nextScheduledMatch = Schedule.GetNextMatchForTeam(team); if (nextScheduledMatch == null) { await SayInChannel(replyChannel, $"Team {team} has no games left in the season."); } else if (DateTime.Now > nextScheduledMatch.ScheduledTime + TimeSpan.FromMinutes(BETBUFFER_MINS)) // If next game is within this hour { await SayInChannel(replyChannel, $"{team} is currently playing! ({nextScheduledMatch}) " + $"Wait until afer the current match to place a bet."); } else // Timing looks good { LCSTeam loser; if (nextScheduledMatch.Team1.Equals(team)) { loser = nextScheduledMatch.Team2; } else { loser = nextScheduledMatch.Team1; } // Update existing bets bool updatedBet = false; for (int i = 0; i < Bets.Count; i++) { if (Bets[i].DiscordID == discordId) // Of my bets... { if (Bets[i].Victor.Equals(team) && Bets[i].Loser.Equals(loser)) // Betting on same victory combo { if (Bets[i].Wager != wager) // Change wager for same victory combo { if (Scoreboard[discordId].Money + Bets[i].Wager - wager < 0) { await SayInChannel(replyChannel, $"You can't change your bet by that much. You have {Scoreboard[discordId].Money:c}."); updatedBet = true; break; } else { Scoreboard[discordId].Money += Bets[i].Wager - wager; // Adjust player money to match wager change Bets[i] = new Bet(team, loser, wager, discordId); await SayInChannel(replyChannel, $"Bet changed: {Bets[i].Wager:c} on {Bets[i].Victor} beating {Bets[i].Loser} ({nextScheduledMatch.ScheduledTime:ddd M/d h:mm tt})"); updatedBet = true; Scoreboard.SaveToFile(SavePath); break; } } else // Same wager and victory combo { await SayInChannel(replyChannel, $"You already bet {Bets[i].Wager:c} on {Bets[i].Victor} (vs {Bets[i].Loser} {nextScheduledMatch.ScheduledTime:ddd M/d h:mm tt})"); updatedBet = true; break; } } else if (Bets[i].Loser.Equals(team) && Bets[i].Victor.Equals(loser)) // Betting on opposite victory combo { if (Scoreboard[discordId].Money + Bets[i].Wager - wager < 0) { await SayInChannel(replyChannel, $"You can't change your bet to that. You have {Scoreboard[discordId].Money:c}."); updatedBet = true; break; } else { Scoreboard[discordId].Money += Bets[i].Wager - wager; // Adjust player money to match wager change Bets[i] = new Bet(team, loser, wager, discordId); // Create new Bet await SayInChannel(replyChannel, $"Bet changed: {Bets[i].Wager:c} on {Bets[i].Victor} beating {Bets[i].Loser} ({nextScheduledMatch.ScheduledTime:ddd M/d h:mm tt})"); updatedBet = true; Scoreboard.SaveToFile(SavePath); break; } } } } if (!updatedBet) // Create new bet if no bets were modified { if (Scoreboard[discordId].Money - wager < 0) { await SayInChannel(replyChannel, $"You can't bet that much. You have {Scoreboard[discordId].Money:c}."); updatedBet = true; break; } else { Bet bet = new Bet(team, loser, wager, discordId); Bets.Add(bet); Scoreboard.TakeMoney(discordId, wager); Scoreboard[discordId].BetCount += 1; Scoreboard.SaveToFile(SavePath); await SayInChannel(replyChannel, $"Bet placed: {wager:c} on {team} beating {loser} ({nextScheduledMatch.ScheduledTime:ddd M/d h:mm tt})"); } } } break; } }