public static IScorable <IActivity, double> MakeDelegate(
            IDialogStack stack,
            IEnumerable <IScorable <IActivity, double> > fromActivity,
            IEnumerable <IScorable <IResolver, double> > fromResolver,
            Func <IActivity, IResolver> makeResolver,
            ITraits <double> traits,
            IComparer <double> comparer)
        {
            // since the stack of scorables changes over time, this should be lazy
            var relevant    = EnumerateRelevant(stack, fromActivity, fromResolver, makeResolver);
            var significant = relevant.Select(s => s.WhereScore((_, score) => comparer.Compare(score, traits.Minimum) >= 0));
            var scorable    = new TraitsScorable <IActivity, double>(traits, comparer, significant);

            return(scorable);
        }
        public async Task Scorable_Traits()
        {
            var tests = new[]
            {
                new { hasScore = false, score = Traits.Minimum },
                new { hasScore = true, score = Traits.Minimum },
                new { hasScore = true, score = Traits.Maximum },
                new { hasScore = true, score = Traits.Minimum + (Traits.Maximum - Traits.Minimum) / 2.0 },
            };

            foreach (var testOne in tests)
            {
                foreach (var testTwo in tests)
                {
                    // arrange
                    var mockOne   = Mock(Item, testOne.score, Token, testOne.hasScore);
                    var mockTwo   = Mock(Item, testTwo.score, Token, testTwo.hasScore);
                    var scorables = new[] { mockOne.Object, mockTwo.Object };
                    var test      = new TraitsScorable <string, double>(Traits, Comparer, scorables);
                    // act
                    bool actualPost = await test.TryPostAsync(Item, Token);

                    // assert
                    var expectedPost = testOne.hasScore || testTwo.hasScore;
                    Assert.AreEqual(expectedPost, actualPost);

                    bool earlyOut = testOne.hasScore && Comparer.Compare(testOne.score, Traits.Maximum) == 0;

                    var  compare  = Comparer.Compare(testOne.score, testTwo.score);
                    bool largeOne = (testOne.hasScore && !testTwo.hasScore) || (testOne.hasScore && testTwo.hasScore && compare >= 0);
                    bool largeTwo = (!testOne.hasScore && testTwo.hasScore) || (testOne.hasScore && testTwo.hasScore && compare < 0);

                    Verify(mockOne, Item, Token, Once(true), Many(true), Many(testOne.hasScore), Once(testOne.hasScore && largeOne));
                    Verify(mockTwo, Item, Token, Once(!earlyOut), Many(!earlyOut), Many(!earlyOut && testTwo.hasScore), Once(!earlyOut && testTwo.hasScore && largeTwo));
                }
            }
        }
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);

            builder.RegisterModule(new FiberModule <DialogTask>());

            // singleton components

            builder
            .Register(c => new ResourceManager("Microsoft.Bot.Builder.Resource.Resources", typeof(Resource.Resources).Assembly))
            .As <ResourceManager>()
            .SingleInstance();

            // every lifetime scope is driven by a message

            builder
            .Register((c, p) => p.TypedAs <IMessageActivity>())
            .AsSelf()
            .AsImplementedInterfaces()
            .InstancePerMatchingLifetimeScope(LifetimeScopeTag);

            // make the address and cookie available for the lifetime scope

            builder
            .Register(c => Address.FromActivity(c.Resolve <IActivity>()))
            .AsImplementedInterfaces()
            .InstancePerMatchingLifetimeScope(LifetimeScopeTag);

            builder
            .RegisterType <ResumptionCookie>()
            .AsSelf()
            .InstancePerMatchingLifetimeScope(LifetimeScopeTag);

            // components not marked as [Serializable]
            builder
            .RegisterType <MicrosoftAppCredentials>()
            .AsSelf()
            .SingleInstance();

            builder
            // not resolving IEqualityComparer<IAddress> from container because it's a very local policy
            // and yet too broad of an interface.  could explore using tags for registration overrides.
            .Register(c => new LocalMutualExclusion <IAddress>(new ConversationAddressComparer()))
            .As <IScope <IAddress> >()
            .SingleInstance();

            builder
            .Register(c => new ConnectorClientFactory(c.Resolve <IAddress>(), c.Resolve <MicrosoftAppCredentials>()))
            .As <IConnectorClientFactory>()
            .InstancePerLifetimeScope();

            builder
            .Register(c => c.Resolve <IConnectorClientFactory>().MakeConnectorClient())
            .As <IConnectorClient>()
            .InstancePerLifetimeScope();

            builder
            .Register(c => c.Resolve <IConnectorClientFactory>().MakeStateClient())
            .As <IStateClient>()
            .InstancePerLifetimeScope();

            builder
            .Register(c => new DetectChannelCapability(c.Resolve <IAddress>()))
            .As <IDetectChannelCapability>()
            .InstancePerLifetimeScope();

            builder
            .Register(c => c.Resolve <IDetectChannelCapability>().Detect())
            .As <IChannelCapability>()
            .InstancePerLifetimeScope();

            builder.RegisterType <ConnectorStore>()
            .AsSelf()
            .InstancePerLifetimeScope();

            // If bot wants to use InMemoryDataStore instead of
            // ConnectorStore, the below registration should be used
            // as the inner IBotDataStore for CachingBotDataStore

            /*builder.RegisterType<InMemoryDataStore>()
             *  .AsSelf()
             *  .SingleInstance(); */

            builder.Register(c => new CachingBotDataStore(c.Resolve <ConnectorStore>(),
                                                          CachingBotDataStoreConsistencyPolicy.ETagBasedConsistency))
            .As <IBotDataStore <BotData> >()
            .AsSelf()
            .InstancePerLifetimeScope();

            builder
            .RegisterType <JObjectBotData>()
            .As <IBotData>()
            .InstancePerLifetimeScope();

            builder
            .Register(c => new BotDataBagStream(c.Resolve <IBotData>().PrivateConversationData, BlobKey))
            .As <Stream>()
            .InstancePerLifetimeScope();

            builder
            .RegisterType <DialogTask>()
            .AsSelf()
            .As <IDialogStack>()
            .InstancePerLifetimeScope();

            // Scorable implementing "/deleteprofile"
            builder
            .Register(c => new Regex("^(\\s)*/deleteprofile", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace))
            .Keyed <Regex>(Key_DeleteProfile_Regex)
            .SingleInstance();

            builder
            .Register(c => new DeleteProfileScorable(c.Resolve <IDialogStack>(), c.Resolve <IBotData>(), c.Resolve <IBotToUser>(), c.ResolveKeyed <Regex>(Key_DeleteProfile_Regex)))
            .As <IScorable <IActivity, double> >()
            .InstancePerLifetimeScope();

            builder
            .Register(c =>
            {
                var stack      = c.Resolve <IDialogStack>();
                var fromStack  = stack.Frames.Select(f => f.Target).OfType <IScorable <IActivity, double> >();
                var fromGlobal = c.Resolve <IScorable <IActivity, double>[]>();
                // since the stack of scorables changes over time, this should be lazy
                var lazyScorables = fromStack.Concat(fromGlobal);
                var scorable      = new TraitsScorable <IActivity, double>(c.Resolve <ITraits <double> >(), c.Resolve <IComparer <double> >(), lazyScorables);
                return(scorable);
            })
            .InstancePerLifetimeScope()
            .AsSelf();

            builder
            .RegisterType <NullActivityLogger>()
            .AsImplementedInterfaces()
            .SingleInstance();

            builder
            .Register(c =>
            {
                var cc = c.Resolve <IComponentContext>();

                Func <IPostToBot> makeInner = () =>
                {
                    var task           = cc.Resolve <DialogTask>();
                    IDialogStack stack = task;
                    IPostToBot post    = task;
                    post = new ReactiveDialogTask(post, stack, cc.Resolve <IStore <IFiberLoop <DialogTask> > >(), cc.Resolve <Func <IDialog <object> > >());
                    post = new ExceptionTranslationDialogTask(post);
                    post = new LocalizedDialogTask(post);
                    post = new ScoringDialogTask <double>(post, stack, cc.Resolve <TraitsScorable <IActivity, double> >());
                    return(post);
                };

                IPostToBot outer = new PersistentDialogTask(makeInner, cc.Resolve <IBotData>());
                outer            = new SerializingDialogTask(outer, cc.Resolve <IAddress>(), c.Resolve <IScope <IAddress> >());
                outer            = new PostUnhandledExceptionToUserTask(outer, cc.Resolve <IBotToUser>(), cc.Resolve <ResourceManager>(), cc.Resolve <TraceListener>());
                outer            = new LogPostToBot(outer, cc.Resolve <IActivityLogger>());
                return(outer);
            })
            .As <IPostToBot>()
            .InstancePerLifetimeScope();

            builder
            .RegisterType <AlwaysSendDirect_BotToUser>()
            .AsSelf()
            .InstancePerLifetimeScope();

            builder
            .Register(c => new LogBotToUser(new MapToChannelData_BotToUser(
                                                c.Resolve <AlwaysSendDirect_BotToUser>(),
                                                new List <IMessageActivityMapper> {
                new KeyboardCardMapper()
            }), c.Resolve <IActivityLogger>()))
            .As <IBotToUser>()
            .InstancePerLifetimeScope();

            builder
            .RegisterType <DialogContext>()
            .As <IDialogContext>()
            .InstancePerLifetimeScope();
        }