Beispiel #1
0
        /// <summary>
        /// Создание экземпляра класса
        /// </summary>
        /// <param name="account">Аккаунт</param>
        /// <param name="repository">Репозиторий</param>
        public AddressParser(RoyaltyRepository.Models.Account account, RoyaltyRepository.Repository repository)
        {
            if (repository == null)
                throw new ArgumentNullException("repository");
            if (account == null)
                throw new ArgumentNullException("account");

            Account = account;
            Repository = repository;
        }
Beispiel #2
0
        public static IEnumerable<string> FileGetLines(this RoyaltyRepository.Repository repository, IFileStorage storage, RoyaltyRepository.Models.File repositoryFile)
        {
            if (repository == null)
                throw new ArgumentNullException(nameof(repository));
            if (repositoryFile == null)
                throw new ArgumentNullException(nameof(repositoryFile));
            if (storage == null)
                throw new ArgumentNullException(nameof(storage));

            var res = new List<string>();
            using (var fileStream = storage.FileGet(repositoryFile.FileUID))
            using (var sr = new System.IO.StreamReader(fileStream, repositoryFile.Encoding))
            {
                var line = string.Empty;
                while ((line = sr.ReadLine()) != null)
                    res.Add(line);
            }
            return res;
        }
 private void UpdateFileInfoes(RoyaltyRepository.Repository rep, RoyaltyRepository.Models.ImportQueueRecord destination, IEnumerable<ImportQueueRecordFileInfo> fileInfoes)
 {
     throw new NotImplementedException();
 }
 private void LoadFiles(RoyaltyRepository.Repository rep, RoyaltyRepository.Models.ImportQueueRecordFileInfo destination, IEnumerable<ImportQueueRecordFileInfoFile> files)
 {
     foreach (var item in files)
     {
         var dbItem = rep.New<RoyaltyRepository.Models.ImportQueueRecordFileInfoFile>((i) => {
             i.FileUID = item.File != null ? item.File.FileUID : item.FileUID;
             i.File = rep.Get<RoyaltyRepository.Models.File>(f => f.FileUID == i.FileUID).FirstOrDefault();
             i.ImportQueueRecordFileInfo = destination;
             i.Type = RoyaltyRepository.Models.ImportQueueRecordFileInfoFileType.Import;
         });
         rep.Add(dbItem, saveAfterInsert: false);
     }
 }
 private void LoadFileInfoes(RoyaltyRepository.Repository rep, RoyaltyRepository.Models.ImportQueueRecord destination, IEnumerable<ImportQueueRecordFileInfo> fileInfoes)
 {
     var stateDafault = rep.ImportQueueRecordStateGetDefault();
     foreach(var item in fileInfoes)
     {
         var dbItem = rep.New<RoyaltyRepository.Models.ImportQueueRecordFileInfo>((i) => {
             i.ImportQueueRecordFileInfoUID = Guid.NewGuid();
             i.ForAnalize = item.ForAnalize;
             i.ImportQueueRecord = destination;
             i.SourceFilePath = item.SourceFilePath;
             i.ImportQueueRecordState = stateDafault;
         });
         rep.Add(dbItem, saveAfterInsert: false);
         LoadFiles(rep, dbItem, item.Files);
     }
 }
Beispiel #6
0
 /// <summary>
 /// Получение списка улиц в соответствии с адресами
 /// </summary>
 /// <param name="incomingAddresses">Адреса, для которых нужно определить улицы</param>
 /// <param name="city">Город</param>
 /// <param name="reportProgress">Action для отслеживания процесса выполнения</param>
 /// <returns>Список соответствия входящему адресу найденной улицы</returns>
 public IDictionary<Address, RoyaltyRepository.Models.Street> GetStreets(
     IEnumerable<Address> incomingAddresses,
     RoyaltyRepository.Models.City city,
     Action<decimal> reportProgress = null,
     Action<string> verboseLog = null)
 {
     return GetStreets(incomingAddresses, city, true, reportProgress, verboseLog);
 }
Beispiel #7
0
        /// <summary>
        /// Получение списка улиц в соответствии с адресами
        /// </summary>
        /// <param name="incomingAddresses">Адреса, для которых нужно определить улицы</param>
        /// <param name="city">Город</param>
        /// <param name="doNotAddAnyDataToDictionary">Флаг для отмены добавления данных в словарь</param>
        /// <param name="reportProgress">Action для отслеживания процесса выполнения</param>
        /// <returns>Список соответствия входящему адресу найденной улицы</returns>
        internal IDictionary<Address, RoyaltyRepository.Models.Street> GetStreets(
            IEnumerable<Address> incomingAddresses,
            RoyaltyRepository.Models.City city,
            bool doNotAddAnyDataToDictionary = false,
            Action<decimal> reportProgress = null,
            Action<string> verboseLog = null)
        {
            var pp = new Helpers.PercentageProgress();
            var ppLoad = pp.GetChild(weight: 0.5m);
            var ppSubitem = pp.GetChild(weight: 9m);
            var ppEnd = pp.GetChild(weight: 0.5m);
            pp.Change += (s, e) => { if (reportProgress != null) reportProgress(e.Value); };
            verboseLog = verboseLog ?? new Action<string>(s => { });

            using (var logSession = Helpers.Log.Session($"{GetType().Name}.{nameof(GetStreets)}()"))
                try
                {
                    logSession.Output = new Action<IEnumerable<string>>( (strs) => strs.ToList().ForEach(s => verboseLog(s)) );

                    var findStreet = incomingAddresses
                        .Distinct()
                        .OrderByDescending(a => a.Area)
                        .ThenByDescending(a => a.Street)
                        .ThenByDescending(a => a.House.ToString())
                        .LeftOuterJoin(Account.Dictionary.Records, //.Where(r => r.Street != null && r.Street.Area != null),
                            s => new { StreetName = s.Street, AreaName = s.Area },
                            d => new { StreetName = d.Street.Name, AreaName = d.Street.Area.Name },
                            (s, d) => new
                            {
                                IncomingAddress = s,
                                Street = (d != null ? d.ChangeStreetTo ?? d.Street : null),
                                ConditionsScore = GetConditionsScore(s.House.Number, d == null ? null : d.Conditions, doNotAddAnyDataToDictionary),
                            })
                        .ToArray();

                    var count = findStreet.Length;
                    int current = 0;
                    ppLoad.Value = 90;

                    var res = findStreet
                        .Select(i =>
                        {
                            var subRes = new
                            {
                                i.IncomingAddress,
                                Street = i.Street
                                    ?? GetStreetByDictionary(i.IncomingAddress, city, doNotAddAnyDataToDictionary, (s) => logSession.Add(s))
                                    ?? GetNewStreet(i.IncomingAddress, city, doNotAddAnyDataToDictionary, (s) => logSession.Add(s))
                            };
                            current++;
                            ppSubitem.Value = (decimal)current / (decimal)count * 100m;
                            return subRes;
                        }
                        )
                        .GroupBy(i => i.IncomingAddress)
                        .Select(g => new { IncomingAddress = g.Key, Items = g })
                        //Исключаем случаи, когда в словаре более одной записи на входящий адрес (что-то пошло не так, и мы генерируем ошибку)
                        .Select(g => 
                        {
                            if (g.Items.Count() > 1)
                            {
                                var ex = new Exception($"For incoming address '{g.IncomingAddress.ToString()}' found more then 1 street. See data for details");
                                int index = 0;
                                foreach (var i in g.Items.Select(n => n.Street))
                                    ex.Data.Add(index++, i.ToString());

                                throw ex;
                            }

                            return new
                            {
                                g.IncomingAddress,
                                g.Items.FirstOrDefault().Street
                            };
                        })
                        .ToArray();

                    ppLoad.Value = 100;

                    logSession.Add($"Array constructed with {res.Length} elements for city '{city}'. Try to create dictionary.");
                    return res.ToDictionary(i => i.IncomingAddress, i => i.Street);
                }
                catch(Exception ex)
                {
                    logSession.Add(ex);
                    logSession.Enabled = true;
                    throw;
                }
                finally
                {
                    ppEnd.Value = 100;
                }
        }
Beispiel #8
0
        /// <summary>
        /// Создает новую улицу и добавляет в словарь, если это необходимо
        /// </summary>
        /// <param name="address">Адрес</param>
        /// <param name="city">Город</param>
        /// <param name="doNotAddAnyDataToDictionary">Флаг для отмены добавления данных в словарь</param>
        /// <param name="verboseLog">Action по логированию метода</param>
        /// <returns>Улицу</returns>
        internal RoyaltyRepository.Models.Street GetNewStreet(Address address, RoyaltyRepository.Models.City city, bool doNotAddAnyDataToDictionary, Action<string> verboseLog = null)
        {
            if (address == null)
                throw new ArgumentNullException(nameof(address));
            if (city == null)
                throw new ArgumentNullException(nameof(city));

            var log = new Action<string>((str) => { if (verboseLog != null) verboseLog($"{GetType().Name}.{nameof(GetNewStreet)}() {str}"); });
            bool isNewArea = false;

            try
                {
                    log($"Incoming parameters: address is '{address}' and city is '{city}'");
                    RoyaltyRepository.Models.Area a = null;
                    if (string.IsNullOrWhiteSpace(address.Area))
                    {
                        log($"Area is unsetted. Use default aread for city: '{city.UndefinedArea}'");
                        a = city.UndefinedArea;
                    } else
                    {
                        log($"Try get area with name '{address.Area}' from database");
                        a = Repository.AreaGet(address.Area, city);
                        if (a == null)
                        {
                            log($"Area not found. Create new");
                            a = Repository.AreaNew(address.Area, city: city);
                            log($"New area for addres is {a}");
                            isNewArea = true;
                        } else
                            log($"Area found: {a}");
                    }

                    RoyaltyRepository.Models.Street s = null;
                    if (!isNewArea)
                    {
                        log($"Try to get street from database");
                        s = Repository.StreetGet(address.Street, a);
                        if (s != null)
                            log($"Street found in database: {s}"); else
                            log($"Street '{address.Street}' with area '{a}' not found in database");
                    }
                    if (s == null)
                    {
                        s = a != city.UndefinedArea ? Repository.StreetGet(address.Street, city.UndefinedArea) : null;
                        if (s != null)
                        {
                            log($"Street found in undefined area in database: {s}. Change area for this street to '{a}'");
                            s.Area = a;
                        }
                        else
                        {
                            s = Repository.StreetNew(address.Street, a);
                            log($"New street created: {s}");
                        }
                    }
                    else
                        log($"Street found in database: {s}");

                    if (Account.Dictionary.AllowAddToDictionaryAutomatically && !doNotAddAnyDataToDictionary)
                    lock (Account.Dictionary)
                        AddNewOrUpdateDictionaryRecord(address, s, (str) => log(str));

                    return s;
                }
                catch(Exception)
                {
                    throw;
                }
        }
Beispiel #9
0
        /// <summary>
        /// Добавляет новую запись или обновляет существующую запись в словаре для адреса
        /// </summary>
        /// <param name="address">Адрес</param>
        /// <param name="street">Улица</param>
        /// <param name="verboseLog">Action по логированию метода</param>
        internal void AddNewOrUpdateDictionaryRecord(Address address, RoyaltyRepository.Models.Street street, Action<string> verboseLog = null)
        {
            if (address == null)
                throw new ArgumentNullException(nameof(address));

            var log = new Action<string>((str) => { if (verboseLog != null) verboseLog($"{GetType().Name}.{nameof(AddNewOrUpdateDictionaryRecord)}() {str}"); });

            log("Try get record to dictionary");
            var dictionaryRecords = Account.Dictionary.Records.Where(ad => ad.Street == street);
            if (!dictionaryRecords.Any())
            {
                log("Dictionary record not found. Create new and add it");
                var adr = Repository.AccountDictionaryRecordNew(Account.Dictionary, street: street);
                if (address.House.Number.HasValue)
                {
                    var cond = Repository.AccountDictionaryRecordConditionNew(adr, address.House.Number, address.House.Number);
                    log($"Add condition for dictionary record {cond.ToString()}");
                }
                log($"Add dictionary record: {adr.ToString()}");
            }
            else
            {
                ConcatDictionaryRecordConditions(address, dictionaryRecords, (str) => log(str));
            }
        }
Beispiel #10
0
 /// <summary>
 /// Получает улицу по адресу в соответствии со словарем
 /// </summary>
 /// <param name="address">Адрес для поиска</param>
 /// <param name="city">Город</param>
 /// <param name="verboseLog">Action по логированию поиска</param>
 /// <returns>Улица из БД. Если NULL, значит улица в соответствии со словарем не найдена</returns>
 public RoyaltyRepository.Models.Street GetStreetByDictionary(Address address, RoyaltyRepository.Models.City city, Action<string> verboseLog = null)
 {
     return GetStreetByDictionary(address, city, true, verboseLog);
 }
Beispiel #11
0
        /// <summary>
        /// Получает улицу по адресу в соответствии со словарем
        /// </summary>
        /// <param name="address">Адрес для поиска</param>
        /// <param name="city">Город</param>
        /// <param name="doNotAddAnyDataToDictionary">Флаг для отмены добавления данных в словарь</param>
        /// <param name="log">Action по логированию поиска</param>
        /// <returns>Улица из БД. Если NULL, значит улица в соответствии со словарем не найдена</returns>
        internal RoyaltyRepository.Models.Street GetStreetByDictionary(Address address, RoyaltyRepository.Models.City city, bool doNotAddAnyDataToDictionary, Action<string> verboseLog = null)
        {
            if (address == null)
                throw new ArgumentNullException(nameof(address));
            if (city == null)
                throw new ArgumentNullException(nameof(city));

            var log = new Action<string>((str) => { if (verboseLog != null) verboseLog($"{GetType().Name}.{nameof(GetStreetByDictionary)}() {str}"); });

            //lock (Account.Dictionary)
            try
            { 
                log($"Get all account records");

                ICollection<RoyaltyRepository.Models.AccountDictionaryRecord> recs = null;
                lock (Account.Dictionary)
                    recs = Account.Dictionary.Records.ToArray();

                log($"Get all streets in city '{city}'");

                var dictionary = city.Areas
                    //.AsParallel()
                    .SelectMany(a => a.Streets.Select(s => new
                    {
                        Area = a,
                        Street = s
                    }))
                    .LeftOuterJoin(recs, s => s.Street, r => r.Street, (s, r) => new
                    {
                        Street = s.Street,
                        Area = s.Area,
                        ChangeStreetTo = r?.ChangeStreetTo,
                        Conditions = r?.Conditions,
                        DictionaryRecord = r,
                    })
                    .ToArray();

                log($"Try to add street for sort dictionary");

                var dS = dictionary.AsParallel().Where(i => i.Street.Name.ToUpper() == address.Street.ToUpper()).ToArray();
                if (dS.Any())
                {
                    dictionary = dS;
                    log($"Street added for sort");
                }

                if (!string.IsNullOrWhiteSpace(address.Area))
                {
                    log($"Try to add area for sort dictionary");
                    var dA = dictionary.AsParallel().Where(i => i.Area.Name.ToUpper() == address.Area.ToUpper()).ToArray();
                    if (dA.Any())
                    {
                        dictionary = dA;
                        log($"Area added for sort");
                    }
                }

                log($"Get scores for dictionary and incoming address '{address}'");
                var subRes = dictionary
                    .AsParallel()
                    .Select(i => new
                    {
                        Street = i.ChangeStreetTo ?? i.Street,
                        i.Street.Area,
                        ConditionsScore = GetConditionsScore(address.House.Number, i.Conditions, doNotAddAnyDataToDictionary),
                        StreetScore = (decimal)new WordsMatching.MatchsMaker(address.Street, i.Street.Name).Score,
                        AreaScore = string.IsNullOrWhiteSpace(address.Area)
                            ? Account.Dictionary.SimilarityForTrust
                            : (decimal)new WordsMatching.MatchsMaker(address.Area, i.Street.Area.Name).Score,
                        i.DictionaryRecord,
                    });

                log($"Get nearest data");
                var res = subRes
                    .Where(i => i.StreetScore + i.AreaScore >= Account.Dictionary.SimilarityForTrust * 2 && i.ConditionsScore >= Account.Dictionary.ConditionsScoreForTrust)
                    .OrderByDescending(i => i.StreetScore + i.AreaScore + i.ConditionsScore / 2m)
                    .ThenByDescending(i => i.DictionaryRecord != null ? 1 : 0)
                    .ThenByDescending(i => i.Area.Streets.Count)
                    .FirstOrDefault();

                if (res == null)
                    log($"Street not found for address '{address}'");
                else
                {
                    log($"Founded street {(res.DictionaryRecord != null ? "in dictionary" : string.Empty)}for address '{address}': '{res}'");
                    if (Account.Dictionary.AllowAddToDictionaryAutomatically && !doNotAddAnyDataToDictionary)
                    {
                        if (res.DictionaryRecord == null)
                        {
                            lock (Account.Dictionary)
                               AddNewOrUpdateDictionaryRecord(address, res.Street, (str) => log(str));
                        }
                        else
                            ConcatDictionaryRecordConditions(address, new RoyaltyRepository.Models.AccountDictionaryRecord[] { res.DictionaryRecord }, (str) => log(str));
                    }
                }
                return res?.Street;
            }
            catch(Exception ex)
            {
                log(ex.GetExceptionText());
                throw;
            }
        }