コード例 #1
0
ファイル: StreamTests.cs プロジェクト: zhouwensi/sodium
        public void TestLoopCell()
        {
            DiscreteCellSink <int> ca = DiscreteCell.CreateSink(22);
            ValueTuple <DiscreteCellLoop <int>, DiscreteCell <int>, DiscreteCell <int> > c = Transaction.Run(() =>
            {
                DiscreteCellLoop <int> cbLocal = DiscreteCell.CreateLoop <int>();
                DiscreteCell <int> ccLocal     = ca.Map(x => x % 10).Lift(cbLocal, (x, y) => x * y);
                DiscreteCell <int> cbOut       = ca.Map(x => x / 10);
                cbLocal.Loop(cbOut);
                return(ValueTuple.Create(cbLocal, cbOut, ccLocal));
            });
            DiscreteCellLoop <int> cb   = c.Item1;
            DiscreteCell <int>     cb2  = c.Item2;
            DiscreteCell <int>     cc   = c.Item3;
            List <int>             @out = new List <int>();
            List <int>             out2 = new List <int>();
            List <int>             out3 = new List <int>();
            IListener l  = cb.Listen(@out.Add);
            IListener l2 = cb2.Listen(out2.Add);
            IListener l3 = cc.Listen(out3.Add);

            ca.Send(2);
            ca.Send(52);
            l3.Unlisten();
            l2.Unlisten();
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 2, 0, 5 }, @out.ToArray());
            CollectionAssert.AreEqual(new[] { 2, 0, 5 }, out2.ToArray());
            CollectionAssert.AreEqual(new[] { 4, 0, 10 }, out3.ToArray());
        }
コード例 #2
0
        public void TestLoop()
        {
            Tuple <DiscreteCell <int>, DiscreteCellStreamSink <int> > result = Transaction.Run(() =>
            {
                DiscreteCellLoop <int> loop         = DiscreteCell.CreateLoop <int>();
                DiscreteCell <int> cLocal           = loop.Map(v => v * 5);
                DiscreteCellStreamSink <int> sLocal = new DiscreteCellStreamSink <int>();
                loop.Loop(sLocal.Hold(3));
                return(Tuple.Create(cLocal, sLocal));
            });

            DiscreteCell <int>           c = result.Item1;
            DiscreteCellStreamSink <int> s = result.Item2;

            List <int> output1 = new List <int>();
            List <int> output2 = new List <int>();
            IListener  l       = c.Listen(output1.Add);
            IListener  l2      = c.Updates.Listen(output2.Add);

            s.Send(5);
            s.Send(7);

            l2.Unlisten();
            l.Unlisten();

            CollectionAssert.AreEqual(new[] { 15, 25, 35 }, output1);
            CollectionAssert.AreEqual(new[] { 25, 35 }, output2);
        }
コード例 #3
0
ファイル: CellTests.cs プロジェクト: zzazang/sodium
        public void TestDiscreteCellLoopThrowsException()
        {
            //TODO: adjust the types so that loops can only be created safely through the type system

            Exception actual = null;

            try
            {
                StreamSink <int>   s    = new StreamSink <int>();
                DiscreteCell <int> cell = Transaction.Run(() =>
                {
                    DiscreteCellLoop <int> cellLoop = new DiscreteCellLoop <int>();
                    DiscreteCell <int> cellLocal    = cellLoop.Updates.Filter(v => v % 2 == 0).Map(v => v + 1).Merge(s, (_, r) => r).Hold(1);
                    cellLoop.Loop(cellLocal);
                    return(cellLocal);
                });
                List <int> @out = new List <int>();
                IListener  l    = cell.Listen(@out.Add);
                s.Send(3);
                s.Send(4);
                s.Send(7);
                s.Send(8);
                l.Unlisten();
            }
            catch (Exception e)
            {
                actual = e;
            }

            Assert.IsNotNull(actual);
            Assert.AreEqual("A dependency cycle was detected.", actual.Message);
        }
コード例 #4
0
ファイル: LoopTests.cs プロジェクト: tyahha/sodium
            public void TestSwitchSValuesLoop()
            {
                DiscreteCellStreamSink <IReadOnlyList <TestObject> > streamSink = new DiscreteCellStreamSink <IReadOnlyList <TestObject> >();
                DiscreteCell <IReadOnlyList <TestObject> >           cell       = Transaction.Run(() =>
                {
                    DiscreteCellLoop <IReadOnlyList <TestObject> > cellLoop = new DiscreteCellLoop <IReadOnlyList <TestObject> >();
                    DiscreteCell <IReadOnlyList <TestObject> > cellLocal    = streamSink.Map <Func <IReadOnlyList <TestObject>, IReadOnlyList <TestObject> > >(v => _ => v)
                                                                              .Merge(cellLoop.Map(oo => oo.Select(o => o.Output).Lift(vv => vv.Sum()).Values).SwitchS().Filter(sum => sum < 50).MapTo <Func <IReadOnlyList <TestObject>, IReadOnlyList <TestObject> > >(v => v.Concat(new[] { new TestObject() }).ToArray()), (f, g) => v => g(f(v)))
                                                                              .Snapshot(cellLoop, (f, v) => f(v))
                                                                              .Hold(Enumerable.Range(1, 10).Select(_ => new TestObject()).ToArray());
                    cellLoop.Loop(cellLocal);
                    return(cellLocal);
                });

                List <int> objectCounts = new List <int>();

                objectCounts.Add(-1);
                cell.Listen(vv => objectCounts.Add(vv.Count));
                objectCounts.Add(-1);
                cell.Cell.Sample()[2].Input1.Send(1);
                objectCounts.Add(-1);
                cell.Cell.Sample()[1].Input1.Send(-20);
                objectCounts.Add(-1);
                streamSink.Send(new TestObject[0]);
                objectCounts.Add(-1);

                // Ideal result, likely not achievable.
                //CollectionAssert.AreEquivalent(new[] { -1, 10, -1, 11, -1, 15, -1, 10, -1 }, objectCounts);

                // Glitchy result, also not returned by this method.
                //CollectionAssert.AreEquivalent(new[] { -1, 10, -1, 11, -1, 12, 13, 14, 15, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1 }, objectCounts);

                // Incorrect result we will see.
                CollectionAssert.AreEquivalent(new[] { -1, 10, -1, 11, -1, 12, -1, 0, -1 }, objectCounts);
            }
コード例 #5
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestSwitchC()
        {
            StreamSink <Sc> ssc = Stream.CreateSink <Sc>();
            // Split each field out of SB so we can update multiple behaviors in a
            // single transaction.
            DiscreteCell <char> ca = ssc.Map(s => s.A).FilterMaybe().Hold('A');
            DiscreteCell <char> cb = ssc.Map(s => s.B).FilterMaybe().Hold('a');
            DiscreteCell <DiscreteCell <char> > csw = ssc.Map(s => s.Sw).FilterMaybe().Hold(ca);
            DiscreteCell <char> co   = csw.SwitchC();
            List <char>         @out = new List <char>();
            IListener           l    = co.Listen(@out.Add);

            ssc.Send(new Sc(Maybe.Just('B'), Maybe.Just('b'), Maybe.Nothing <DiscreteCell <char> >()));
            ssc.Send(new Sc(Maybe.Just('C'), Maybe.Just('c'), Maybe.Just(cb)));
            ssc.Send(new Sc(Maybe.Just('D'), Maybe.Just('d'), Maybe.Nothing <DiscreteCell <char> >()));
            ssc.Send(new Sc(Maybe.Just('E'), Maybe.Just('e'), Maybe.Just(ca)));
            ssc.Send(new Sc(Maybe.Just('F'), Maybe.Just('f'), Maybe.Nothing <DiscreteCell <char> >()));
            ssc.Send(new Sc(Maybe.Nothing <char>(), Maybe.Nothing <char>(), Maybe.Just(cb)));
            ssc.Send(new Sc(Maybe.Nothing <char>(), Maybe.Nothing <char>(), Maybe.Just(ca)));
            ssc.Send(new Sc(Maybe.Just('G'), Maybe.Just('g'), Maybe.Just(cb)));
            ssc.Send(new Sc(Maybe.Just('H'), Maybe.Just('h'), Maybe.Just(ca)));
            ssc.Send(new Sc(Maybe.Just('I'), Maybe.Just('i'), Maybe.Just(ca)));
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 'A', 'B', 'c', 'd', 'E', 'F', 'f', 'F', 'g', 'H', 'I' }, @out);
        }
コード例 #6
0
ファイル: LoopTests.cs プロジェクト: tyahha/sodium
            public void TestSwitchCDeferredLoopWithBetterApi()
            {
                DiscreteCellStreamSink <IReadOnlyList <TestObject> > streamSink = new DiscreteCellStreamSink <IReadOnlyList <TestObject> >();
                DiscreteCell <IReadOnlyList <TestObject> >           cell       = Transaction.Run(() =>
                {
                    DiscreteCellLoop <IReadOnlyList <TestObject> > cellLoop = new DiscreteCellLoop <IReadOnlyList <TestObject> >();
                    DiscreteCell <IReadOnlyList <TestObject> > cellLocal    = streamSink
                                                                              .OrElse(Operational.Defer(cellLoop.Map(oo => oo.Select(o => o.Output).Lift(vv => vv.Sum())).SwitchCWithDeferredValues()).Filter(sum => sum < 50).Snapshot(cellLoop, (_, items) => (IReadOnlyList <TestObject>)items.Concat(new[] { new TestObject() }).ToArray()))
                                                                              .Hold(Enumerable.Range(1, 10).Select(_ => new TestObject()).ToArray());
                    cellLoop.Loop(cellLocal);
                    return(cellLocal);
                });

                List <int> objectCounts = new List <int>();

                objectCounts.Add(-1);
                cell.Listen(vv => objectCounts.Add(vv.Count));
                objectCounts.Add(-1);
                cell.Cell.Sample()[2].Input1.Send(1);
                objectCounts.Add(-1);
                cell.Cell.Sample()[1].Input1.Send(-20);
                objectCounts.Add(-1);
                streamSink.Send(new TestObject[0]);
                objectCounts.Add(-1);

                // Ideal result, likely not achievable.
                //CollectionAssert.AreEquivalent(new[] { -1, 10, -1, 11, -1, 15, -1, 10, -1 }, objectCounts);

                // Glitchy result, but correct otherwise.
                CollectionAssert.AreEquivalent(new[] { -1, 10, -1, 11, -1, 12, 13, 14, 15, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1 }, objectCounts);
            }
コード例 #7
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestSwitchCSimultaneous()
        {
            Sc2 sc1 = new Sc2(0);
            DiscreteCellSink <Sc2> csc  = DiscreteCell.CreateSink(sc1);
            DiscreteCell <int>     co   = csc.Map <DiscreteCell <int> >(b => b.C).SwitchC();
            List <int>             @out = new List <int>();
            IListener l   = co.Listen(@out.Add);
            Sc2       sc2 = new Sc2(3);
            Sc2       sc3 = new Sc2(4);
            Sc2       sc4 = new Sc2(7);

            sc1.C.Send(1);
            sc1.C.Send(2);
            csc.Send(sc2);
            sc1.C.Send(3);
            sc2.C.Send(4);
            sc3.C.Send(5);
            csc.Send(sc3);
            sc3.C.Send(6);
            sc3.C.Send(7);
            Transaction.RunVoid(() =>
            {
                sc3.C.Send(2);
                csc.Send(sc4);
                sc4.C.Send(8);
            });
            sc4.C.Send(9);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, @out);
        }
コード例 #8
0
        /// <summary>
        ///     A timer that fires at the specified time.
        /// </summary>
        /// <param name="t">The time to fire at.</param>
        /// <returns>A stream which fires at the specified time.</returns>
        public Stream <T> At(DiscreteCell <Maybe <T> > t)
        {
            StreamSink <T> alarm        = new StreamSink <T>();
            Maybe <ITimer> currentTimer = Maybe.None;
            IListener      l            = t.Listen(
                m =>
            {
                currentTimer.MatchSome(timer => timer.Cancel());
                currentTimer = m.Match(
                    time => Maybe.Some(
                        this.implementation.SetTimer(
                            time,
                            () =>
                {
                    lock (this.eventQueue)
                    {
                        this.eventQueue.Enqueue(new Event(time, alarm));
                    }
                    // Open and close a transaction to trigger queued
                    // events to run.
                    Transaction.RunVoid(() => { });
                })),
                    () => Maybe.None);
            });

            return(alarm.AttachListener(l));
        }
コード例 #9
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestHold()
        {
            StreamSink <int>   s    = Stream.CreateSink <int>();
            DiscreteCell <int> c    = s.Hold(0);
            List <int>         @out = new List <int>();
            IListener          l    = c.Listen(@out.Add);

            s.Send(2);
            s.Send(9);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 0, 2, 9 }, @out);
        }
コード例 #10
0
ファイル: StreamTests.cs プロジェクト: zhouwensi/sodium
        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);
        }
コード例 #11
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestMapLateListen()
        {
            DiscreteCellSink <int> c    = DiscreteCell.CreateSink(6);
            List <string>          @out = new List <string>();
            DiscreteCell <string>  cm   = c.Map(x => x.ToString());

            c.Send(2);
            IListener l = cm.Listen(@out.Add);

            c.Send(8);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { "2", "8" }, @out);
        }
コード例 #12
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestLiftGlitch()
        {
            DiscreteCellSink <int> c1   = DiscreteCell.CreateSink(1);
            DiscreteCell <int>     c3   = c1.Map(x => x * 3);
            DiscreteCell <int>     c5   = c1.Map(x => x * 5);
            DiscreteCell <string>  c    = c3.Lift(c5, (x, y) => x + " " + y);
            List <string>          @out = new List <string>();
            IListener l = c.Listen(@out.Add);

            c1.Send(2);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { "3 5", "6 10" }, @out);
        }
コード例 #13
0
ファイル: StreamTests.cs プロジェクト: zhouwensi/sodium
        public void TestAccum()
        {
            StreamSink <int>   sa   = Stream.CreateSink <int>();
            List <int>         @out = new List <int>();
            DiscreteCell <int> sum  = sa.Accum(100, (a, s) => a + s);
            IListener          l    = sum.Listen(@out.Add);

            sa.Send(5);
            sa.Send(7);
            sa.Send(1);
            sa.Send(2);
            sa.Send(3);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 100, 105, 112, 113, 115, 118 }, @out);
        }
コード例 #14
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestLiftListLarge()
        {
            IReadOnlyList <DiscreteCellSink <int> > cellSinks = Enumerable.Range(0, 500).Select(_ => DiscreteCell.CreateSink(1)).ToArray();
            DiscreteCell <int> sum  = cellSinks.Lift().Map(v => v.Sum());
            List <int>         @out = new List <int>();
            IListener          l    = sum.Listen(@out.Add);

            cellSinks[4].Send(5);
            cellSinks[5].Send(5);
            Transaction.RunVoid(() =>
            {
                cellSinks[9].Send(5);
                cellSinks[17].Send(5);
                cellSinks[41].Send(5);
                cellSinks[48].Send(5);
            });
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 500, 504, 508, 524 }, @out);
        }
コード例 #15
0
        public void TestLiftInSwitchC()
        {
            IReadOnlyList <Test> list1 = new[] { new Test(0), new Test(1), new Test(2), new Test(3), new Test(4) };
            IReadOnlyList <Test> list2 = new[] { new Test(5), new Test(6), new Test(7), new Test(8), new Test(9) };

            DiscreteCellSink <IReadOnlyList <Test> > v = DiscreteCell.CreateSink(list1);

            DiscreteCell <IReadOnlyList <int> > c = v.Map(oo => oo.Select(o => o.Value).Lift()).SwitchC();

            List <IReadOnlyList <int> > streamOutput = new List <IReadOnlyList <int> >();
            IListener l = c.Updates.Listen(streamOutput.Add);

            List <IReadOnlyList <int> > cellOutput = new List <IReadOnlyList <int> >();
            IListener l2 = c.Listen(cellOutput.Add);

            list1[2].Value.Send(12);
            list2[1].Value.Send(16);
            list1[4].Value.Send(14);
            Transaction.RunVoid(() =>
            {
                list2[2].Value.Send(17);
                list1[0].Value.Send(10);
                v.Send(list2);
            });
            list1[3].Value.Send(13);
            list2[3].Value.Send(18);

            l2.Unlisten();
            l.Unlisten();

            Assert.AreEqual(4, streamOutput.Count);
            Assert.AreEqual(5, cellOutput.Count);

            CollectionAssert.AreEqual(new[] { 0, 1, 2, 3, 4 }, cellOutput[0]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 4 }, streamOutput[0]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 4 }, cellOutput[1]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 14 }, streamOutput[1]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 14 }, cellOutput[2]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 8, 9 }, streamOutput[2]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 8, 9 }, cellOutput[3]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 18, 9 }, streamOutput[3]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 18, 9 }, cellOutput[4]);
        }
コード例 #16
0
ファイル: LoopTests.cs プロジェクト: tyahha/sodium
            public void TestSwitchCLoop()
            {
                Exception actual = null;

                try
                {
                    DiscreteCellStreamSink <IReadOnlyList <TestObject> > streamSink = new DiscreteCellStreamSink <IReadOnlyList <TestObject> >();
                    DiscreteCell <IReadOnlyList <TestObject> >           cell       = Transaction.Run(() =>
                    {
                        DiscreteCellLoop <IReadOnlyList <TestObject> > cellLoop = new DiscreteCellLoop <IReadOnlyList <TestObject> >();
                        DiscreteCell <IReadOnlyList <TestObject> > cellLocal    = streamSink.Map <Func <IReadOnlyList <TestObject>, IReadOnlyList <TestObject> > >(v => _ => v)
                                                                                  .Merge(cellLoop.Map(oo => oo.Select(o => o.Output).Lift(vv => vv.Sum())).SwitchC().Updates.Filter(sum => sum < 50).MapTo <Func <IReadOnlyList <TestObject>, IReadOnlyList <TestObject> > >(v => v.Concat(new[] { new TestObject() }).ToArray()), (f, g) => v => g(f(v)))
                                                                                  .Snapshot(cellLoop, (f, v) => f(v))
                                                                                  .Hold(Enumerable.Range(1, 10).Select(_ => new TestObject()).ToArray());
                        cellLoop.Loop(cellLocal);
                        return(cellLocal);
                    });

                    List <int> objectCounts = new List <int>();
                    objectCounts.Add(-1);
                    cell.Listen(vv => objectCounts.Add(vv.Count));
                    objectCounts.Add(-1);
                    cell.Cell.Sample()[2].Input1.Send(1);
                    objectCounts.Add(-1);
                    cell.Cell.Sample()[1].Input1.Send(-20);
                    objectCounts.Add(-1);
                    streamSink.Send(new TestObject[0]);
                    objectCounts.Add(-1);
                }
                catch (AggregateException e)
                {
                    actual = e.InnerExceptions.FirstOrDefault(ex => ex.Message == "A dependency cycle was detected.");
                }
                catch (Exception e)
                {
                    actual = e;
                }

                Assert.IsNotNull(actual);
                Assert.AreEqual("A dependency cycle was detected.", actual.Message);
            }
コード例 #17
0
ファイル: StreamTests.cs プロジェクト: zhouwensi/sodium
        public async Task TestListenAsync()
        {
            DiscreteCellSink <int> a  = DiscreteCell.CreateSink(1);
            DiscreteCell <int>     a1 = a.Map(x => x + 1);
            DiscreteCell <int>     a2 = a.Map(x => x * 2);
            ValueTuple <List <int>, DiscreteCellLoop <int>, IListener> resultsAndCalled = Transaction.Run(() =>
            {
                DiscreteCell <int> result         = a1.Lift(a2, (x, y) => x + y);
                Stream <Unit> incrementStream     = Operational.Value(result.Cell).MapTo(Unit.Value);
                StreamSink <Unit> decrementStream = Stream.CreateSink <Unit>();
                DiscreteCellLoop <int> calledLoop = DiscreteCell.CreateLoop <int>();
                calledLoop.Loop(incrementStream.MapTo(1).Merge(decrementStream.MapTo(-1), (x, y) => x + y).Snapshot(calledLoop.Cell, (u, c) => c + u).Hold(0));
                List <int> r = new List <int>();
                IListener l  = result.Listen(v =>
                {
                    Task.Run(async() =>
                    {
                        await Task.Delay(900);
                        r.Add(v);
                        decrementStream.Send(Unit.Value);
                    });
                });
                return(ValueTuple.Create(r, calledLoop, l));
            });
            // ReSharper disable once UnusedVariable
            List <int>         results       = resultsAndCalled.Item1;
            DiscreteCell <int> called        = resultsAndCalled.Item2;
            List <int>         calledResults = new List <int>();
            IListener          l2            = called.Listen(calledResults.Add);

            await Task.Delay(500);

            a.Send(2);
            await Task.Delay(500);

            a.Send(3);
            await Task.Delay(2500);

            l2.Unlisten();
            resultsAndCalled.Item3.Unlisten();
        }
コード例 #18
0
ファイル: CellTests.cs プロジェクト: zzazang/sodium
        public void TestDiscreteCellLoop()
        {
            StreamSink <int>   s    = new StreamSink <int>();
            DiscreteCell <int> cell = Transaction.Run(() =>
            {
                DiscreteCellLoop <int> cellLoop = new DiscreteCellLoop <int>();
                DiscreteCell <int> cellLocal    = s.Snapshot(cellLoop, (x, y) => x + y).Hold(1);
                cellLoop.Loop(cellLocal);
                return(cellLocal);
            });
            List <int> @out = new List <int>();
            IListener  l    = cell.Listen(@out.Add);

            s.Send(3);
            s.Send(4);
            s.Send(7);
            s.Send(8);
            l.Unlisten();

            CollectionAssert.AreEqual(new[] { 1, 4, 8, 15, 23 }, @out);
        }
コード例 #19
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void SwitchCCatchFirst()
        {
            List <int> output = new List <int>();

            ValueTuple <DiscreteCell <int>, DiscreteCellSink <int>, DiscreteCellSink <int>, DiscreteCellSink <DiscreteCell <int> >, IListener> t = Transaction.Run(() =>
            {
                DiscreteCellSink <int> c1 = DiscreteCell.CreateSink(1);
                DiscreteCellSink <int> c2 = DiscreteCell.CreateSink(11);
                DiscreteCellSink <DiscreteCell <int> > s = DiscreteCell.CreateSink(c1.AsDiscreteCell());
                DiscreteCell <int> c = s.SwitchC();

                c1.Send(2);
                c2.Send(12);
                s.Send(c2);

                IListener l = c.Listen(output.Add);

                return(ValueTuple.Create(c, c1, c2, s, l));
            });

            t.Item2.Send(3);
            t.Item3.Send(13);

            Transaction.RunVoid(() =>
            {
                t.Item2.Send(4);
                t.Item3.Send(14);
                t.Item4.Send(t.Item2);
            });

            t.Item2.Send(5);
            t.Item3.Send(15);

            t.Item5.Unlisten();

            CollectionAssert.AreEqual(new[] { 12, 13, 4, 5 }, output);
        }
コード例 #20
0
ファイル: CellTests.cs プロジェクト: zhouwensi/sodium
        public void TestLiftListLargeManyUpdates()
        {
            IReadOnlyList <DiscreteCellSink <int> > cellSinks = Enumerable.Range(0, 500).Select(_ => DiscreteCell.CreateSink(1)).ToArray();
            DiscreteCell <int> sum  = cellSinks.Lift().Map(v => v.Sum());
            List <int>         @out = new List <int>();
            IListener          l    = sum.Listen(@out.Add);

            for (int i = 0; i < 100; i++)
            {
                int n = i;
                cellSinks[n * 5].Send(5);
                cellSinks[n * 5 + 1].Send(5);
                Transaction.RunVoid(() =>
                {
                    cellSinks[n * 5 + 2].Send(5);
                    cellSinks[n * 5 + 3].Send(5);
                    cellSinks[n * 5 + 4].Send(5);
                });
            }
            l.Unlisten();
            IReadOnlyList <int> expected = new[] { 500 }.Concat(Enumerable.Range(0, 100).SelectMany(n => new[] { 500 + 20 * n + 4, 500 + 20 * n + 8, 500 + 20 * n + 20 })).ToArray();

            CollectionAssert.AreEqual(expected, @out);
        }
コード例 #21
0
            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));
                        }
                    };
                }

                DiscreteCellLoop <UpDown> nozzle1 = new DiscreteCellLoop <UpDown>();
                DiscreteCellLoop <UpDown> nozzle2 = new DiscreteCellLoop <UpDown>();
                DiscreteCellLoop <UpDown> nozzle3 = new DiscreteCellLoop <UpDown>();

                DiscreteCell <double>             calibration = DiscreteCell.Constant(0.001);
                DiscreteCell <double>             price1      = textPrice1.Text.Map(parseDoubleSafe);
                DiscreteCell <double>             price2      = textPrice2.Text.Map(parseDoubleSafe);
                DiscreteCell <double>             price3      = textPrice3.Text.Map(parseDoubleSafe);
                DiscreteCellSink <Stream <Unit> > csClearSale = new DiscreteCellSink <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(
                                            nozzle1.Updates,
                                            nozzle2.Updates,
                                            nozzle3.Updates,
                                            sKey,
                                            sFuelPulses,
                                            calibration,
                                            price1,
                                            price2,
                                            price3,
                                            sClearSale)));

                DiscreteCell <Delivery> delivery        = outputs.Map(o => o.Delivery).SwitchC();
                DiscreteCell <string>   presetLcd       = outputs.Map(o => o.PresetLcd).SwitchC();
                DiscreteCell <string>   saleCostLcd     = outputs.Map(o => o.SaleCostLcd).SwitchC();
                DiscreteCell <string>   saleQuantityLcd = outputs.Map(o => o.SaleQuantityLcd).SwitchC();
                DiscreteCell <string>   priceLcd1       = outputs.Map(o => o.PriceLcd1).SwitchC();
                DiscreteCell <string>   priceLcd2       = outputs.Map(o => o.PriceLcd2).SwitchC();
                DiscreteCell <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         = () => { };

                void PlayFast()
                {
                    ManualResetEvent mre = new ManualResetEvent(false);

                    new Thread(() =>
                    {
                        fastRumblePlayer.PlayLooping();
                        mre.WaitOne();
                        fastRumblePlayer.Stop();
                    })
                    {
                        IsBackground = true
                    }.Start();
                    stopFast = () =>
                    {
                        mre.Set();
                        stopFast = () => { };
                    };
                }

                SoundPlayer slowRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\slow.wav"));
                Action      stopSlow         = () => { };

                void PlaySlow()
                {
                    ManualResetEvent mre = new ManualResetEvent(false);

                    new Thread(() =>
                    {
                        slowRumblePlayer.PlayLooping();
                        mre.WaitOne();
                        slowRumblePlayer.Stop();
                    })
                    {
                        IsBackground = true
                    }.Start();
                    stopSlow = () =>
                    {
                        mre.Set();
                        stopSlow = () => { };
                    };
                }

                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 <DiscreteCellLoop <UpDown>, Image> nozzles = new Dictionary <DiscreteCellLoop <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 <DiscreteCellLoop <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
                                l?.Unlisten();
                            });
                        });
                    });
                }));

                Task.Run(async() =>
                {
                    while (true)
                    {
                        Transaction.RunVoid(() =>
                        {
                            switch (delivery.Cell.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
                });
            }