private Dictionary <ulong, ulong> FillPreviousTradesPairs(ApplicationData thisMonth, ApplicationData prevMonth)
        {
            Dictionary <ulong, ulong> prevMonthList = new Dictionary <ulong, ulong>();

            foreach (UserData user in prevMonth.GetStorage())
            {
                UserData nextUser;
                if (thisMonth.Get(user.UserId) != null && prevMonth.Next(user.UserId, out nextUser))
                {
                    prevMonthList.Add(user.UserId, nextUser.UserId);
                }
            }
            return(prevMonthList);
        }
        private bool Initialize(ApplicationData currentTrade, ApplicationHistory tradeHistory)
        {
            _data.Clear();
            _computedChain.Clear();

            Dictionary <ulong, ulong> prevMonthList = null;

            if (tradeHistory.Count() > 0)
            {
                prevMonthList = FillPreviousTradesPairs(currentTrade, tradeHistory.GetTrade(0));
            }

            Dictionary <ulong, ulong> prevPrevMonthList = null;

            if (tradeHistory.Count() > 1)
            {
                prevPrevMonthList = FillPreviousTradesPairs(currentTrade, tradeHistory.GetTrade(1));
            }

            Dictionary <UserData, List <ulong> > tmpData = new Dictionary <UserData, List <ulong> >();

            foreach (UserData user1 in currentTrade.GetStorage())
            {
                List <ulong> candidate = new List <ulong>();

                ulong prevPartner = 0;
                if (prevMonthList != null)
                {
                    prevMonthList.TryGetValue(user1.UserId, out prevPartner);
                }

                ulong prevPrevPartner = 0;
                if (prevPrevMonthList != null)
                {
                    prevPrevMonthList.TryGetValue(user1.UserId, out prevPrevPartner);
                }

                bool bPushBack = false;
                foreach (UserData user2 in currentTrade.GetStorage())
                {
                    if (user2.UserId == user1.UserId || user2.UserId == prevPartner || user2.UserId == user1.PreferenceId)
                    {
                        continue;
                    }

                    if (user2.UserId == prevPrevPartner)
                    {
                        bPushBack = true;
                    }
                    else
                    {
                        candidate.Add(user2.UserId);
                    }
                }

                candidate = candidate.OrderBy(x => Guid.NewGuid()).ToList();

                if (bPushBack)
                {
                    candidate.Add(prevPrevPartner);
                }

                if (user1.PreferenceId != 0)
                {
                    candidate = candidate.Prepend(user1.PreferenceId).ToList();
                }

                if (candidate.Count == 0)
                {
                    return(false);
                }

                tmpData.Add(user1, candidate);
            }

            if (tmpData.Count == 0)
            {
                return(false);
            }

            // order by number of candidates first, if someone had someone else as a partner las trade, it is removed from candidates this trade
            foreach (var byCount in tmpData.GroupBy(x => x.Value.Count))
            {
                foreach (var byPreference in byCount.GroupBy(x => x.Key.PreferenceId != 0))
                {
                    foreach (var dat in byPreference.OrderBy(x => Guid.NewGuid()))
                    {
                        _data.Add(dat.Key.UserId, dat.Value);
                    }
                }
            }

            //_data = _data.OrderBy(x => x.Value.Count).ToDictionary(x => x.Key, x => x.Value);
            return(true);
        }