public FrFlow(Orientation dir, IEnumerable <Fridget> fridgets) : base((size, sMouse, sKey, focus, idSupply) => { DiscreteCell <Size> desiredSize = DiscreteCell.Constant(new Size(0, 0)); DiscreteCell <DrawableDelegate> drawable = DiscreteCell.Constant(new DrawableDelegate(d => { })); Stream <long> sChangeFocus = Stream.Never <long>(); foreach (Fridget fridget in fridgets) { DiscreteCellLoop <Maybe <Size> > childSz = new DiscreteCellLoop <Maybe <Size> >(); Output fo = new FrTranslate(fridget, dir == Orientation.Horizontal ? desiredSize.Map(dsz => new Point(dsz.Width, 0)) : desiredSize.Map(dsz => new Point(0, dsz.Height))) .Reify(childSz, sMouse, sKey, focus, idSupply.Child1()); idSupply = idSupply.Child2(); childSz.Loop( size.Lift(fo.DesiredSize, (mSize, foDsz) => mSize.Map(s => dir == Orientation.Horizontal ? new Size(foDsz.Width, s.Height) : new Size(s.Width, foDsz.Height)))); Size LiftDesiredSizeHorizontal(Size dsz, Size foDsz) => new Size(dsz.Width + foDsz.Width, dsz.Height > foDsz.Height ? dsz.Height : foDsz.Height); Size LiftDesiredSizeVertical(Size dsz, Size foDsz) => new Size(dsz.Width > foDsz.Width ? dsz.Width : foDsz.Width, dsz.Height + foDsz.Height); desiredSize = desiredSize.Lift(fo.DesiredSize, dir == Orientation.Horizontal ? LiftDesiredSizeHorizontal : (Func <Size, Size, Size>)LiftDesiredSizeVertical); drawable = drawable.Lift(fo.Drawable, (drA, drB) => drA.Append(drB)); sChangeFocus = sChangeFocus.OrElse(fo.SChangeFocus); } return(new Output(drawable, desiredSize, sChangeFocus)); }) { }
public NotifyPointOfSale( LifeCycle lc, Stream <Unit> sClearSale, Fill fi) { DiscreteCell <bool> locked = lc.SStart.Map(u => true).OrElse(sClearSale.Map(u => false)).Hold(false); this.SStart = lc.SStart.Gate(locked.Map(l => !l)); this.SEnd = lc.SEnd.Gate(locked); this.FuelFlowing = this.SStart.Map(Maybe.Just).OrElse( this.SEnd.Map(f => Maybe.Nothing <Fuel>())).Hold(Maybe.Nothing <Fuel>()); this.FillActive = this.SStart.Map(Maybe.Just).OrElse( sClearSale.Map(f => Maybe.Nothing <Fuel>())).Hold(Maybe.Nothing <Fuel>()); this.SBeep = sClearSale; this.SSaleComplete = this.SEnd.Snapshot( this.FuelFlowing.Lift( fi.Price, fi.DollarsDelivered, fi.LitersDelivered, (oFuel, price, dollars, liters) => oFuel.Match(v => Maybe.Just( new Sale(v, price, dollars, liters)), Maybe.Nothing <Sale>))).FilterMaybe(); }
public MainWindow() { this.InitializeComponent(); IReadOnlyList <Tuple <Grid, Grid> > emailAndValidationPlaceholders = new[] { Tuple.Create(this.Email1Placeholder, this.Email1ValidationPlaceholder), Tuple.Create(this.Email2Placeholder, this.Email2ValidationPlaceholder), Tuple.Create(this.Email3Placeholder, this.Email3ValidationPlaceholder), Tuple.Create(this.Email4Placeholder, this.Email4ValidationPlaceholder) }; int maxEmails = emailAndValidationPlaceholders.Count; STextBox name = new STextBox(string.Empty) { Width = 200 }; this.NamePlaceholder.Children.Add(name); DiscreteCell <string> nameValidationError = name.Text.Map(t => string.IsNullOrEmpty(t.Trim()) ? "<-- enter something" : t.Trim().IndexOf(' ') < 0 ? "<-- must contain space" : string.Empty); DiscreteCell <bool> isNameValid = nameValidationError.Map(string.IsNullOrEmpty); SLabel validName = new SLabel(nameValidationError); this.NameValidationPlaceholder.Children.Add(validName); SSpinner number = SSpinner.Create(1); this.NumberOfEmailAddressesPlaceholder.Children.Add(number); DiscreteCell <string> numberOfEmailAddressesValidationError = number.Value.Map(n => n <1 || n> maxEmails ? "<-- must be 1 to " + maxEmails : string.Empty); DiscreteCell <bool> isNumberOfEmailAddressesValid = numberOfEmailAddressesValidationError.Map(string.IsNullOrEmpty); SLabel validNumber = new SLabel(numberOfEmailAddressesValidationError); this.NumberOfEmailAddressesValidationPlaceholder.Children.Add(validNumber); IReadOnlyList <DiscreteCell <bool> > validEmails = emailAndValidationPlaceholders.Select((p, i) => { DiscreteCell <bool> enabled = number.Value.Map(n => i < n); STextBox email = new STextBox(string.Empty, enabled) { Width = 200 }; p.Item1.Children.Add(email); DiscreteCell <string> validText = email.Text.Lift(number.Value, (e, n) => i >= n ? string.Empty : string.IsNullOrEmpty(e.Trim()) ? "<-- enter something" : e.IndexOf('@') < 0 ? "<-- must contain @" : string.Empty); SLabel validEmail = new SLabel(validText); p.Item2.Children.Add(validEmail); return(validText.Map(string.IsNullOrEmpty)); }).ToArray(); DiscreteCell <bool> allValid = validEmails.Concat(new[] { isNameValid, isNumberOfEmailAddressesValid }).Lift(vv => vv.All(v => v)); SButton ok = new SButton(allValid) { Content = "OK", Width = 75 }; this.ButtonPlaceholder.Children.Add(ok); }
public void Test_MapC_TestCase() { Tuple <Stream <int>, Dictionary <int, Action> > st = MkStream(new Dictionary <int, int> { { 2, 3 }, { 3, 5 } }); Stream <int> s = st.Item1; Dictionary <int, Action> sf = st.Item2; DiscreteCell <int> c = s.Hold(0); List <int> @out = RunSimulation <int>(c.Map(x => x + 1).Listen, new[] { sf }); CollectionAssert.AreEqual(new[] { 1, 4, 6 }, @out); }
private FrButton(DiscreteCell <string> label, StreamLoop <Unit> sClicked) : base((size, sMouse, sKey, focus, idSupply) => { Stream <Unit> sPressed = sMouse.Snapshot(size, (e, mSize) => mSize.Match( s => { MouseButtonEventArgs b = e.Args as MouseButtonEventArgs; Point p = e.GetPosition(); return(b != null && b.ChangedButton == MouseButton.Left && b.ButtonState == MouseButtonState.Pressed && p.X >= 2 && p.X < s.Width - 2 && p.Y >= 2 && p.Y < s.Height - 2 ? Maybe.Just(Unit.Value) : Maybe.Nothing <Unit>()); }, Maybe.Nothing <Unit>)).FilterMaybe(); Stream <Unit> sReleased = sMouse.Snapshot(size, (e, mSize) => mSize.Match( s => { MouseButtonEventArgs b = e.Args as MouseButtonEventArgs; return(b != null && b.ChangedButton == MouseButton.Left && b.ButtonState == MouseButtonState.Released ? Maybe.Just(Unit.Value) : Maybe.Nothing <Unit>()); }, Maybe.Nothing <Unit>)).FilterMaybe(); DiscreteCell <bool> pressed = sPressed.MapTo(true).OrElse(sReleased.MapTo(false)).Hold(false); sClicked.Loop(sReleased.Gate(pressed)); Typeface typeface = new Typeface(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); DiscreteCell <Size> desiredSize = label.Map(l => { Size labelSize = FontUtilities.MeasureString(l, typeface, 13); return(new Size(labelSize.Width + 14, labelSize.Height + 10)); }); return(new Output( label.Lift( size, pressed, (l, mSize, p) => new DrawableDelegate(d => { mSize.Match(sz => { d.DrawRectangle(p ? Brushes.DarkGray : Brushes.LightGray, new Pen(Brushes.Black, 1), new Rect(new Point(2, 2), new Size(sz.Width - 5, sz.Height - 5))); FormattedText t = FontUtilities.GetStandardFormattedText(l, typeface, 13, Brushes.Black); d.DrawText(t, new Point((sz.Width - t.Width) / 2, (sz.Height - t.Height) / 2)); }, () => { }); })), desiredSize, Stream.Never <long>())); }) { this.SClicked = sClicked; }
public Frp(Action <string> addMessage) { this.listener = Transaction.Run(() => { DiscreteCell <Maybe <DragInfo> > dragInfo = this.sMouseDown.Map(me => Maybe.Some(new DragInfo(me, Canvas.GetLeft(me.Element.Polygon).ZeroIfNaN(), Canvas.GetTop(me.Element.Polygon).ZeroIfNaN()))) .OrElse(this.sMouseUp.Map(_ => Maybe <DragInfo> .None)).Hold(Maybe.None); Stream <MouseEvt> mouseMoveWhileDragging = dragInfo.Map(md => md.Match(d => this.sMouseMove, Stream.Never <MouseEvt>)).SwitchS(); IListener listener1 = dragInfo.Values.FilterMaybe().Listen(d => addMessage("FRP dragging " + d.Me.Element.Name)); IListener listener2 = mouseMoveWhileDragging.Snapshot(dragInfo, (me, md) => md.Match(d => Maybe.Some(new Reposition(d, me)), () => Maybe.None)).FilterMaybe().Listen(p => { Canvas.SetLeft(p.Polygon, p.Left); Canvas.SetTop(p.Polygon, p.Top); }); return(new CompositeListener(new[] { listener1, listener2 })); }); }
public Outputs Create(Inputs inputs) { LifeCycle lc = new LifeCycle(inputs.SNozzle1, inputs.SNozzle2, inputs.SNozzle3); DiscreteCell <double> litersDelivered = Accumulate(lc.SStart.Map(_ => Unit.Value), inputs.SFuelPulses, inputs.Calibration); return(new Outputs() .SetDelivery(lc.FillActive.Map( m => m.Equals(Maybe.Just(Fuel.One)) ? Delivery.Fast1 : m.Equals(Maybe.Just(Fuel.Two)) ? Delivery.Fast2 : m.Equals(Maybe.Just(Fuel.Three)) ? Delivery.Fast3 : Delivery.Off)) .SetSaleQuantityLcd(litersDelivered.Map(Formatters.FormatSaleQuantity))); }
public MainWindow() { this.InitializeComponent(); STextBox txtA = new STextBox("5") { Width = 100 }; STextBox txtB = new STextBox("10") { Width = 100 }; DiscreteCell <int> a = txtA.Text.Map(ParseInt); DiscreteCell <int> b = txtB.Text.Map(ParseInt); DiscreteCell <int> sum = a.Lift(b, (x, y) => x + y); SLabel lblSum = new SLabel(sum.Map(i => i.ToString())); this.Container.Children.Add(txtA); this.Container.Children.Add(txtB); this.Container.Children.Add(lblSum); }
private static Stream <Signal> BounceAt(TimerSystem <double> sys, DiscreteCell <Signal> vel, DiscreteCell <Signal> pos, double target) { return(sys.At(pos.Map(p => p.When(target))).Snapshot(vel, (t, v) => new Signal(t, v.A, v.B, -v.ValueAt(t) * Restitution))); }
public Frp(Action <string> addMessage) { this.listener = Transaction.Run(() => { DiscreteCell <Maybe <DragInfo> > dragInfo = this.sMouseDown.Map(me => Maybe.Some(new DragInfo(me, Canvas.GetLeft(me.Element.Polygon).ZeroIfNaN(), Canvas.GetTop(me.Element.Polygon).ZeroIfNaN()))) .OrElse(this.sMouseUp.Map(_ => Maybe <DragInfo> .None)).Hold(Maybe.None); DiscreteCell <bool> axisLock = this.sShift.Hold(false); DiscreteCell <Maybe <Tuple <MouseEvt, bool> > > mouseMoveAndAxisLock = dragInfo.Map(md => md.Match( d => this.sMouseMove.Hold(d.Me).Lift(axisLock, Tuple.Create).Map(Maybe.Some), () => DiscreteCell.Constant(Maybe <Tuple <MouseEvt, bool> > .None))).SwitchC(); IListener listener1 = dragInfo.Values.FilterMaybe().Listen(d => addMessage("FRP dragging " + d.Me.Element.Name)); IListener listener2 = mouseMoveAndAxisLock .Values .FilterMaybe() .Snapshot(dragInfo, (ma, md) => md.Match(d => Maybe.Some(new Reposition(d, ma.Item1, ma.Item2)), () => Maybe.None)) .FilterMaybe() .Listen(p => { Canvas.SetLeft(p.Polygon, p.Left); Canvas.SetTop(p.Polygon, p.Top); }); return(new CompositeListener(new[] { listener1, listener2 })); }); }
public void TestDiscreteCellLoopComplex() { StreamSink <int> s = new StreamSink <int>(); StreamSink <Tuple <int, int> > addItemStreamSink = new StreamSink <Tuple <int, int> >(); StreamSink <IReadOnlyList <TestObject> > removeItemsStreamSink = new StreamSink <IReadOnlyList <TestObject> >(); DiscreteCell <IReadOnlyList <TestObject> > listCell = Transaction.Run(() => { DiscreteCellLoop <IReadOnlyList <TestObject> > listCellLoop = new DiscreteCellLoop <IReadOnlyList <TestObject> >(); DiscreteCell <IReadOnlyList <TestObject> > listCellLocal = addItemStreamSink.OrElse(s.Map(v => Tuple.Create(v, v))).Map <Func <IReadOnlyList <TestObject>, IReadOnlyList <TestObject> > >(o => c => c.Concat(new[] { new TestObject(o.Item1, o.Item2) }).ToArray()) .Merge(removeItemsStreamSink.Map <Func <IReadOnlyList <TestObject>, IReadOnlyList <TestObject> > >(o => c => c.Except(o).ToArray()), (f, g) => c => g(f(c))) .Snapshot(listCellLoop, (f, c) => f(c)) .Hold(new TestObject[0]); listCellLoop.Loop(listCellLocal); return(listCellLocal); }); IListener l2 = Transaction.Run(() => { return(listCell.Values.Listen(c => Transaction.Post(() => { if (c.Any()) { Tuple <int, int> t = c.Last().BothNumbersCell.Cell.Sample(); if (t.Item1 == 9 && t.Item2 == 9) { addItemStreamSink.Send(Tuple.Create(0, 0)); } } }))); }); IListener l3 = Transaction.Run(() => listCell.Map(c => c.Select(o => o.RemoveStream.MapTo(new[] { o })).Merge((x, y) => x.Concat(y).ToArray())).SwitchS().Listen(o => Transaction.Post(() => removeItemsStreamSink.Send(o)))); IListener l4 = Transaction.Run(() => listCell.Map(c => c.Any() ? c.Last().Number1Cell.Lift(c.Last().Number2Cell, (x, y) => x == 9 && y == 9).Updates : Stream.Never <bool>()).SwitchS().Filter(v => v).Listen(_ => Transaction.Post(() => addItemStreamSink.Send(Tuple.Create(0, 0))))); List <IReadOnlyList <Tuple <int, int> > > @out = new List <IReadOnlyList <Tuple <int, int> > >(); IListener l = listCell.Map(c => c.Select(o => o.Number1Cell.Lift(o.Number2Cell, Tuple.Create)).Lift()).SwitchC().Listen(@out.Add); addItemStreamSink.Send(Tuple.Create(5, 2)); addItemStreamSink.Send(Tuple.Create(9, 2)); listCell.Cell.Sample()[0].Remove(); addItemStreamSink.Send(Tuple.Create(2, 9)); listCell.Cell.Sample()[1].ChangeNumber1(9); addItemStreamSink.Send(Tuple.Create(9, 9)); s.Send(5); s.Send(9); Transaction.RunVoid(() => { addItemStreamSink.Send(Tuple.Create(5, 5)); s.Send(5); }); listCell.Cell.Sample()[8].ChangeNumber2(9); listCell.Cell.Sample()[8].ChangeNumber1(9); l.Unlisten(); l2.Unlisten(); l3.Unlisten(); l4.Unlisten(); Tuple <int, int>[][] expected = { new Tuple <int, int> [0], new[] { Tuple.Create(5,2) }, new[] { Tuple.Create(5,2), Tuple.Create(9, 2) }, new[] { Tuple.Create(9,2) }, new[] { Tuple.Create(9,2), Tuple.Create(2, 9) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5), Tuple.Create(9, 9) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5), Tuple.Create(9, 9), Tuple.Create(0, 0) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 9) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9) }, new[] { Tuple.Create(9,2), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(5, 5), Tuple.Create(9, 9), Tuple.Create(0, 0), Tuple.Create(9, 9), Tuple.Create(0, 0) } }; Assert.AreEqual(expected.Length, @out.Count); for (int i = 0; i < 16; i++) { CollectionAssert.AreEqual(@out[i], expected[i]); } }