Ejemplo n.º 1
0
        private static Tuple<string, WinningBean[]> GetWinnersSprtLineage(string lineage, Tuple<string, WinningBean[]> existing, WinningBean[] candidates, int maxPerLineage, bool tracksLivingInstances)
        {

            List<WinningBean> distinctBeans = new List<WinningBean>();

            if (tracksLivingInstances)
            {
                // Existing and candidate lists could have the same instance of a bean (from different moments in time).  Group by
                // bean instances
                var beanGroups = UtilityCore.Iterate(existing == null ? null : existing.Item2, candidates).
                    GroupBy(o => o.Ship.PhysicsBody).		// the physics body implements IComparable (compares on token)
                    ToArray();

                // Now pull only the best example from each instance of a bean
                foreach (var group in beanGroups)
                {
                    distinctBeans.Add(group.OrderByDescending(o => o.Score).First());
                }
            }
            else
            {
                // DNA should never be shared between existing and new, so everything is unique
                distinctBeans = UtilityCore.Iterate(existing == null ? null : existing.Item2, candidates).ToList();
            }

            // Sort by score, and take the top performers
            WinningBean[] retVal = distinctBeans.
                OrderByDescending(o => o.Score).
                Take(maxPerLineage).
                ToArray();

            // Exit Function
            return Tuple.Create(lineage, retVal);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This merges the current tree with the beans passed in.  Only keeps the top performers, independent of where they came from
        /// </summary>
        private static Tuple<DateTime, WinningSet[]> GetWinners(Tuple<DateTime, WinningSet[]> existing, WinningBean[] candidates, int maxLineages, int maxPerLineage, bool tracksLivingInstances)
        {
            List<WinningSet> retVal = new List<WinningSet>();

            #region Validate candidates

            if (candidates != null)
            {
                if (tracksLivingInstances)
                {
                    if (candidates.Any(o => o.DNA != null))
                    {
                        throw new ArgumentException("When tracking live instances, raw dna shouldn't be passed in");
                    }
                }
                else
                {
                    if (candidates.Any(o => o.Ship != null))
                    {
                        throw new ArgumentException("When tracking dna, live instances shouldn't be passed in");
                    }
                }
            }

            #endregion

            // Shoot through all the unique names across exising and candidate
            foreach (string name in UtilityCore.Iterate(
                existing == null ? null : existing.Item2.Select(o => o.ShipName),
                tracksLivingInstances ? candidates.Select(o => o.Ship.Name) : candidates.Select(o => o.DNA.ShipName)
                ).Distinct())
            {
                // Each name is treated independently of the other names.  So one name could have far worse winners than
                // others, and it wouldn't matter
                retVal.Add(GetWinnersSprtName(name,
                    existing == null ? null : existing.Item2.Where(o => o.ShipName == name).FirstOrDefault(),
                    tracksLivingInstances ? candidates.Where(o => o.Ship.Name == name).ToArray() : candidates.Where(o => o.DNA.ShipName == name).ToArray(),
                    maxLineages, maxPerLineage, tracksLivingInstances));
            }

            // Sort the list by the highest performer
            return Tuple.Create(DateTime.UtcNow,
                retVal.OrderByDescending(o => o.BeansByLineage.Max(p => p.Item2.Max(q => q.Score))).
                ToArray());
        }
Ejemplo n.º 3
0
        private static WinningSet GetWinnersSprtName(string name, WinningSet existing, WinningBean[] candidates, int maxLineages, int maxPerLineage, bool tracksLivingInstances)
        {
            if (candidates == null)
            {
                #region Validate Existing

                //TODO: See if the constraints are more restrictive
                //if (existing != null)
                //{
                //    if (existing.BeansByLineage.Length > maxLineages)
                //    {

                //    }
                //}

                #endregion
                return existing;
            }

            // Group the candidates up by lineage
            var candidateLineage = candidates.GroupBy(o => tracksLivingInstances ? o.Ship.Lineage : o.DNA.ShipLineage).ToArray();

            List<Tuple<string, WinningBean[]>> retVal = new List<Tuple<string, WinningBean[]>>();

            // Shoot through all the unique lineages across existing and candidate
            foreach (string lineage in UtilityCore.Iterate(
                existing == null ? null : existing.BeansByLineage.Select(o => o.Item1),
                candidateLineage.Select(o => o.Key)).
                Distinct())
            {
                var matchingCandidate = candidateLineage.Where(o => o.Key == lineage).FirstOrDefault();

                // Get the top beans for this lineage
                retVal.Add(GetWinnersSprtLineage(lineage,
                    existing == null ? null : existing.BeansByLineage.Where(o => o.Item1 == lineage).FirstOrDefault(),
                    matchingCandidate == null ? null : matchingCandidate.ToArray(),
                    maxPerLineage, tracksLivingInstances));
            }

            // Sort, take top
            return new WinningSet(name,
                retVal.OrderByDescending(o => o.Item2.Max(p => p.Score)).
                Take(maxLineages).
                ToArray());
        }
Ejemplo n.º 4
0
        private static WinningBean[] RemoveBeansSprtArgs(List<Tuple<long, WinningBean>> returnList, WinningBean[] beans, long[] removals)
        {
            if (beans == null)
            {
                return null;
            }

            List<WinningBean> remaining = new List<WinningBean>();

            for (int cntr = 0; cntr < beans.Length; cntr++)
            {
                long token = beans[cntr].Ship.PhysicsBody.Token;
                if (removals.Contains(token))
                {
                    returnList.Add(Tuple.Create(token, beans[cntr]));
                }
                else
                {
                    remaining.Add(beans[cntr]);
                }
            }

            return remaining.ToArray();
        }
Ejemplo n.º 5
0
        /// <summary>
        /// This pulls beans out of the list passed in and the current tree
        /// </summary>
        private Tuple<long, WinningBean>[] RemoveBeans(out WinningBean[] remaining, WinningBean[] beans, long[] removals)
        {
            List<Tuple<long, WinningBean>> retVal = new List<Tuple<long, WinningBean>>();

            // Reduce the list of beans passed in
            remaining = RemoveBeansSprtArgs(retVal, beans, removals);

            //NOTE: Since there could be other threads working this tree, it's possible for removed beans to reemerge.  But that would
            //only happen if StoreWinners is called faster than a thread can process, which shouldn't happen in reality
            _current = RemoveBeansSprtTree(retVal, _current, removals);

            // Exit Function
            return retVal.ToArray();
        }
Ejemplo n.º 6
0
        private Tuple<long, WinningBean>[] StoreWinnersSprtDoIt(WinningBean[] beans, long[] removals)
        {
            if ((removals == null || removals.Length == 0) && (beans == null || beans.Length == 0))
            {
                return null;
            }

            // Remove - this thread
            Tuple<long, WinningBean>[] retVal = null;
            WinningBean[] reducedBeans = beans;
            if (removals != null && removals.Length > 0)
            {
                retVal = RemoveBeans(out reducedBeans, beans, removals);
            }

            if (reducedBeans != null && reducedBeans.Length > 0)
            {
                int maxLineages = this.MaxLineages;
                int maxPerLineage = this.MaxPerLineage;
                bool tracksLiveInstances = this.TracksLivingInstances;

                #region Merge - other thread

                // Merge the scores passed in with the current winners
                var task = Task.Factory.StartNew(() =>
                {
                    // Merge
                    return GetWinners(_current, reducedBeans, maxLineages, maxPerLineage, tracksLiveInstances);
                });

                #endregion
                #region Store results - this thread

                // Store the results
                task.ContinueWith(result =>
                {
                    var prev = _current;		// since it's volatile, only read once

                    // Store if newer
                    if (prev == null || result.Result.Item1 > prev.Item1)
                    {
                        _current = result.Result;
                    }
                }, TaskScheduler.FromCurrentSynchronizationContext());

                #endregion
            }

            // Exit Function
            return retVal;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// This method is only used for live tracking.  You can pass in tokens of ships that have died, and this will remove them
        /// from the list, as well as return the final score of any that were actually removed.
        /// </summary>
        public Tuple<long, WinningBean>[] StoreWinners(WinningBean[] adds, long[] removals)
        {
            if (!this.TracksLivingInstances)
            {
                throw new InvalidOperationException("This method can only be used when tracking live instances");
            }

            return StoreWinnersSprtDoIt(adds, removals);
        }
Ejemplo n.º 8
0
 public void StoreWinners(WinningBean[] beans)
 {
     StoreWinnersSprtDoIt(beans, null);
 }