예제 #1
0
        public void SetUniformValue(int uniformId, object value)
        {
            if (CurrentProgramId != 0 && CurrentProgramId != ProgramId)
            {
                throw new System.Exception("An other program is already loaded!");
            }

            using (UseProgram())
            {
                TypeSwitch.On(value)
                .Case((int x) => GL.Uniform1(uniformId, x))
                .Case((uint x) => GL.Uniform1(uniformId, x))
                .Case((float x) => GL.Uniform1(uniformId, x))
                .Case((Vector2 x) => GL.Uniform2(uniformId, x))
                .Case((Vector3 x) => GL.Uniform3(uniformId, x))
                .Case((Vector4 x) => GL.Uniform4(uniformId, x))
                .Case((Quaternion x) => GL.Uniform4(uniformId, x))
                .Case((Color4 x) => GL.Uniform4(uniformId, x))
                .Case((int[] x) => GL.Uniform1(uniformId, x.Length, x))
                .Case((uint[] x) => GL.Uniform1(uniformId, x.Length, x))
                .Case((float[] x) => GL.Uniform1(uniformId, x.Length, x))
                .Case((Matrix4 x) => GL.UniformMatrix4(uniformId, false, ref x))
                .Case((Color x) => GL.Uniform4(uniformId, x.R, x.G, x.B, x.A))
                .Default(x => Throw("GLUniform type {0} is not is not implemented.", value.GetType()));
            }
        }
        public virtual ExceptionModel Convert(Exception exception)
        {
            ExceptionModel model = null;

            TypeSwitch.On(exception)
            .Case <HttpStatusException>(ex =>
            {
                exception = ex.InnerException;
                model     = Convert(exception);
            })
            .Case <ArgumentException>(ex => model = new ArgumentExceptionModel
            {
                ParamName = ex.ParamName,
            })
            .Case <NotSupportedException>(ex => model     = new NotSupportedExceptionModel())
            .Case <InvalidOperationException>(ex => model = new InvalidOperationExceptionModel())
            .Default(() => model = new ExceptionModel
            {
                Message = string.Format("[No exception serializer found for {0}].{1}", exception.GetType(), Environment.NewLine)
            });

            model.Message    = exception.Message;
            model.StackTrace = exception.StackTrace;
            return(model);
        }
예제 #3
0
        /// <summary>
        /// Sets the uniform value.
        /// </summary>
        /// <param name="uniformId">Uniform identifier.</param>
        /// <param name="value">Value.</param>
        void SetUniformValue(int uniformId, object value)
        {
            // Check if another program is loaded
            if (CurrentProgramId != 0 && CurrentProgramId != programId)
            {
                // Throw an exception
                const string message = "Cannot set uniform {0} on program {1} because the current program is {2}.";
                this.Throw(message, uniformId, programId, CurrentProgramId);
            }

            // Set the uniform
            using (UseProgram()) {
                TypeSwitch.On(value)
                .Case((int x) => GL.Uniform1(uniformId, x))
                .Case((uint x) => GL.Uniform1(uniformId, x))
                .Case((float x) => GL.Uniform1(uniformId, x))
                .Case((Vector2 x) => GL.Uniform2(uniformId, x))
                .Case((Vector3 x) => GL.Uniform3(uniformId, x))
                .Case((Vector4 x) => GL.Uniform4(uniformId, x))
                .Case((Quaternion x) => GL.Uniform4(uniformId, x))
                .Case((Color4 x) => GL.Uniform4(uniformId, x))
                .Case((int[] x) => GL.Uniform1(uniformId, x.Length, x))
                .Case((uint[] x) => GL.Uniform1(uniformId, x.Length, x))
                .Case((float[] x) => GL.Uniform1(uniformId, x.Length, x))
                .Case((Matrix4 x) => GL.UniformMatrix4(uniformId, false, ref x))
                .Case((Color x) => GL.Uniform4(uniformId, x.R, x.G, x.B, x.A))
                .Default(x => this.Throw("GlUniform type {0} is not (yet?) implemented.", value.GetType().FullName));
            }
        }
        protected override void OnReceive(AbstractMessage message)
        {
            TypeSwitch.On(message)
            .Case((ClearMessage clearMessage) =>
            {
                // Reset partition and send sync message
                clear();
                clearMessage.Sender.SendMe(new EstimateRefinedMessage(this));
            })
            .Case((RefineMessage refineMessage) =>
            {
                // Perform local refine step
                refine();
                refineMessage.Sender.SendMe(new EstimateRefinedMessage(this));
            })
            .Case((CountMessage countMessage) =>
            {
                var blocks = new HashSet <int>();
                foreach (var node in ownerInverted[this])
                {
                    if (!blocks.Contains(partition[node]))
                    {
                        blocks.Add(partition[node]);
                    }
                }

                countMessage.Sender.SendMe(new CountedMessage(this, blocks));
            })
            .Case((ShareMessage shareMessage) =>
            {
                // Share changes
                foreach (var worker in ownerInverted.Keys)
                {
                    if (worker != this)
                    {
                        var changedNodesOfInterest = partition.Where(kvp => interestedIn[worker].Contains(kvp.Key) && changed[kvp.Key]);

                        if (changedNodesOfInterest.Any())
                        {
                            worker.SendMe(new UpdatePartitionMessage <TNode>(this, changedNodesOfInterest));
                        }
                    }
                }

                shareMessage.Sender.SendMe(new SharedMessage(this));
            })
            .Case((UpdatePartitionMessage <TNode> updatePartitionMessage) =>
            {
                foreach (var change in updatePartitionMessage.Changes)
                {
                    partition[change.Key] = change.Value;
                }
            })
            .Case((SegmentRequestMessage segmentRequestMessage) =>
            {
                segmentRequestMessage.Sender.SendMe(new SegmentResponseMessage <TNode>(this, partition.Where(kvp => owner[kvp.Key] == this)));
            });
        }
예제 #5
0
        public object GetValueFromPath(Type entityType, PathComponent[] pathComponents, object entity)
        {
            try
            {
                if (entity == null)
                {
                    throw new JsonPatchException("The root object is null.");
                }

                object previous = entity;

                for (int i = 0; i < pathComponents.Length; i++)
                {
                    string parentPath    = PathComponent.GetFullPath(pathComponents.Take(i));
                    var    pathComponent = pathComponents[i];

                    TypeSwitch.On(pathComponent)
                    .Case((PropertyPathComponent component) =>
                    {
                        if (previous == null)
                        {
                            throw new JsonPatchException(string.Format(
                                                             "Cannot get property \"{0}\" from null object at path \"{1}\".",
                                                             component.Name, parentPath));
                        }

                        previous = component.GetPropertyInfo(previous).GetValue(previous);
                    })
                    .Case((CollectionIndexPathComponent component) =>
                    {
                        try
                        {
                            var list = (IList)previous;
                            previous = list[component.CollectionIndex];
                        }
                        catch (Exception e)
                        {
                            throw new JsonPatchException(string.Format(
                                                             "Cannot access index {0} from collection at path \"{1}\".",
                                                             component.CollectionIndex, parentPath), e);
                        }
                    });
                }

                return(previous);
            }
            catch (Exception e)
            {
                throw new JsonPatchException(string.Format(
                                                 "Failed to get value from path \"{0}\": {1}",
                                                 PathComponent.GetFullPath(pathComponents), e.Message), e);
            }
        }
예제 #6
0
        /// <summary>
        /// Views the did load.
        /// </summary>
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            base.StyleNavigationBar();

            _tilesCollectionView = new UICollectionView(new CGRect(), new TetrixLayout())
            {
                TranslatesAutoresizingMaskIntoConstraints = false,
                BackgroundColor = UIColor.White
            };
            _tilesCollectionView.RegisterClassForCell(typeof(TileCollectionViewCell), TileCollectionViewCell.Key);

            _tilesSource = new TetrixCollectionSource(_tilesCollectionView, TileCollectionViewCell.Key,
                                                      (item, collectionView, indexPath) =>
            {
                var cell = default(BaseCollectionViewCell);

                TypeSwitch.On(item)
                .Case((TileViewModel x) => cell = (BaseCollectionViewCell)collectionView.DequeueReusableCell(TileCollectionViewCell.Key, indexPath));

                //cell.DataContext = item;

                return(cell);
            });
            _tilesCollectionView.Source = _tilesSource;

            Add(_tilesCollectionView);

            var views = new DictionaryViews()
            {
                { "tilesCollectionView", _tilesCollectionView }
            };

            View.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|-20-[tilesCollectionView]-20-|", NSLayoutFormatOptions.DirectionLeftToRight, null, views)
                                .Concat(NSLayoutConstraint.FromVisualFormat("H:|-20-[tilesCollectionView]-20-|", NSLayoutFormatOptions.AlignAllTop, null, views))
                                .ToArray());

            this.WhenActivated(d =>
            {
                // We need to bind the ViewModel property to the DataContext in order to be able to
                // use WPF Bindings. Let's use WPF bindings for the UserName property.
                //this.Bind(ViewModel, vm => vm.Cells, v => v._tilesSource.ItemsSource);

                //set.Bind(_tilesSource).For(s => s.ItemsSource).To(vm => vm.Cells);
                //set.Bind(_tilesSource).For(cv => cv.SelectionChangedCommand)
                //   .To(vm => vm.SelectCommand);

                //OnAppear(new Dictionary<string, object>());
            });
        }
예제 #7
0
 private void MenuView_OnViewEvent(object sender, EventArgs e)
 {
     TypeSwitch.On(e.GetType())
     // paging
     .Case <GoToFirstPageEventArgs>(() => this.OnGoToFirstPageEvent())
     .Case <GoToPrevPageEventArgs>(() => this.OnGoToPrevPageEvent())
     .Case <GoToNextPageEventArgs>(() => this.OnGoToNextPageEvent())
     .Case <GoToLastPageEventArgs>(() => this.OnGoToLastPageEvent())
     // sorting
     .Case <SortByPersonPropertiesEventArgs>(() => this.OnSortEvent(
                                                 e.As <SortByPersonPropertiesEventArgs>().SortCriteria,
                                                 e.As <SortByPersonPropertiesEventArgs>().SortDirection))
     // exit
     .Case <ExitEventArgs>(() => this.OnExitEvent())
     // unknwon
     .Case <UnknownCommandEventArgs>(() => this.OnUnknownEvent(e.As <UnknownCommandEventArgs>()?.Command))
     .Evaluate();
 }
예제 #8
0
 private void AddEmitterToRoot(StatementSequenceEmitter rootEmitter, StatementSequenceNode astNode)
 {
     foreach (var astSubNode in astNode.SubNodes)
     {
         StatementSequenceEmitter emittedNode = new NoOpEmitter();
         TypeSwitch.On(astSubNode)
         .Case((VariableDeclarationNode variableDeclarationNode) =>
         {
             emittedNode = new VariableDeclarationNodeEmitter(variableDeclarationNode);
         })
         .Case((ReturnStatementNode returnStatementNode) =>
         {
             emittedNode = new ReturnStatementNodeEmitter(returnStatementNode);
         });
         if (astSubNode is StatementSequenceNode)
         {
             AddEmitterToRoot(emittedNode, astSubNode as StatementSequenceNode); //Also copy subnodes
         }
         rootEmitter.SubNodes.Add(emittedNode);
     }
 }
예제 #9
0
        public string Lookup <T>(T key, params string[] args) where T : struct, IConvertible
        {
            if (!typeof(T).IsEnum)
            {
                throw new ArgumentException("T must be an enumerated type");
            }

            var returnValue = string.Empty;
            var lookup      = (object)key;

            TypeSwitch.On <T>
            (
                TypeSwitch.Case <StringApplicationTemplate>(() =>
            {
                returnValue = Lookup((StringApplicationTemplate)lookup, args);
            }),
                TypeSwitch.Case <StringWarningTemplate>(() =>
            {
                returnValue = Lookup((StringWarningTemplate)lookup, args);
            }),
                TypeSwitch.Case <StringErrorTemplate>(() =>
            {
                returnValue = Lookup((StringErrorTemplate)lookup, args);
            }),
                TypeSwitch.Case <StringExceptionTemplate>(() =>
            {
                returnValue = Lookup((StringExceptionTemplate)lookup, args);
            }),
                TypeSwitch.Case <StringCacheKeyTemplate>(() =>
            {
                returnValue = Lookup((StringCacheKeyTemplate)lookup, args);
            }),
                TypeSwitch.Default(() =>
            {
                returnValue = StringHelper.Current.Lookup(key, args);
            })
            );

            return(returnValue);
        }
예제 #10
0
        public void SetValueFromPath(Type entityType, PathComponent[] pathComponents, object entity, object value, JsonPatchOperationType operationType)
        {
            try
            {
                PathComponent[] parent     = pathComponents.Take(pathComponents.Length - 1).ToArray();
                string          parentPath = PathComponent.GetFullPath(parent);

                object previous = GetValueFromPath(entityType, parent, entity);

                if (previous == null)
                {
                    throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is null.", parentPath));
                }

                var target = pathComponents.Last();

                TypeSwitch.On(target)
                .Case((PropertyPathComponent component) =>
                {
                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                    case JsonPatchOperationType.replace:
                        component.GetPropertyInfo(previous).SetValue(previous, ConvertValue(value, component.ComponentType));
                        break;

                    case JsonPatchOperationType.remove:
                        component.GetPropertyInfo(previous).SetValue(previous, null);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                })
                .Case((CollectionPathComponent component) =>
                {
                    var list = previous as IList;
                    if (list == null)
                    {
                        throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is not a valid collection.", parentPath));
                    }

                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                        list.Add(ConvertValue(value, component.ComponentType));
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                })
                .Case((CollectionPathComponent component) =>
                {
                    var list = previous as IList;
                    if (list == null)
                    {
                        throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is not a valid collection.", parentPath));
                    }

                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                        list.Add(ConvertValue(value, component.ComponentType));
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                })
                .Case((CollectionIndexPathComponent component) =>
                {
                    var list = previous as IList;
                    if (list == null)
                    {
                        throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is not a valid collection.", parentPath));
                    }

                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                        list.Insert(component.CollectionIndex, ConvertValue(value, component.ComponentType));
                        break;

                    case JsonPatchOperationType.remove:
                        list.RemoveAt(component.CollectionIndex);
                        break;

                    case JsonPatchOperationType.replace:
                        list[component.CollectionIndex] = ConvertValue(value, component.ComponentType);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                });
            }
            catch (Exception e)
            {
                throw new JsonPatchException(string.Format(
                                                 "Failed to set value at path \"{0}\" while performing \"{1}\" operation: {2}",
                                                 PathComponent.GetFullPath(pathComponents), operationType, e.Message), e);
            }
        }
예제 #11
0
        /// <summary>
        /// Posts the load subscriptions.
        /// </summary>
        /// <returns>The load subscriptions.</returns>
        public override IEnumerable <IDisposable> LoadSubscriptions()
        {
            yield return(ViewModel.WhenAnyValue(vm => vm.Feedbacks).BindTo <FeedbackListItemViewModel,
                                                                            FeedbackListItemTableViewCell>(_feedbackTableView, 80, cell => cell.Initialize()));

            yield return(ViewModel.WhenAnyValue(vm => vm.Infos)
                         .Select((IReactiveList <TetrixViewModelBase> list) =>
            {
                return list.GroupBy(model => (float)model.Height)
                .Select(typeGroup =>
                {
                    var collection = new ReactiveList <TetrixViewModelBase>();
                    collection.AddRange(typeGroup);

                    return new TableSectionInformation <TetrixViewModelBase, BaseTableViewCell>(collection, (model) =>
                    {
                        var cellIndentifier = "";

                        TypeSwitch.On(model)
                        .Case((HeaderListItemViewModel m) => cellIndentifier = HeaderTableViewCell.Key)
                        .Case((ContactListItemViewModel m) => cellIndentifier = ContactTableViewCell.Key);

                        return new NSString(cellIndentifier);
                    }, typeGroup.Key, cell => cell.Initialize());
                }).ToList();
            }).BindTo(_infoTableView));

            yield return(this.WhenAnyValue(v => v._tableSource.ElementSelected)
                         .Subscribe(x =>
            {
                // when ever this value is updated we want to make sure we only ever have
                // the latest subscription
                _serialDisposable.Disposable = x.Subscribe(vm => ViewModel.SelectFeedbackAsync());
            }));

            yield return(this.WhenAnyValue(v => v._infoTableSource.ElementSelected)
                         .Subscribe(x =>
            {
                // when ever this value is updated we want to make sure we only ever have
                // the latest subscription
                _serialDisposable.Disposable = x.Subscribe(vm => ViewModel.SelectContactAsync());
            }));

            yield return(Observable.FromEventPattern <PathUpdateEventArgs>(ViewModel, "PathUpdate")
                         .Window(() => Observable.Interval(TimeSpan.FromSeconds(2)))
                         .SelectMany(x => x.Take(1))
                         .SubscribeOn(ViewModel.Scheduler)
                         .Subscribe(e =>
            {
                var pathArgs = e.EventArgs;

                var latDif = pathArgs.StartCoordinate.Latitude - pathArgs.EndCoordinate.Latitude;
                var lonDif = pathArgs.StartCoordinate.Longitude - pathArgs.EndCoordinate.Longitude;
                var midLat = latDif / 2 + pathArgs.EndCoordinate.Latitude;
                var midLon = lonDif / 2 + pathArgs.EndCoordinate.Longitude;

                double dist = Math.Sqrt(latDif * latDif + lonDif * lonDif) * 90;

                var polyline = new List <CLLocationCoordinate2D>();

                foreach (var pathPoint in pathArgs.Path)
                {
                    polyline.Add(new CLLocationCoordinate2D(pathPoint.Latitude,
                                                            pathPoint.Longitude));
                }

                // Must update the UI on the main thread
                // set map center
                var mapCenter = new CLLocationCoordinate2D(midLat, midLon);
                var mapRegion = MKCoordinateRegion.FromDistance(mapCenter, dist * 2000, dist * 2000);

                // if _mkPolyLine not null, remove then recreate and re add
                if (_mkPolyLine != null)
                {
                    _mapView.RemoveOverlay(_mkPolyLine);
                    _mkPolyLine?.Dispose();
                }

                _mkPolyLine = MKPolyline.FromCoordinates(polyline.ToArray());

                _mapView.CenterCoordinate = mapCenter;
                _mapView.Region = mapRegion;

                // add map overlay for path
                _mapView.AddOverlay(_mkPolyLine);
            }));

            yield return(ViewModel.WhenAnyValue(vm => vm.LocationLoading)
                         .SubscribeOn(ViewModel.Scheduler)
                         .Subscribe(loading =>
            {
                if (loading)
                {
                    _progressView.StartAnimating();
                }
                else
                {
                    _progressView.StopAnimating();
                }
            }));
        }
예제 #12
0
        protected override void OnReceive(AbstractMessage message)
        {
            TypeSwitch.On(message)
            .Case((CoordinatorMessage coordinatorMessage) =>
            {
                k_max        = 0;
                partition    = new Dictionary <TNode, int>();
                oldNumBlocks = 0;
                blocks       = new HashSet <int>();
                workers      = coordinatorMessage.Workers;
                state        = new Dictionary <AbstractMachine, WorkerState>();

                var comparer1 = EqualityComparer <TLabel> .Default;
                var comparer2 = new Utils.HashSetEqualityComparer <Tuple <TLabel, int> >();
                var comparer  = new Utils.PairEqualityComparer <TLabel, HashSet <Tuple <TLabel, int> > >(comparer1, comparer2);
                signatures    = new Dictionary <Tuple <TLabel, HashSet <Tuple <TLabel, int> > >, int>(comparer);
                counter       = 0;

                foreach (var worker in workers)
                {
                    state.Add(worker, WorkerState.Refining);
                    worker.SendMe(new ClearMessage(this));
                }
            })
            .Case((ExactRefinedMessage <TLabel> refinedMessage) =>
            {
                state[refinedMessage.Sender] = WorkerState.Waiting;

                var remap = new Dictionary <int, int>();
                foreach (var kvp in refinedMessage.PartitionMap)
                {
                    if (!signatures.ContainsKey(kvp.Key))
                    {
                        signatures.Add(kvp.Key, counter++);
                    }

                    remap.Add(kvp.Value, signatures[kvp.Key]);
                }

                refinedMessage.Sender.SendMe(new RemapPartitionMessage(this, remap));

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    signatures.Clear();

                    // All workers have refined, now perform a share step
                    foreach (var worker in workers)
                    {
                        state[worker] = WorkerState.Sharing;
                        worker.SendMe(new ShareMessage(this));
                    }
                }
            })
            .Case((SharedMessage sharedMessage) =>
            {
                state[sharedMessage.Sender] = WorkerState.Waiting;

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    // All workers have shared, now count the number of unqiue blocks
                    oldNumBlocks = blocks.Count;
                    blocks.Clear();
                    foreach (var worker in workers)
                    {
                        state[worker] = WorkerState.Counting;
                        worker.SendMe(new CountMessage(this));
                    }
                }
            })
            .Case((CountedMessage countedMessage) =>
            {
                state[countedMessage.Sender] = WorkerState.Waiting;
                blocks.UnionWith(countedMessage.Blocks);

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    if (blocks.Count > oldNumBlocks)
                    {
                        // There was a change, continue refining
                        k_max += 1;
                        foreach (var worker in workers)
                        {
                            state[worker] = WorkerState.Refining;
                            worker.SendMe(new RefineMessage(this));
                        }
                    }
                    else
                    {
                        // We're done, collect global partition
                        k_max -= 1;
                        foreach (var worker in workers)
                        {
                            state[worker] = WorkerState.Collecting;
                            worker.SendMe(new SegmentRequestMessage(this));
                        }
                    }
                }
            })
            .Case((SegmentResponseMessage <TNode> segmentResponseMessage) =>
            {
                state[segmentResponseMessage.Sender] = WorkerState.Waiting;

                foreach (var pair in segmentResponseMessage.Pairs)
                {
                    partition.Add(pair.Key, pair.Value);
                }

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    onComplete(k_max, partition);
                }
            });
        }
        protected override void OnReceive(AbstractMessage message)
        {
            TypeSwitch.On(message)
            .Case((CoordinatorMessage coordinatorMessage) =>
            {
                k_max        = 0;
                partition    = new Dictionary <TNode, int>();
                oldNumBlocks = 0;
                blocks       = new HashSet <int>();
                workers      = coordinatorMessage.Workers;
                state        = new Dictionary <AbstractMachine, WorkerState>();

                foreach (var worker in workers)
                {
                    state.Add(worker, WorkerState.Refining);
                    worker.SendMe(new ClearMessage(this));
                }
            })
            .Case((EstimateRefinedMessage refinedMessage) =>
            {
                state[refinedMessage.Sender] = WorkerState.Waiting;

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    // All workers have refined, now perform a share step
                    foreach (var worker in workers)
                    {
                        state[worker] = WorkerState.Sharing;
                        worker.SendMe(new ShareMessage(this));
                    }
                }
            })
            .Case((SharedMessage sharedMessage) =>
            {
                state[sharedMessage.Sender] = WorkerState.Waiting;

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    // All workers have shared, now count the number of unqiue blocks
                    oldNumBlocks = blocks.Count;
                    blocks.Clear();
                    foreach (var worker in workers)
                    {
                        state[worker] = WorkerState.Counting;
                        worker.SendMe(new CountMessage(this));
                    }
                }
            })
            .Case((CountedMessage countedMessage) =>
            {
                state[countedMessage.Sender] = WorkerState.Waiting;
                blocks.UnionWith(countedMessage.Blocks);

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    if (blocks.Count > oldNumBlocks)
                    {
                        // There was a change, continue refining
                        k_max += 1;
                        foreach (var worker in workers)
                        {
                            state[worker] = WorkerState.Refining;
                            worker.SendMe(new RefineMessage(this));
                        }
                    }
                    else
                    {
                        // We're done, collect global partition
                        k_max -= 1;
                        foreach (var worker in workers)
                        {
                            state[worker] = WorkerState.Collecting;
                            worker.SendMe(new SegmentRequestMessage(this));
                        }
                    }
                }
            })
            .Case((SegmentResponseMessage <TNode> segmentResponseMessage) =>
            {
                state[segmentResponseMessage.Sender] = WorkerState.Waiting;

                foreach (var pair in segmentResponseMessage.Pairs)
                {
                    partition.Add(pair.Key, pair.Value);
                }

                if (workers.All(worker => state[worker] == WorkerState.Waiting))
                {
                    onComplete(k_max, partition);
                }
            });
        }