public async Task <Tuple <List <Job>, DateTime> > Get(long userid)
        {
            var list           = new List <Job>();
            var cachedUntilUTC = DateTime.UtcNow;

            _logger.Debug("{method}", "JobsService::Get");
            try
            {
                var keys = await _userRepo.GetKeys(userid);

                var visited      = new HashSet <string>();
                var jobsTaskList = new List <Task <EveXmlResponse <IndustryJobs> > >();
                foreach (var k in keys)
                {
                    bool corpoKey = _eveApi.IsCorporationKey(k.KeyId, k.VCode);

                    if (corpoKey)
                    {
                        var corporation = _eveApi.GetCorporations(k.KeyId, k.VCode);
                        if (visited.Contains(corporation.CorporationName))
                        {
                            continue;
                        }
                        visited.Add(corporation.CorporationName);

                        jobsTaskList.Add(corporation.GetIndustryJobsAsync());
                    }
                    else
                    {
                        var characters = _eveApi.GetCharacters(k.KeyId, k.VCode);
                        foreach (var character in characters)
                        {
                            if (visited.Contains(character.CharacterName))
                            {
                                continue;
                            }
                            visited.Add(character.CharacterName);

                            var task = character.GetIndustryJobsAsync();
                            jobsTaskList.Add(task);
                            var z = (await task).Result;
                        }
                    }
                }

                foreach (var jobTask in jobsTaskList)
                {
                    var jobs = await jobTask;
                    cachedUntilUTC = cachedUntilUTC < jobs.CachedUntil ? cachedUntilUTC : jobs.CachedUntil;

                    var typeNameDict =
                        (await _typeNameDict.GetById(jobs.Result.Jobs.Select(x => (long)x.BlueprintTypeId)))
                        .ToDictionary(key => key.Item1, value => value.Item2);

                    foreach (var j in jobs.Result.Jobs)
                    {
                        var typeName    = typeNameDict[(long)j.BlueprintTypeId];
                        var runningTime = DateTime.UtcNow > j.StartDate
                            ? DateTime.UtcNow - j.StartDate
                            : new TimeSpan();
                        var totalTime  = j.EndDate > j.StartDate ? j.EndDate - j.StartDate : new TimeSpan();
                        int percentage = 0;
                        if (totalTime.TotalSeconds > 0)
                        {
                            percentage = Math.Min((int)(100.0 * runningTime.TotalSeconds / totalTime.TotalSeconds), 100);
                        }

                        var job = new Job()
                        {
                            JobCompleted           = j.CompletedDate != new DateTime(),
                            JobDescription         = string.Format("{0} {1} {2}", typeName, GetActivityAnnotation(j.ActivityId), j.Runs),
                            JobEnd                 = j.EndDate > DateTime.UtcNow ? j.EndDate : DateTime.UtcNow,
                            Owner                  = j.InstallerName,
                            PercentageOfCompletion = percentage,
                            Url             = string.Format("http://image.eveonline.com/Type/{0}_64.png", j.BlueprintTypeId),
                            IsManufacturing = j.ActivityId == 1
                        };
                        list.Add(job);
                    }
                }
            }
            catch (UserException)
            {
                throw;
            }
            catch (Exception e)
            {
                _logger.Error("{method} {@exception}", "JobService::Get", e);
                throw new UserException(strings.ErrorCallingEveApi, e);
            }

            return(new Tuple <List <Job>, DateTime>(list, cachedUntilUTC));
        }
        public async Task <Tuple <List <Pilot>, List <Corporation>, DateTime> > Get(long userid)
        {
            var list           = new List <Pilot>();
            var listCorpo      = new List <Corporation>();
            var cachedUntilUTC = DateTime.UtcNow.AddHours(2);

            _logger.Debug("{method}", "EvePilotDataService::Get");

            try
            {
                var keys = await _keyRepo.GetKeys(userid);

                foreach (var k in keys)
                {
                    if (_eveApi.IsCorporationKey(k.KeyId, k.VCode))
                    {
                        var ci = new Corporation();
                        ci.KeyInfoId = k.KeyInfoId;
                        var corpo = _eveApi.GetCorporations(k.KeyId, k.VCode);
                        ci.Name          = corpo.CorporationName;
                        ci.CorporationId = corpo.CorporationId;
                        listCorpo.Add(ci);
                        continue;
                    }

                    var characters = _eveApi.GetCharacters(k.KeyId, k.VCode);
                    foreach (var character in characters)
                    {
                        if (list.Count(x => x.Name == character.CharacterName) > 0)
                        {
                            continue;
                        }

                        var sheet = await character.GetCharacterSheetAsync();

                        var info = await character.GetCharacterInfoAsync();

                        var skillInTraining = await character.GetSkillTrainingAsync();

                        var skillQueue = await character.GetSkillQueueAsync();

                        var dt =
                            new DateTime[]
                        { sheet.CachedUntil, info.CachedUntil, skillInTraining.CachedUntil, skillQueue.CachedUntil }
                        .Min();
                        cachedUntilUTC = cachedUntilUTC < dt ? cachedUntilUTC : dt;

                        const long massProductionTypeId              = 3387;
                        const long advancedMassProductionTypeId      = 24625;
                        const long laboratoryOperationTypeId         = 3406;
                        const long advancedLaboratoryOperationTypeId = 24624;

                        var maxManufacturingJobs = 1 +
                                                   sheet.Result.Skills.Where(
                            x =>
                            x.TypeId == massProductionTypeId ||
                            x.TypeId == advancedMassProductionTypeId).Sum(x => x.Level);
                        var maxResearchJobs = 1 +
                                              sheet.Result.Skills.Where(
                            x =>
                            x.TypeId == laboratoryOperationTypeId ||
                            x.TypeId == advancedLaboratoryOperationTypeId).Sum(x => x.Level);


                        string typename = "";
                        if (skillInTraining.Result.TypeId > 0)
                        {
                            var tp = await _typeNameDict.GetById(new long[] { skillInTraining.Result.TypeId });

                            typename = tp[0].Item2;
                        }
                        var p = new Pilot()
                        {
                            Name = character.CharacterName,
                            CurrentTrainingEnd          = skillInTraining.Result.EndTime,
                            CurrentTrainingNameAndLevel = string.Format("{0} {1}", typename, skillInTraining.Result.ToLevel),
                            TrainingQueueEnd            = skillQueue.Result.Queue.Max(x => x.EndTime),
                            TrainingActive       = skillInTraining.Result.IsTraining,
                            EveId                = character.CharacterId,
                            MaxManufacturingJobs = maxManufacturingJobs,
                            MaxResearchJobs      = maxResearchJobs,
                            KeyInfoId            = k.KeyInfoId
                        };

                        // interestiong type ids
                        var ids =
                            sheet.Result.Skills.Select(x => (long)x.TypeId)
                            .Union(skillQueue.Result.Queue.Select(x => (long)x.TypeId))
                            .Distinct();

                        var typenames =
                            (await _typeNameDict.GetById(ids)).ToDictionary
                                (key => key.Item1, value => value.Item2);
                        p.Skills = sheet.Result.Skills.Select(x => new Skill()
                        {
                            PilotId   = p.PilotId,
                            SkillName = typenames[(long)x.TypeId],
                            Level     = x.Level
                        }).ToList();

                        p.SkillsInQueue = skillQueue.Result.Queue.OrderBy(z => z.StartTime).Select(x => new SkillInQueue()
                        {
                            PilotId   = p.PilotId,
                            SkillName = typenames[(long)x.TypeId],
                            Level     = x.Level,
                            Length    = x.EndTime - x.StartTime
                        }).ToList();
                        int order = 1;
                        foreach (var sq in p.SkillsInQueue)
                        {
                            sq.Order = order++;
                        }

                        list.Add(p);
                    }
                }
            }
            catch (UserException)
            {
                throw;
            }
            catch (Exception e)
            {
                _logger.Error("{method} {@exception}", "EvePilotDataService::Get", e);
                if (e.ToString().Contains("Illegal page") && e.ToString().Contains("access"))
                {
                    throw new UserException(strings.ErrorAccessMask, e);
                }
                throw new UserException(strings.ErrorCallingEveApi, e);
            }

            return(new Tuple <List <Pilot>, List <Corporation>, DateTime>(list, listCorpo, cachedUntilUTC));
        }