/// <inheritdoc cref="ITrainingSessionService.GetOrganismsAsync(GetOrganismsRequest)"/> public async Task <GetOrganismsResponse> GetOrganismsAsync(GetOrganismsRequest getOrganismsRequest) { string message = "Successfully fetched all requested organisms."; TrainingSession trainingSession; if (getOrganismsRequest.Amount < 1) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "Amount cannot be smaller than 1.")); } if ((trainingSession = await EntityRepository.FindSingleOrDefaultAsync(ts => ts.Id.Equals(getOrganismsRequest.TrainingSessionId))) == default) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "Training session does not exist.")); } if (!trainingSession.TrainingRoom.IsUserAuthorized(getOrganismsRequest.UserId) || trainingSession.UserId != getOrganismsRequest.UserId) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "User is not authorized.")); } if (trainingSession.EndedTimestamp != default) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "Training session has ended and can not be used any more.")); } TrainingRoomSettings trainingRoomSettings = trainingSession.TrainingRoom.TrainingRoomSettings; // if the list is empty then get new ones from the training room if (trainingSession.LeasedOrganisms.Count(o => !o.Organism.IsEvaluated) == 0) { if (trainingSession.TrainingRoom.Generation == 0) { for (int i = 0; i < trainingRoomSettings.OrganismCount; i++) { Organism organism = new Organism(trainingRoomSettings, trainingSession.TrainingRoom.GetInnovationNumber) { IsLeased = true }; trainingSession.TrainingRoom.AddOrganism(organism); trainingSession.LeasedOrganisms.Add(new LeasedOrganism(organism, trainingSession.Id)); } trainingSession.TrainingRoom.IncreaseNodeIdTo(trainingRoomSettings.InputCount + trainingRoomSettings.OutputCount); message = $"First generation; generated {trainingSession.TrainingRoom.TrainingRoomSettings.OrganismCount} organisms."; await _trainingSessionRepository.InsertFirstGenerationAsync(trainingSession); } else { trainingSession.LeasedOrganisms.AddRange(GetNewLeasedOrganisms(getOrganismsRequest.Amount)); message = "Start of new generation."; await _trainingSessionRepository.InsertLeasedOrganismsAsync(trainingSession); } } else if (trainingSession.LeasedOrganisms.Count(o => !o.Organism.IsEvaluated) < getOrganismsRequest.Amount) { int take = getOrganismsRequest.Amount - trainingSession.LeasedOrganisms.Count(o => !o.Organism.IsEvaluated); List <LeasedOrganism> newLeasedOrganisms = GetNewLeasedOrganisms(take); trainingSession.LeasedOrganisms.AddRange(newLeasedOrganisms); await _trainingSessionRepository.SaveChangesAsync(); } if (trainingSession.LeasedOrganisms.Count(o => !o.Organism.IsEvaluated) < getOrganismsRequest.Amount && getOrganismsRequest.Amount < trainingRoomSettings.OrganismCount) { message = "The requested amount of organisms are not all available. The training room is close to a new generation."; } List <OrganismDto> organismDtos = trainingSession.LeasedOrganisms .Where(lo => !lo.Organism.IsEvaluated) .Take(getOrganismsRequest.Amount) .Select(lo => { OrganismDto organismDto = Mapper.Map <OrganismDto>(lo.Organism); // Because the input and output nodes are set using a Many To Many relation the nodes are converted separately. organismDto.InputNodes = lo.Organism.Inputs.Select(input => Mapper.Map <NodeDto>(input.InputNode)).ToList(); organismDto.OutputNodes = lo.Organism.Outputs.Select(input => Mapper.Map <NodeDto>(input.OutputNode)).ToList(); return(organismDto); }).ToList(); return(new GetOrganismsResponse(getOrganismsRequest.Id, organismDtos, message, organismDtos.Any())); List <LeasedOrganism> GetNewLeasedOrganisms(int take) { return(trainingSession.TrainingRoom.Species .SelectMany(sp => sp.Organisms) .Where(lo => !lo.IsLeased) .Take(take).Select(o => { o.IsLeased = true; return new LeasedOrganism(o, trainingSession.Id); }).ToList()); } }
/// <inheritdoc cref="ITrainingRoomService.GetOrganismsAsync(GetOrganismsRequest)"/> public async Task <GetOrganismsResponse> GetOrganismsAsync(GetOrganismsRequest getOrganismsRequest) { string message = "Successfully fetched all requested organisms."; TrainingSession trainingSession; if (getOrganismsRequest.TrainingSessionId.Equals(Guid.Empty)) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "Training room id cannot be an empty guid.")); } if (getOrganismsRequest.Amount < 1) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "Amount cannot be smaller than 1.")); } if ((trainingSession = await _trainingSessionRepository.FindSingleOrDefaultAsync(ts => ts.Id.Equals(getOrganismsRequest.TrainingSessionId))) == default) { return(new GetOrganismsResponse(getOrganismsRequest.Id, new List <OrganismDto>(), "Training session does not exist.")); } // if the list is empty then get new ones from the training room if (trainingSession.LeasedOrganisms.Count(o => !o.Organism.Evaluated) == 0) { if (trainingSession.TrainingRoom.Generation == 0) { TrainingRoomSettings trainingRoomSettings = trainingSession.TrainingRoom.TrainingRoomSettings; for (int i = 0; i < trainingRoomSettings.OrganismCount; i++) { Organism organism = new Organism(trainingSession.TrainingRoom.Generation, trainingRoomSettings) { Leased = true }; trainingSession.TrainingRoom.AddOrganism(organism); trainingSession.LeasedOrganisms.Add(new LeasedOrganism(organism)); } trainingSession.TrainingRoom.IncreaseNodeIdTo(trainingRoomSettings.InputCount + trainingRoomSettings.OutputCount); message = $"First generation; generated {trainingSession.TrainingRoom.TrainingRoomSettings.OrganismCount} organisms."; } else { trainingSession.LeasedOrganisms.AddRange(GetNewLeasedOrganisms(getOrganismsRequest.Amount)); message = "Start of new generation."; } } else if (trainingSession.LeasedOrganisms.Count(o => !o.Organism.Evaluated) < getOrganismsRequest.Amount) { int take = getOrganismsRequest.Amount - trainingSession.LeasedOrganisms.Count(o => !o.Organism.Evaluated); List <LeasedOrganism> newLeasedOrganisms = GetNewLeasedOrganisms(take); trainingSession.LeasedOrganisms.AddRange(newLeasedOrganisms); } if (trainingSession.LeasedOrganisms.Count(o => !o.Organism.Evaluated) < getOrganismsRequest.Amount) { message = "The requested amount of organisms are not all available. The training room is probably close to a new generation or is waiting on other training sessions to complete."; } await _trainingSessionRepository.UpdateAsync(trainingSession); List <OrganismDto> organismDtos = trainingSession.LeasedOrganisms .Where(lo => !lo.Organism.Evaluated) .Take(getOrganismsRequest.Amount) .Select(lo => { OrganismDto organismDto = EntityToDtoConverter.Convert <OrganismDto, Organism>(lo.Organism); // Because the input and output nodes are set using a Many To Many relation the nodes are converted separately. organismDto.InputNodes = lo.Organism.Inputs.Select(input => EntityToDtoConverter.Convert <NodeDto, InputNode>(input.InputNode)).ToList(); organismDto.OutputNodes = lo.Organism.Outputs.Select(input => EntityToDtoConverter.Convert <NodeDto, OutputNode>(input.OutputNode)).ToList(); return(organismDto); }).ToList(); return(new GetOrganismsResponse(getOrganismsRequest.Id, organismDtos, message, organismDtos.Any())); List <LeasedOrganism> GetNewLeasedOrganisms(int take) { return(trainingSession.TrainingRoom.Species.SelectMany(sp => sp.Organisms).Where(lo => !lo.Leased) .Take(take).Select(o => { o.Leased = true; return new LeasedOrganism(o); }).ToList()); } }