public DisplayMatch(OrganizerViewModel ovm, ObservableMatch match, DisplayType displayType) { Match = match; MatchDisplayType = displayType; //Modify ViewModel state when an action is initiated Action startAction = () => { ovm.ErrorMessage = null; ovm.IsBusy = true; }; //Modify ViewModel state when an action is completed Action endAction = () => { ovm.IsBusy = false; }; //Modify ViewModel state when an action comes back with an exception Action<Exception> errorHandler = ex => { if (ex.InnerException is ChallongeApiException) { var cApiEx = (ChallongeApiException)ex.InnerException; if (cApiEx.Errors != null) ovm.ErrorMessage = cApiEx.Errors.Aggregate((one, two) => one + "\r\n" + two); else ovm.ErrorMessage = string.Format("Error with ResponseStatus \"{0}\" and StatusCode \"{1}\". {2}", cApiEx.RestResponse.ResponseStatus, cApiEx.RestResponse.StatusCode, cApiEx.RestResponse.ErrorMessage); } else { ovm.ErrorMessage = ex.NewLineDelimitedMessages(); } ovm.IsBusy = false; }; Player1Wins = Command.CreateAsync(() => true, () => Match.ReportPlayer1Victory(SetScore.Create(1, 0)), startAction, endAction, errorHandler); Player2Wins = Command.CreateAsync(() => true, () => Match.ReportPlayer2Victory(SetScore.Create(0, 1)), startAction, endAction, errorHandler); Player1WinsScored = Command.CreateAsync<SetScore[]>(_ => true, scores => Match.ReportPlayer1Victory(scores), _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); Player2WinsScored = Command.CreateAsync<SetScore[]>(_ => true, scores => Match.ReportPlayer2Victory(scores), _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); Player1ToggleMissing = Command.CreateAsync(() => true, () => Match.Player1.IsMissing = !Match.Player1.IsMissing, startAction, endAction, errorHandler); Player2ToggleMissing = Command.CreateAsync(() => true, () => Match.Player2.IsMissing = !Match.Player2.IsMissing, startAction, endAction, errorHandler); AssignStation = Command.CreateAsync<Station>(_ => true, s => Match.AssignPlayersToStation(s.Name), _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); CallMatchAnywhere = Command.CreateAsync(() => true, () => Match.AssignPlayersToStation("Any"), startAction, endAction, errorHandler); CallMatch = Command.CreateAsync<Station>(_ => true, s => { if (!match.IsMatchInProgress) { if (s != null) Match.AssignPlayersToStation(s.Name); else Match.AssignPlayersToStation("Any"); } }, _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); UncallMatch = Command.CreateAsync(() => true, () => Match.ClearStationAssignment(), startAction, endAction, errorHandler); }
public MainViewModel() { CurrentScreen = ScreenType.ApiKey; //Observable.Start(() => //{ // try // { // //I'm considering doing an http request to smashboards to find if a new version is released. I think smashboard's anti-DDOS protection is preventing it from working // WebRequest request = WebRequest.Create(ThreadUrl); // request.Credentials = CredentialCache.DefaultCredentials; // WebResponse response = request.GetResponse(); // if (((HttpWebResponse)response).StatusDescription == "OK") // { // Stream dataStream = response.GetResponseStream(); // StreamReader reader = new StreamReader(dataStream); // string responseFromServer = reader.ReadToEnd(); // reader.Close(); // } // response.Close(); // } // catch { /* ignore */ } //}); //Modify ViewModel state when an action is initiated Action startAction = () => { ErrorMessage = null; IsBusy = true; }; //Modify ViewModel state when an action is completed Action endAction = () => { IsBusy = false; }; //Modify ViewModel state when an action comes back with an exception Action<Exception> errorHandler = ex => { if (ex.InnerException is ChallongeApiException) { var cApiEx = (ChallongeApiException)ex.InnerException; if (cApiEx.Errors != null) ErrorMessage = cApiEx.Errors.Aggregate((one, two) => one + "\r\n" + two); else ErrorMessage = string.Format("Error with ResponseStatus \"{0}\" and StatusCode \"{1}\". {2}", cApiEx.RestResponse.ResponseStatus, cApiEx.RestResponse.StatusCode, cApiEx.RestResponse.ErrorMessage); } else { ErrorMessage = ex.NewLineDelimitedMessages(); } IsBusy = false; }; var dispatcher = System.Threading.SynchronizationContext.Current; //Handle next button press NextCommand = Command.CreateAsync(() => true, () => { switch (CurrentScreen) { case ScreenType.ApiKey: var subdomain = string.IsNullOrWhiteSpace(Subdomain) ? null : Subdomain; Portal = new ChallongePortal(ApiKey, subdomain); //Load list of tournaments that match apikey/subdomain TournamentCollection = Portal.GetTournaments().OrderByDescending(t => t.CreatedAt).ToArray(); try { //This is a silly method for checking whether a new application version exists without me having my own website. //I manage the most recent version number in the description of a tournament hosted on challonge. This code fetches that number var versionCheckPortal = new ChallongePortal(ApiKey, "fizzitestorg"); MostRecentVersion = versionCheckPortal.GetTournaments().Where(t => t.Name == "CMDVersionTest").Select(t => { //Modifying the description seems to put some html formatting into the result. This filters the description for //just the version number by itself var versionResult = string.Concat(t.Description.Where(c => char.IsDigit(c) || c == '.')); return versionResult; }).First(); //Check both version numbers to determine if current version is older than recent version var versionCompareResult = Version.Split('.').Zip(MostRecentVersion.Split('.'), (v, mrv) => { return int.Parse(v).CompareTo(int.Parse(mrv)); }).FirstOrDefault(i => i != 0); //If app version is older than most recent version, show message IsVersionOutdatedVisible = versionCompareResult < 0; } catch (Exception) { //If version check fails simply ignore the problem and move on System.Diagnostics.Debug.WriteLine("Version check failed."); } break; case ScreenType.TournamentSelection: if (Context != null) Context.Dispose(); if (matchesChangedHandler != null) Context.Tournament.PropertyChanged -= matchesChangedHandler; //Create tournament context from selected tournament Context = new TournamentContext(Portal, SelectedTournament.Id); Context.StartSynchronization(TimeSpan.FromMilliseconds(500), 6); //Create TO View Model OrgViewModel = new OrganizerViewModel(this, dispatcher); //Load up matches into display matches. This is done to allow ordering of assigned matches over unassigned matches without having to refresh the view DisplayMatches = Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Assigned)) .Concat(Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Unassigned))).ToList(); //This handler is used to keep matches display matches in sync with tournament context matches. If the matches in the context change, re-generate the display matches matchesChangedHandler = new PropertyChangedEventHandler((sender, e) => { if (e.PropertyName == "Matches") { if (Context.Tournament.Matches == null) DisplayMatches = null; else { DisplayMatches = Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Assigned)) .Concat(Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Unassigned))).ToList(); } } }); Context.Tournament.PropertyChanged += matchesChangedHandler; break; } CurrentScreen = (ScreenType)((int)CurrentScreen + 1); }, startAction, endAction, errorHandler); Back = Command.CreateAsync(() => true, () => { switch (CurrentScreen) { case ScreenType.TournamentSelection: ApiKey = null; break; case ScreenType.PendingMatchView: if (OrgViewModel != null) { OrgViewModel.Dispose(); OrgViewModel = null; } break; } CurrentScreen = (ScreenType)((int)CurrentScreen - 1); }, startAction, endAction, errorHandler); IgnoreVersionNotification = Command.Create(() => true, () => IsVersionOutdatedVisible = false); }
public MainViewModel() { CurrentScreen = ScreenType.ApiKey; //Observable.Start(() => //{ // try // { // //I'm considering doing an http request to smashboards to find if a new version is released. I think smashboard's anti-DDOS protection is preventing it from working // WebRequest request = WebRequest.Create(ThreadUrl); // request.Credentials = CredentialCache.DefaultCredentials; // WebResponse response = request.GetResponse(); // if (((HttpWebResponse)response).StatusDescription == "OK") // { // Stream dataStream = response.GetResponseStream(); // StreamReader reader = new StreamReader(dataStream); // string responseFromServer = reader.ReadToEnd(); // reader.Close(); // } // response.Close(); // } // catch { /* ignore */ } //}); //Modify ViewModel state when an action is initiated Action startAction = () => { ErrorMessage = null; IsBusy = true; }; //Modify ViewModel state when an action is completed Action endAction = () => { IsBusy = false; }; //Modify ViewModel state when an action comes back with an exception Action <Exception> errorHandler = ex => { if (ex.InnerException is ChallongeApiException) { var cApiEx = (ChallongeApiException)ex.InnerException; if (cApiEx.Errors != null) { ErrorMessage = cApiEx.Errors.Aggregate((one, two) => one + "\r\n" + two); } else { ErrorMessage = string.Format("Error with ResponseStatus \"{0}\" and StatusCode \"{1}\". {2}", cApiEx.RestResponse.ResponseStatus, cApiEx.RestResponse.StatusCode, cApiEx.RestResponse.ErrorMessage); } } else { ErrorMessage = ex.NewLineDelimitedMessages(); } IsBusy = false; }; var dispatcher = System.Threading.SynchronizationContext.Current; //Handle next button press NextCommand = Command.CreateAsync(() => true, () => { switch (CurrentScreen) { case ScreenType.ApiKey: var subdomain = string.IsNullOrWhiteSpace(Subdomain) ? null : Subdomain; Portal = new ChallongePortal(ApiKey, subdomain); //Load list of tournaments that match apikey/subdomain TournamentCollection = Portal.GetTournaments().OrderByDescending(t => t.CreatedAt).ToArray(); try { //This is a silly method for checking whether a new application version exists without me having my own website. //I manage the most recent version number in the description of a tournament hosted on challonge. This code fetches that number var versionCheckPortal = new ChallongePortal(ApiKey, "fizzitestorg"); MostRecentVersion = versionCheckPortal.GetTournaments().Where(t => t.Name == "CMDVersionTest").Select(t => { //Modifying the description seems to put some html formatting into the result. This filters the description for //just the version number by itself var versionResult = string.Concat(t.Description.Where(c => char.IsDigit(c) || c == '.')); return(versionResult); }).First(); //Check both version numbers to determine if current version is older than recent version var versionCompareResult = Version.Split('.').Zip(MostRecentVersion.Split('.'), (v, mrv) => { return(int.Parse(v).CompareTo(int.Parse(mrv))); }).FirstOrDefault(i => i != 0); //If app version is older than most recent version, show message IsVersionOutdatedVisible = versionCompareResult < 0; } catch (Exception) { //If version check fails simply ignore the problem and move on System.Diagnostics.Debug.WriteLine("Version check failed."); } break; case ScreenType.TournamentSelection: if (Context != null) { Context.Dispose(); } if (matchesChangedHandler != null) { Context.Tournament.PropertyChanged -= matchesChangedHandler; } //Create tournament context from selected tournament Context = new TournamentContext(Portal, SelectedTournament.Id); Context.StartSynchronization(TimeSpan.FromMilliseconds(500), 6); //Create TO View Model OrgViewModel = new OrganizerViewModel(this, dispatcher); //Load up matches into display matches. This is done to allow ordering of assigned matches over unassigned matches without having to refresh the view DisplayMatches = Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Assigned)) .Concat(Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Unassigned))).ToList(); //This handler is used to keep matches display matches in sync with tournament context matches. If the matches in the context change, re-generate the display matches matchesChangedHandler = new PropertyChangedEventHandler((sender, e) => { if (e.PropertyName == "Matches") { if (Context.Tournament.Matches == null) { DisplayMatches = null; } else { DisplayMatches = Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Assigned)) .Concat(Context.Tournament.Matches.Select(kvp => new DisplayMatch(OrgViewModel, kvp.Value, DisplayMatch.DisplayType.Unassigned))).ToList(); } } }); Context.Tournament.PropertyChanged += matchesChangedHandler; break; } CurrentScreen = (ScreenType)((int)CurrentScreen + 1); }, startAction, endAction, errorHandler); Back = Command.CreateAsync(() => true, () => { switch (CurrentScreen) { case ScreenType.TournamentSelection: ApiKey = null; break; case ScreenType.PendingMatchView: if (OrgViewModel != null) { OrgViewModel.Dispose(); OrgViewModel = null; } break; } CurrentScreen = (ScreenType)((int)CurrentScreen - 1); }, startAction, endAction, errorHandler); IgnoreVersionNotification = Command.Create(() => true, () => IsVersionOutdatedVisible = false); }
public DisplayMatch(OrganizerViewModel ovm, ObservableMatch match, DisplayType displayType) { Match = match; MatchDisplayType = displayType; //Modify ViewModel state when an action is initiated Action startAction = () => { ovm.ErrorMessage = null; ovm.IsBusy = true; }; //Modify ViewModel state when an action is completed Action endAction = () => { ovm.IsBusy = false; }; //Modify ViewModel state when an action comes back with an exception Action <Exception> errorHandler = ex => { if (ex.InnerException is ChallongeApiException) { var cApiEx = (ChallongeApiException)ex.InnerException; if (cApiEx.Errors != null) { ovm.ErrorMessage = cApiEx.Errors.Aggregate((one, two) => one + "\r\n" + two); } else { ovm.ErrorMessage = string.Format("Error with ResponseStatus \"{0}\" and StatusCode \"{1}\". {2}", cApiEx.RestResponse.ResponseStatus, cApiEx.RestResponse.StatusCode, cApiEx.RestResponse.ErrorMessage); } } else { ovm.ErrorMessage = ex.NewLineDelimitedMessages(); } ovm.IsBusy = false; }; Player1Wins = Command.CreateAsync(() => true, () => Match.ReportPlayer1Victory(SetScore.Create(1, 0)), startAction, endAction, errorHandler); Player2Wins = Command.CreateAsync(() => true, () => Match.ReportPlayer2Victory(SetScore.Create(0, 1)), startAction, endAction, errorHandler); Player1WinsScored = Command.CreateAsync <SetScore[]>(_ => true, scores => Match.ReportPlayer1Victory(scores), _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); Player2WinsScored = Command.CreateAsync <SetScore[]>(_ => true, scores => Match.ReportPlayer2Victory(scores), _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); Player1ToggleMissing = Command.CreateAsync(() => true, () => Match.Player1.IsMissing = !Match.Player1.IsMissing, startAction, endAction, errorHandler); Player2ToggleMissing = Command.CreateAsync(() => true, () => Match.Player2.IsMissing = !Match.Player2.IsMissing, startAction, endAction, errorHandler); AssignStation = Command.CreateAsync <Station>(_ => true, s => Match.AssignPlayersToStation(s.Name), _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); CallMatchAnywhere = Command.CreateAsync(() => true, () => Match.AssignPlayersToStation("Any"), startAction, endAction, errorHandler); CallMatch = Command.CreateAsync <Station>(_ => true, s => { if (!match.IsMatchInProgress) { if (s != null) { Match.AssignPlayersToStation(s.Name); } else { Match.AssignPlayersToStation("Any"); } } }, _ => startAction(), _ => endAction(), (_, ex) => errorHandler(ex)); UncallMatch = Command.CreateAsync(() => true, () => Match.ClearStationAssignment(), startAction, endAction, errorHandler); }