public void TestCoalesce2() { StreamSink<int> s = new StreamSink<int>((x, y) => x + y); List<int> @out = new List<int>(); using (s.Listen(@out.Add)) { Transaction.RunVoid(() => { s.Send(1); s.Send(2); s.Send(3); s.Send(4); s.Send(5); }); Transaction.RunVoid(() => { s.Send(6); s.Send(7); s.Send(8); s.Send(9); s.Send(10); }); } CollectionAssert.AreEqual(new[] { 15, 40 }, @out.ToArray()); }
public void TestMapMemory() { int? beforeListenerCount = null; int? duringListenerCount = null; int? afterListenerCount = null; StreamSink<int> s = new StreamSink<int>(); Stream<string> m = s.Map(x => (x + 2).ToString()); List<string> @out = new List<string>(); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); ((Action)(() => { using (m.Listen(@out.Add)) { dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }))(); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before == After"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During > Before"); }
public void TestCalm() { StreamSink<int> s = new StreamSink<int>(); List<int> @out = new List<int>(); using (s.Calm().Listen(@out.Add)) { s.Send(2); s.Send(2); s.Send(2); s.Send(4); s.Send(2); s.Send(4); s.Send(4); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(4); s.Send(2); s.Send(4); s.Send(4); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(4); s.Send(2); s.Send(4); s.Send(4); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(4); s.Send(2); s.Send(4); s.Send(4); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(2); s.Send(4); s.Send(2); s.Send(4); s.Send(4); s.Send(2); s.Send(2); } CollectionAssert.AreEqual(new[] { 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2 }, @out); }
public void TestBaseSend1() { StreamSink<string> s = new StreamSink<string>(); List<string> @out = new List<string>(); using (s.Listen(@out.Add)) { s.Send("a"); s.Send("b"); } CollectionAssert.AreEqual(new[] { "a", "b" }, @out); }
public void TestHold() { StreamSink<int> e = new StreamSink<int>(); Cell<int> b = e.Hold(0); List<int> @out = new List<int>(); using (b.Listen(@out.Add)) { e.Send(2); e.Send(9); } CollectionAssert.AreEqual(new[] { 0, 2, 9 }, @out); }
public void TestHoldUpdates() { StreamSink<int> s = new StreamSink<int>(); Cell<int> c = s.Hold(0); List<int> @out = new List<int>(); using (Operational.Updates(c).Listen(@out.Add)) { s.Send(2); s.Send(9); } CollectionAssert.AreEqual(new[] { 2, 9 }, @out); }
public void TestMergeSimultaneous() { StreamSink <int> s = new StreamSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); using (s.Merge(s2, (x, y) => x + y).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 21, 27 }, @out); }
public void TestHold() { StreamSink <char> s = Stream.CreateSink <char>(); DiscreteCell <char> c = s.Hold(' '); List <char> @out = new List <char>(); IListener l = c.Listen(@out.Add); s.Send('C'); s.Send('B'); s.Send('A'); l.Unlisten(); CollectionAssert.AreEqual(new[] { ' ', 'C', 'B', 'A' }, @out); }
public void TestHoldUpdates() { StreamSink <int> e = new StreamSink <int>(); Cell <int> b = e.Hold(0); List <int> @out = new List <int>(); using (Operational.Updates(b).Listen(@out.Add)) { e.Send(2); e.Send(9); } CollectionAssert.AreEqual(new[] { 2, 9 }, @out); }
public void TestHoldIsDelayed() { StreamSink<int> s = new StreamSink<int>(); Cell<int> h = s.Hold(0); Stream<string> pair = s.Snapshot(h, (a, b) => a + " " + b); List<string> @out = new List<string>(); using (pair.Listen(@out.Add)) { s.Send(2); s.Send(3); } CollectionAssert.AreEqual(new[] { "2 0", "3 2" }, @out); }
private static Tuple <Stream <T>, ILookup <int, Action> > MkStream <T>(IReadOnlyList <Tuple <int, T> > firings, Func <T, T, T> coalesce) { StreamSink <T> s = Stream.CreateSink <T>(coalesce); ILookup <int, Action> f = firings.ToLookup(firing => firing.Item1, firing => (Action)(() => s.Send(firing.Item2))); if (f.Any(g => g.Key < 0)) { throw new InvalidOperationException("All firings must occur at T >= 0."); } Stream <T> returnStream = s; return(Tuple.Create(returnStream, f)); }
public void TestFilter() { StreamSink <char> s = new StreamSink <char>(); List <char> @out = new List <char>(); using (s.Filter(char.IsUpper).Listen(@out.Add)) { s.Send('H'); s.Send('o'); s.Send('I'); } CollectionAssert.AreEqual(new[] { 'H', 'I' }, @out); }
public void TestOrElseSimultaneous2() { StreamSink <int> s = new StreamSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); using (s.OrElse(s2).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 7, 9 }, @out); }
private static Tuple <Stream <T>, Dictionary <int, Action> > MkStream <T>(Dictionary <int, T> firings) { StreamSink <T> s = Stream.CreateSink <T>(); Dictionary <int, Action> f = firings.ToDictionary(firing => firing.Key, firing => (Action)(() => s.Send(firing.Value))); if (f.Keys.Any(k => k < 0)) { throw new InvalidOperationException("All firings must occur at T >= 0."); } Stream <T> returnStream = s; return(Tuple.Create(returnStream, f)); }
public void TestOnce() { StreamSink <char> s = new StreamSink <char>(); List <char> @out = new List <char>(); using (s.Once().Listen(@out.Add)) { s.Send('A'); s.Send('B'); s.Send('C'); } CollectionAssert.AreEqual(new[] { 'A' }, @out); }
public async Task TestListenOnceAsyncModify() { StreamSink <char> s = Stream.CreateSink <char>(); TaskWithListener <char> t = s.ListenOnceAsync(async t2 => await t2.ConfigureAwait(false)); GC.Collect(0, GCCollectionMode.Forced); s.Send('A'); s.Send('B'); s.Send('C'); char r = await t; Assert.AreEqual('A', r); }
public void TestMap() { StreamSink <int> s = new StreamSink <int>(); Stream <string> m = s.Map(x => (x + 2).ToString()); List <string> @out = new List <string>(); using (m.Listen(@out.Add)) { s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }
public void TestDefer() { StreamSink <char> s = Stream.CreateSink <char>(); Cell <char> c = s.Hold(' '); List <char> @out = new List <char>(); IListener l = Operational.Defer(s).Snapshot(c).Listen(@out.Add); s.Send('C'); s.Send('B'); s.Send('A'); l.Unlisten(); CollectionAssert.AreEqual(new[] { 'C', 'B', 'A' }, @out); }
public async Task TestListenOnceAsyncSameThreadWithCleanup() { StreamSink <char> s = Stream.CreateSink <char>(); TaskWithListener <char> t = s.ListenOnceAsync(); GC.Collect(0, GCCollectionMode.Forced); s.Send('A'); s.Send('B'); s.Send('C'); char r = await t; Assert.AreEqual('A', r); }
public void TestMergeNonSimultaneous() { StreamSink <int> s1 = Stream.CreateSink <int>(); StreamSink <int> s2 = Stream.CreateSink <int>(); List <int> @out = new List <int>(); IListener l = s1.Merge(s2, (x, y) => x + y).Listen(@out.Add); s1.Send(7); s2.Send(9); s1.Send(8); l.Unlisten(); CollectionAssert.AreEqual(new[] { 7, 9, 8 }, @out); }
public void TestHoldImplicitDelay() { StreamSink <char> s = Stream.CreateSink <char>(); Cell <char> c = s.Hold(' '); List <char> @out = new List <char>(); IListener l = s.Snapshot(c).Listen(@out.Add); s.Send('C'); s.Send('B'); s.Send('A'); l.Unlisten(); CollectionAssert.AreEqual(new[] { ' ', 'C', 'B' }, @out); }
public void TestOperationalSplit() { StreamSink <List <string> > a = Stream.CreateSink <List <string> >(); Stream <string> b = Operational.Split <string, List <string> >(a); List <string> @out = new List <string>(); IListener l = b.Listen(@out.Add); a.Send(new List <string> { "a", "b" }); l.Unlisten(); CollectionAssert.AreEqual(new[] { "a", "b" }, @out); }
public void TestOrElseLeftBias() { StreamSink <int> s = new StreamSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); using (s2.OrElse(s).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 14, 18 }, @out); }
public void TestStreamSend() { StreamSink <int> s = new StreamSink <int>(); List <int> @out = new List <int>(); using (s.Listen(@out.Add)) { s.Send(5); } CollectionAssert.AreEqual(new[] { 5 }, @out); s.Send(6); CollectionAssert.AreEqual(new[] { 5 }, @out); }
public void TestHold() { StreamSink <char> s = new StreamSink <char>(); Cell <char> b = s.Hold(' '); List <char> @out = new List <char>(); using (b.Listen(@out.Add)) { s.Send('C'); s.Send('B'); s.Send('A'); } CollectionAssert.AreEqual(new[] { ' ', 'C', 'B', 'A' }, @out); }
public SComboBox(Stream <IMaybe <T> > setSelectedItem, IMaybe <T> initSelectedItem, IEnumerable <T> items) { Action <IMaybe <T> > setSelectedItemImpl = m => base.SelectedItem = m.Match <object>(v => v, () => null); this.ItemsSource = items ?? new T[0]; setSelectedItemImpl(initSelectedItem); List <IListener> listeners = new List <IListener>(); StreamSink <int> sDecrement = new StreamSink <int>(); DiscreteCell <bool> allow = setSelectedItem.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0); Func <IMaybe <T> > getSelectedItem = () => { object sel = base.SelectedItem; return(sel == null?Maybe.Nothing <T>() : Maybe.Just((T)sel)); }; StreamSink <IMaybe <T> > sUserSelectedItem = new StreamSink <IMaybe <T> >(); this.SUserSelectedItem = sUserSelectedItem; this.SelectedItem = sUserSelectedItem.Gate(allow).OrElse(setSelectedItem).Hold(initSelectedItem); SelectionChangedEventHandler selectionChangedEventHandler = (sender, args) => { IMaybe <T> selectedItem = getSelectedItem(); this.Dispatcher.InvokeAsync(() => sUserSelectedItem.Send(selectedItem)); }; this.SelectionChanged += selectionChangedEventHandler; listeners.Add(setSelectedItem.Listen(m => { this.Dispatcher.InvokeAsync(() => { this.SelectionChanged -= selectionChangedEventHandler; setSelectedItemImpl(m); this.SelectionChanged += selectionChangedEventHandler; sDecrement.Send(-1); }); })); this.disposeListeners = () => { foreach (IListener l in listeners) { l.Unlisten(); } }; }
public void TestOperationalSplit() { StreamSink <List <string> > a = new StreamSink <List <string> >(); Stream <string> b = Operational.Split <string, List <string> >(a); List <string> @out = new List <string>(); using (b.Listen(@out.Add)) { a.Send(new List <string> { "a", "b" }); } CollectionAssert.AreEqual(new[] { "a", "b" }, @out); }
public void TestLazyCellCreation() { List <int> @out = new List <int>(); StreamSink <int> s = Stream.CreateSink <int>(); Cell <Cell <int> > c = Cell.Constant(1).Map(_ => s.Hold(0)); s.Send(1); IListener l = c.SwitchC().Listen(@out.Add); s.Send(3); s.Send(5); l.Unlisten(); CollectionAssert.AreEqual(new[] { 1, 3, 5 }, @out); }
public void Post() { Cell <int> cell = Transaction.Run(() => { StreamSink <int> s = Stream.CreateSink <int>(); s.Send(2); return(s.Hold(1)); }); int value = 0; Transaction.Post(() => value = cell.Sample()); Assert.AreEqual(2, value); }
public void TestHoldIsDelayed() { StreamSink <int> s = new StreamSink <int>(); Cell <int> h = s.Hold(0); Stream <string> pair = s.Snapshot(h, (a, b) => a + " " + b); List <string> @out = new List <string>(); using (pair.Listen(@out.Add)) { s.Send(2); s.Send(3); } CollectionAssert.AreEqual(new[] { "2 0", "3 2" }, @out); }
public void Run() { StreamSink <int> sX = Stream.CreateSink <int>(); Stream <int> sXPlus1 = sX.Map(x => x + 1); IListener l = Transaction.Run(() => { sX.Send(1); return(sXPlus1.Listen(Console.WriteLine)); }); sX.Send(2); sX.Send(3); l.Unlisten(); }
public void TestFilterMaybe() { StreamSink <Maybe <string> > s = Stream.CreateSink <Maybe <string> >(); List <string> @out = new List <string>(); IListener l = s.FilterMaybe().Listen(@out.Add); s.Send(Maybe.Some("tomato")); s.Send(Maybe.None); s.Send(Maybe.Some("peach")); s.Send(Maybe.None); s.Send(Maybe.Some("pear")); l.Unlisten(); CollectionAssert.AreEqual(new[] { "tomato", "peach", "pear" }, @out); }
public void TestDefer() { StreamSink <char> s = new StreamSink <char>(); Cell <char> c = s.Hold(' '); List <char> @out = new List <char>(); using (Operational.Defer(s).Snapshot(c).Listen(@out.Add)) { s.Send('C'); s.Send('B'); s.Send('A'); } CollectionAssert.AreEqual(new[] { 'C', 'B', 'A' }, @out); }
public async Task TestListenOnceAsyncModifyVoid2() { char r = ' '; StreamSink <char> s = Stream.CreateSink <char>(); TaskWithListener t = s.ListenOnceAsync(t2 => t2.ContinueWith(t3 => r = t3.Result, TaskContinuationOptions.ExecuteSynchronously)); GC.Collect(0, GCCollectionMode.Forced); s.Send('A'); s.Send('B'); s.Send('C'); await t; Assert.AreEqual('A', r); }
public void TestHoldImplicitDelay() { StreamSink <char> s = new StreamSink <char>(); Cell <char> c = s.Hold(' '); List <char> @out = new List <char>(); using (s.Snapshot(c).Listen(@out.Add)) { s.Send('C'); s.Send('B'); s.Send('A'); } CollectionAssert.AreEqual(new[] { ' ', 'C', 'B' }, @out); }
public void TestOrElseNonSimultaneous() { StreamSink <int> s1 = new StreamSink <int>(); StreamSink <int> s2 = new StreamSink <int>(); List <int> @out = new List <int>(); using (s1.OrElse(s2).Listen(@out.Add)) { s1.Send(7); s2.Send(9); s1.Send(8); } CollectionAssert.AreEqual(new[] { 7, 9, 8 }, @out); }
public SButton(Cell<bool> enabled) { StreamSink<Unit> sClickedSink = new StreamSink<Unit>(); this.SClicked = sClickedSink; this.Click += (sender, args) => sClickedSink.Send(Unit.Value); // Set the initial value at the end of the transaction so it works with CellLoops. Transaction.Post(() => this.IsEnabled = enabled.Sample()); // ReSharper disable once UseObjectOrCollectionInitializer List<IListener> listeners = new List<IListener>(); listeners.Add(Operational.Updates(enabled).Listen(e => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = e))); this.listeners = listeners; }
public void Run() { StreamSink<int> sX = new StreamSink<int>(); Stream<int> sXPlus1 = sX.Map(x => x + 1); using (Transaction.Run(() => { sX.Send(1); return sXPlus1.Listen(Console.WriteLine); })) { sX.Send(2); sX.Send(3); } }
public void TestAccum() { StreamSink<int> sa = new StreamSink<int>(); List<int> @out = new List<int>(); Cell<int> sum = sa.Accum(100, (a, s) => a + s); using (sum.Listen(@out.Add)) { sa.Send(5); sa.Send(7); sa.Send(1); sa.Send(2); sa.Send(3); } CollectionAssert.AreEqual(new[] { 100, 105, 112, 113, 115, 118 }, @out); }
public void TestMerge() { StreamSink <Unit> s = Stream.CreateSink <Unit>(); var obj = Transaction.Run(() => { StreamLoop <bool> loop = Stream.CreateLoop <bool>(); DiscreteCellStreamSink <int> s1 = new DiscreteCellStreamSink <int>(); DiscreteCellStreamSink <int> s2 = new DiscreteCellStreamSink <int>(); TestObject[] l = Enumerable.Range(0, 5000).Select(_ => new TestObject(loop, s1, s2)).ToArray(); loop.Loop(s.Snapshot(l.Select(o => o.Cell).Lift().Cell).Map(o => o.All(v => v == 0))); return(l); }); int[] values = obj.Select(v => v.CurrentValue).ToArray(); }
public void TestNestedMapGarbageCollection() { int? beforeStreamCount = null; int? beforeListenerCount = null; int? duringStreamCount = null; int? duringListenerCount = null; int? afterStreamCount = null; int? afterListenerCount = null; StreamSink<int> s = new StreamSink<int>(); List<string> @out = new List<string>(); dotMemory.Check(memory => beforeStreamCount = memory.GetObjects(where => where.Type.Is<Stream<int>>()).ObjectsCount + memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); ((Action)(() => { Stream<string> m = s.Map(x => x + 2).Map(x => 2 * x).Map(x => x + 1).Map(x => x.ToString()); using (m.Listen(@out.Add)) { dotMemory.Check(memory => duringStreamCount = memory.GetObjects(where => where.Type.Is<Stream<int>>()).ObjectsCount + memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "15", "11" }, @out); }))(); dotMemory.Check(memory => afterStreamCount = memory.GetObjects(where => where.Type.Is<Stream<int>>()).ObjectsCount + memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); // although all listeners and streams have been cleand up, the nodes will not be disconnected until the stream fires next Assert.AreEqual(1, s.Node.GetListeners().Count); s.Send(1); Assert.AreEqual(0, s.Node.GetListeners().Count); Assert.IsNotNull(beforeStreamCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringStreamCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(afterStreamCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeStreamCount, afterStreamCount, "Before Streams == After Streams"); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before Listeners == After Listeners"); Assert.IsTrue(duringStreamCount > beforeStreamCount, "During Streams > Before Streams"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During Listeners > Before Listeners"); }
public void TestSnapshot() { CellSink<int> c = new CellSink<int>(0); StreamSink<long> trigger = new StreamSink<long>(); List<string> @out = new List<string>(); using (trigger.Snapshot(c, (x, y) => x + " " + y).Listen(@out.Add)) { trigger.Send(100L); c.Send(2); trigger.Send(200L); c.Send(9); c.Send(1); trigger.Send(300L); } CollectionAssert.AreEqual(new[] { "100 0", "200 2", "300 1" }, @out); }
public void TestOperationalDefer1() { StreamSink<string> a = new StreamSink<string>(); Stream<string> b = Operational.Defer(a); List<string> @out = new List<string>(); using (b.Listen(@out.Add)) { a.Send("a"); } CollectionAssert.AreEqual(new[] { "a" }, @out); List<string> out2 = new List<string>(); using (b.Listen(out2.Add)) { a.Send("b"); } CollectionAssert.AreEqual(new[] { "b" }, out2); }
public void TestCollect() { StreamSink<int> sa = new StreamSink<int>(); List<int> @out = new List<int>(); Stream<int> sum = sa.Collect(Tuple.Create(100, true), (a, s) => { int outputValue = s.Item1 + (s.Item2 ? a * 3 : a); return Tuple.Create(outputValue, Tuple.Create(outputValue, outputValue % 2 == 0)); }); using (sum.Listen(@out.Add)) { sa.Send(5); sa.Send(7); sa.Send(1); sa.Send(2); sa.Send(3); } CollectionAssert.AreEqual(new[] { 115, 122, 125, 127, 130 }, @out); }
public async Task Run() { Console.WriteLine("*** test 1"); { StreamSink<string> s1 = new StreamSink<string>(); Task<string> t1 = s1.ListenOnce(); s1.Send("Early"); Console.WriteLine(await t1); } Console.WriteLine(); Console.WriteLine("*** test 2"); { StreamSink<string> s1 = new StreamSink<string>(); Task t1 = s1.ListenOnce().ContinueWith(t => Console.WriteLine(t.Result), TaskContinuationOptions.ExecuteSynchronously); s1.Send("Late"); await t1; } }
public void TestOperationalDeferSimultaneous() { StreamSink<string> a = new StreamSink<string>(); StreamSink<string> b = new StreamSink<string>(); Stream<string> c = Operational.Defer(a).OrElse(Operational.Defer(b)); List<string> @out = new List<string>(); using (c.Listen(@out.Add)) { b.Send("A"); } CollectionAssert.AreEqual(new[] { "A" }, @out); List<string> out2 = new List<string>(); using (c.Listen(out2.Add)) { Transaction.RunVoid(() => { a.Send("b"); b.Send("B"); }); } CollectionAssert.AreEqual(new[] { "b" }, out2); }
public FrView(Window window, Fridget fr, IListener l) { StreamSink<MouseEvent> sMouse = new StreamSink<MouseEvent>(); StreamSink<KeyEvent> sKey = new StreamSink<KeyEvent>(); this.MouseDown += (sender, args) => sMouse.Send(new MouseEvent(args, () => args.GetPosition(this))); this.MouseUp += (sender, args) => sMouse.Send(new MouseEvent(args, () => args.GetPosition(this))); this.MouseMove += (sender, args) => sMouse.Send(new MouseEvent(args, () => args.GetPosition(this))); CellSink<IMaybe<Size>> size = new CellSink<IMaybe<Size>>(Maybe.Nothing<Size>()); this.SizeChanged += (sender, args) => size.Send(Maybe.Just(args.NewSize)); window.KeyDown += (sender, args) => { Key key = args.Key == Key.System ? args.SystemKey : args.Key; if (key == Key.Back) { sKey.Send(new BackspaceKeyEvent()); } }; window.TextInput += (sender, args) => sKey.Send(new StringKeyEvent(args.Text)); CellLoop<long> focus = new CellLoop<long>(); Fridget.Output fo = fr.Reify(size, sMouse, sKey, focus, new Supply()); focus.Loop(fo.SChangeFocus.Hold(-1)); this.drawable = fo.Drawable; this.l = new ImmutableCompositeListener(new[] { l, Operational.Updates(this.drawable).Listen(d => this.InvalidateVisual()) }); }
public Implementation(PetrolPumpWindow petrolPump) { SComboBox<IPump> logic = new SComboBox<IPump>( new IPump[] { new LifeCyclePump(), new AccumulatePulsesPump(), new ShowDollarsPump(), new ClearSalePump(), new KeypadPump(), new PresetAmountPump() }, p => p.GetType().FullName); petrolPump.LogicComboBoxPlaceholder.Children.Add(logic); STextField textPrice1 = new STextField("2.149") { Width = 100 }; petrolPump.Price1Placeholder.Children.Add(textPrice1); STextField textPrice2 = new STextField("2.341") { Width = 100 }; petrolPump.Price2Placeholder.Children.Add(textPrice2); STextField textPrice3 = new STextField("1.499") { Width = 100 }; petrolPump.Price3Placeholder.Children.Add(textPrice3); Func<string, double> parseDoubleSafe = s => { double n; if (double.TryParse(s, out n)) { return n; } return 0.0; }; StreamSink<Key> sKey = new StreamSink<Key>(); Dictionary<Key, FrameworkElement> containersByKey = new Dictionary<Key, FrameworkElement> { { Key.One, petrolPump.Keypad1Button }, { Key.Two, petrolPump.Keypad2Button }, { Key.Three, petrolPump.Keypad3Button }, { Key.Four, petrolPump.Keypad4Button }, { Key.Five, petrolPump.Keypad5Button }, { Key.Six, petrolPump.Keypad6Button }, { Key.Seven, petrolPump.Keypad7Button }, { Key.Eight, petrolPump.Keypad8Button }, { Key.Nine, petrolPump.Keypad9Button }, { Key.Zero, petrolPump.Keypad0Button }, { Key.Clear, petrolPump.KeypadClearButton } }; foreach (KeyValuePair<Key, FrameworkElement> containerAndKey in containersByKey) { containerAndKey.Value.MouseDown += async (sender, args) => { if (args.LeftButton == MouseButtonState.Pressed) { await Task.Run(() => sKey.Send(containerAndKey.Key)); } }; } CellLoop<UpDown> nozzle1 = new CellLoop<UpDown>(); CellLoop<UpDown> nozzle2 = new CellLoop<UpDown>(); CellLoop<UpDown> nozzle3 = new CellLoop<UpDown>(); Cell<double> calibration = Cell.Constant(0.001); Cell<double> price1 = textPrice1.Text.Map(parseDoubleSafe); Cell<double> price2 = textPrice2.Text.Map(parseDoubleSafe); Cell<double> price3 = textPrice3.Text.Map(parseDoubleSafe); CellSink<Stream<Unit>> csClearSale = new CellSink<Stream<Unit>>(Sodium.Stream.Never<Unit>()); Stream<Unit> sClearSale = csClearSale.SwitchS(); StreamSink<int> sFuelPulses = new StreamSink<int>(); Cell<Outputs> outputs = logic.SelectedItem.Map( pump => pump.Create(new Inputs( Operational.Updates(nozzle1), Operational.Updates(nozzle2), Operational.Updates(nozzle3), sKey, sFuelPulses, calibration, price1, price2, price3, sClearSale))); Cell<Delivery> delivery = outputs.Map(o => o.Delivery).SwitchC(); Cell<string> presetLcd = outputs.Map(o => o.PresetLcd).SwitchC(); Cell<string> saleCostLcd = outputs.Map(o => o.SaleCostLcd).SwitchC(); Cell<string> saleQuantityLcd = outputs.Map(o => o.SaleQuantityLcd).SwitchC(); Cell<string> priceLcd1 = outputs.Map(o => o.PriceLcd1).SwitchC(); Cell<string> priceLcd2 = outputs.Map(o => o.PriceLcd2).SwitchC(); Cell<string> priceLcd3 = outputs.Map(o => o.PriceLcd3).SwitchC(); Stream<Unit> sBeep = outputs.Map(o => o.SBeep).SwitchS(); Stream<Sale> sSaleComplete = outputs.Map(o => o.SSaleComplete).SwitchS(); SoundPlayer beepPlayer = new SoundPlayer(GetResourceStream(@"sounds\beep.wav")); this.listeners.Add(sBeep.Listen(_ => new Thread(() => beepPlayer.PlaySync()) { IsBackground = true }.Start())); SoundPlayer fastRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\fast.wav")); Action stopFast = () => { }; Action playFast = () => { ManualResetEvent mre = new ManualResetEvent(false); new Thread(() => { fastRumblePlayer.PlayLooping(); mre.WaitOne(); fastRumblePlayer.Stop(); }) { IsBackground = true }.Start(); stopFast = () => mre.Set(); }; SoundPlayer slowRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\slow.wav")); Action stopSlow = () => { }; Action playSlow = () => { ManualResetEvent mre = new ManualResetEvent(false); new Thread(() => { slowRumblePlayer.PlayLooping(); mre.WaitOne(); slowRumblePlayer.Stop(); }) { IsBackground = true }.Start(); stopSlow = () => mre.Set(); }; this.listeners.Add(delivery.Changes().Listen(d => { petrolPump.Dispatcher.InvokeIfNecessary(() => { if (d == Delivery.Fast1 || d == Delivery.Fast2 || d == Delivery.Fast3) { playFast(); } else { stopFast(); } if (d == Delivery.Slow1 || d == Delivery.Slow2 || d == Delivery.Slow3) { playSlow(); } else { stopSlow(); } }); })); StackPanel presetLcdStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.PresetPlaceholder.Children.Add(presetLcdStackPanel); this.listeners.Add(presetLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(presetLcdStackPanel, t, 5, true)))); StackPanel saleCostStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.DollarsPlaceholder.Children.Add(saleCostStackPanel); this.listeners.Add(saleCostLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(saleCostStackPanel, t, 5, true)))); StackPanel saleQuantityLcdStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.LitersPlaceholder.Children.Add(saleQuantityLcdStackPanel); this.listeners.Add(saleQuantityLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(saleQuantityLcdStackPanel, t, 5, true)))); StackPanel priceLcd1StackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.Fuel1Placeholder.Children.Add(priceLcd1StackPanel); this.listeners.Add(priceLcd1.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd1StackPanel, t, 5, false)))); StackPanel priceLcd2StackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.Fuel2Placeholder.Children.Add(priceLcd2StackPanel); this.listeners.Add(priceLcd2.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd2StackPanel, t, 5, false)))); StackPanel priceLcd3StackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.Fuel3Placeholder.Children.Add(priceLcd3StackPanel); this.listeners.Add(priceLcd3.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd3StackPanel, t, 5, false)))); Dictionary<CellLoop<UpDown>, Image> nozzles = new Dictionary<CellLoop<UpDown>, Image> { { nozzle1, petrolPump.Nozzle1Image }, { nozzle2, petrolPump.Nozzle2Image }, { nozzle3, petrolPump.Nozzle3Image } }; this.listeners.AddRange(nozzles.Select(nozzle => nozzle.Key.Listen(p => petrolPump.Dispatcher.InvokeIfNecessary(() => nozzle.Value.Margin = p == UpDown.Up ? new Thickness(0, 0, 0, 0) : new Thickness(0, 30, 0, 0))))); foreach (KeyValuePair<CellLoop<UpDown>, Image> nozzle in nozzles) { StreamSink<Unit> nozzleClicks = new StreamSink<Unit>(); nozzle.Value.MouseDown += async (sender, args) => { if (args.LeftButton == MouseButtonState.Pressed) { await Task.Run(() => nozzleClicks.Send(Unit.Value)); } }; nozzle.Key.Loop(nozzleClicks.Snapshot(nozzle.Key, (_, n) => n == UpDown.Down ? UpDown.Up : UpDown.Down).Hold(UpDown.Down)); } this.listeners.Add(sSaleComplete.Listen(sale => { Task.Run(() => { petrolPump.Dispatcher.InvokeIfNecessary(() => { SaleCompleteDialog dialog = new SaleCompleteDialog( sale.Fuel.ToString(), Formatters.FormatPrice(sale.Price, null), Formatters.FormatSaleCost(sale.Cost), Formatters.FormatSaleQuantity(sale.Quantity)); dialog.Owner = petrolPump; csClearSale.Send(dialog.SOkClicked); dialog.Show(); IListener l = null; // ReSharper disable once RedundantAssignment l = dialog.SOkClicked.Listen(_ => { petrolPump.Dispatcher.InvokeIfNecessary(() => dialog.Close()); // ReSharper disable once AccessToModifiedClosure using (l) { } }); }); }); })); Task.Run(async () => { while (true) { Transaction.RunVoid(() => { switch (delivery.Sample()) { case Delivery.Fast1: case Delivery.Fast2: case Delivery.Fast3: sFuelPulses.Send(40); break; case Delivery.Slow1: case Delivery.Slow2: case Delivery.Slow3: sFuelPulses.Send(2); break; } }); await Task.Delay(200).ConfigureAwait(false); } // ReSharper disable once FunctionNeverReturns }); }
public void TestOnce() { StreamSink<char> s = new StreamSink<char>(); List<char> @out = new List<char>(); using (s.Once().Listen(@out.Add)) { s.Send('A'); s.Send('B'); s.Send('C'); } CollectionAssert.AreEqual(new[] { 'A' }, @out); }
public async Task Run() { Console.WriteLine("*** test"); { StreamSink<string> s1 = new StreamSink<string>(); Task<string> t1 = s1.ListenOnce(); new Thread(() => { s1.Send("Sent"); }).Start(); Console.WriteLine(await t1); } }
public void TestStreamSend() { StreamSink<int> s = new StreamSink<int>(); List<int> @out = new List<int>(); using (s.Listen(@out.Add)) { s.Send(5); } CollectionAssert.AreEqual(new[] { 5 }, @out); s.Send(6); CollectionAssert.AreEqual(new[] { 5 }, @out); }
public async Task Run() { Console.WriteLine("*** Simple test"); { StreamSink<string> sa = new StreamSink<string>(); StreamSink<string> sb = new StreamSink<string>(); Task<string> ta = sa.ListenOnce(); Task<string> tb = sb.ListenOnce(); Func<Task<string>> t = async () => await ta + " " + await tb; sa.Send("Hello"); Func<Task> task = () => t().ContinueWith(t1 => Console.WriteLine(t1.Result), TaskContinuationOptions.ExecuteSynchronously); sb.Send("World"); await task(); } Console.WriteLine(); Console.WriteLine("*** Simultaneous case"); { StreamSink<string> sa = new StreamSink<string>(); StreamSink<string> sb = new StreamSink<string>(); Task<string> ta = sa.ListenOnce(); Task<string> tb = sb.ListenOnce(); Func<Task<string>> t = async () => await ta + " " + await tb; Func<Task> task = () => t().ContinueWith(t1 => Console.WriteLine(t1.Result), TaskContinuationOptions.ExecuteSynchronously); Transaction.RunVoid(() => { sa.Send("Hello"); sb.Send("World"); }); await task(); } }
public void TestOrElseLeftBias() { StreamSink<int> s = new StreamSink<int>(); Stream<int> s2 = s.Map(x => 2 * x); List<int> @out = new List<int>(); using (s2.OrElse(s).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 14, 18 }, @out); }
public void TestOrElseNonSimultaneous() { StreamSink<int> s1 = new StreamSink<int>(); StreamSink<int> s2 = new StreamSink<int>(); List<int> @out = new List<int>(); using (s1.OrElse(s2).Listen(@out.Add)) { s1.Send(7); s2.Send(9); s1.Send(8); } CollectionAssert.AreEqual(new[] { 7, 9, 8 }, @out); }
public void TestOrElseSimultaneous1() { StreamSink<int> s1 = new StreamSink<int>((l, r) => r); StreamSink<int> s2 = new StreamSink<int>((l, r) => r); List<int> @out = new List<int>(); using (s2.OrElse(s1).Listen(@out.Add)) { Transaction.RunVoid(() => { s1.Send(7); s2.Send(60); }); Transaction.RunVoid(() => { s1.Send(9); }); Transaction.RunVoid(() => { s1.Send(7); s1.Send(60); s2.Send(8); s2.Send(90); }); Transaction.RunVoid(() => { s2.Send(8); s2.Send(90); s1.Send(7); s1.Send(60); }); Transaction.RunVoid(() => { s2.Send(8); s1.Send(7); s2.Send(90); s1.Send(60); }); } CollectionAssert.AreEqual(new[] { 60, 9, 90, 90, 90 }, @out); }
public void TestDefer() { StreamSink<char> s = new StreamSink<char>(); Cell<char> b = s.Hold(' '); List<char> @out = new List<char>(); using (Operational.Defer(s).Snapshot(b).Listen(@out.Add)) { s.Send('C'); s.Send('B'); s.Send('A'); } CollectionAssert.AreEqual(new[] { 'C', 'B', 'A' }, @out); }
public SButton() { StreamSink<Unit> sClickedSink = new StreamSink<Unit>(); this.SClicked = sClickedSink; this.Click += async (sender, args) => await Task.Run(() => sClickedSink.Send(Unit.Value)); }
public async Task Run() { Console.WriteLine("*** Simple test"); { StreamSink<string> sa = new StreamSink<string>(); StreamSink<string> sb = new StreamSink<string>(); Task<string> ta = sa.ListenOnce(); Task<string> tb = sb.ListenOnce(); new Thread(() => { sa.Send("Hello"); sb.Send("World"); }).Start(); Console.WriteLine(await ta + " " + await tb); } Console.WriteLine(); Console.WriteLine("*** Simultaneous case"); { StreamSink<string> sa = new StreamSink<string>(); StreamSink<string> sb = new StreamSink<string>(); Task<string> ta = sa.ListenOnce(); Task<string> tb = sb.ListenOnce(); new Thread(() => { Transaction.RunVoid(() => { sa.Send("Hello"); sb.Send("World"); }); }).Start(); Console.WriteLine(await ta + " " + await tb); } }
public void TestOrElseSimultaneous2() { StreamSink<int> s = new StreamSink<int>(); Stream<int> s2 = s.Map(x => 2 * x); List<int> @out = new List<int>(); using (s.OrElse(s2).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 7, 9 }, @out); }
public STextBox(Stream<string> setText, string initText, Cell<bool> enabled) { base.Text = initText; List<IListener> listeners = new List<IListener>(); StreamSink<int> sDecrement = new StreamSink<int>(); Cell<bool> allow = setText.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0); StreamSink<string> sUserChanges = new StreamSink<string>(); this.SUserChanges = sUserChanges; this.Text = sUserChanges.Gate(allow).OrElse(setText).Hold(initText); TextChangedEventHandler textChangedEventHandler = (sender, args) => { string text = base.Text; this.Dispatcher.InvokeAsync(() => sUserChanges.Send(text)); }; this.TextChanged += textChangedEventHandler; // Set the initial value at the end of the transaction so it works with CellLoops. Transaction.Post(() => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = enabled.Sample())); listeners.Add(setText.Listen(t => { this.Dispatcher.InvokeAsync(() => { this.TextChanged -= textChangedEventHandler; base.Text = t; this.TextChanged += textChangedEventHandler; sDecrement.Send(-1); }); })); listeners.Add(Operational.Updates(enabled).Listen(e => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = e))); this.disposeListeners = () => { foreach (IListener l in listeners) { using (l) { } } }; }