Fizzi.Applications.ChallongeVisualization.Model.ObservableMatch.ObservableMatch C# (CSharp) Method

ObservableMatch() public method

public ObservableMatch ( Match match, TournamentContext context ) : System
match Fizzi.Libraries.ChallongeApiWrapper.Match
context TournamentContext
return System
        public ObservableMatch(Match match, TournamentContext context)
        {
            source = match;
            OwningContext = context;

            //Round doesn't change, initialize RoundFixed
            var totalPlayerCount = context.Tournament.ParticipantsCount;
            var lowerBoundExponent = Math.Floor(Math.Log(totalPlayerCount, 2));

            var lowerBound = Math.Pow(2, lowerBoundExponent);
            if (match.Round < 0 && totalPlayerCount > lowerBound && totalPlayerCount <= lowerBound + (lowerBound / 2))
            {
                Round = match.Round - 1;
            }
            else Round = match.Round;

            //Check if station assignment data checks out. If not, clear the assignment
            var player1Station = Player1 != null ? Player1.StationAssignment : default(string);
            var player2Station = Player2 != null ? Player2.StationAssignment : default(string);

            //If stations don't match, clear. Don't check completed matches because those will frequently have mismatching stations
            if (State != "complete" && player1Station != player2Station) ClearStationAssignment();

            //Listen for when properties changed to that changed events for the convenience properties can also be fired.
            this.PropertyChanged += (sender, e) =>
            {
                switch (e.PropertyName)
                {
                    case "Player1Id":
                        this.Raise("Player1", PropertyChanged);
                        this.Raise("PlayerCount", PropertyChanged);
                        if (Player1 != null) Player1.IsMissing = false; //When a player gets added to a match, clear their missing flag
                        break;
                    case "Player2Id":
                        this.Raise("Player2", PropertyChanged);
                        this.Raise("PlayerCount", PropertyChanged);
                        if (Player2 != null) Player2.IsMissing = false; //When a player gets added to a match, clear their missing flag
                        break;
                    case "Player1PrereqMatchId":
                        this.Raise("Player1PreviousMatch", PropertyChanged);
                        break;
                    case "Player2PrereqMatchId":
                        this.Raise("Player2PreviousMatch", PropertyChanged);
                        break;
                    case "StartedAt":
                        this.Raise("TimeSinceAvailable", PropertyChanged);
                        break;
                    case "State":
                        //Clear station assignments if match state changes
                        if (Player1 != null) Player1.ClearStationAssignment();
                        if (Player2 != null) Player2.ClearStationAssignment();

                        //If match state has changed to open, execute selected new match option
                        if (State == "open")
                        {
                            var option = GlobalSettings.Instance.SelectedNewMatchAction;

                            switch (option)
                            {
                                case NewMatchAction.AutoAssign:
                                    //TODO: Consider using lock block here to prevent potential multithreaded assignment to the same station
                                    var highestPriorityStation = Stations.Instance.GetBestNormalStation();
                                    if (highestPriorityStation != null) AssignPlayersToStation(highestPriorityStation.Name);
                                    break;
                                case NewMatchAction.Anywhere:
                                    AssignPlayersToStation("Any");
                                    break;
                            }
                        }
                        break;
                }
            };

            var propertyChangedObs = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(h => this.PropertyChanged += h, h => this.PropertyChanged -= h);

            //The following will create an observable sequence that will raise an event either when player1 changes or when player1's station assignment status changes
            var player1ChangedOrAssignmentChanged = propertyChangedObs.Where(a => a.EventArgs.PropertyName == "Player1")
                .Select(_ =>
                {
                    if (Player1 != null)
                    {
                        return Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(h =>
                            {
                                player1Queue.Enqueue(Player1);
                                Player1.PropertyChanged += h;
                            }, h =>
                            {
                                player1Queue.Dequeue().PropertyChanged -= h;
                            })
                            .Where(a => a.EventArgs.PropertyName == "IsAssignedToStation" || a.EventArgs.PropertyName == "StationAssignment")
                            .Select(_2 => EventArgs.Empty).StartWith(EventArgs.Empty);
                    }
                    else return Observable.Return(EventArgs.Empty);
                }).Switch();

            //Subscribe to above observable sequence to maintain the assignment state of the match
            player1ChangedOrAssignmentChanged.Subscribe(_ =>
            {
                IsMatchInProgress = Player1 != null && Player1.IsAssignedToStation;
                StationAssignment = Player1 == null ? null : Player1.StationAssignment;
            });

            //Forcibly raise player1 property notification to assign station status
            this.Raise("Player1", PropertyChanged);
        }