Skip to content

Commit

Permalink
main method refactored, covering more corner cases
Browse files Browse the repository at this point in the history
  • Loading branch information
erickmob committed Jul 12, 2020
1 parent eb57e56 commit 38d88e4
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 36 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,19 @@ mvn test
"inicioJanelaDeExecucao": "2019-11-10T09:00:00.483Z",
"jobList": [
{
"dataMaximaDeDuracao": "2019-11-10T12:00:00.483Z",
"dataMaximaDeConclusao": "2019-11-10T12:00:00.483Z",
"descricao": "Importação de arquivos de fundos",
"id": 1,
"tempoEstimado": 2
},
{
"dataMaximaDeDuracao": "2019-11-11T12:00:00.483Z",
"dataMaximaDeConclusao": "2019-11-11T12:00:00.483Z",
"descricao": "Importação de dados da Base Legada",
"id": 2,
"tempoEstimado": 4
},
{
"dataMaximaDeDuracao": "2019-11-11T08:00:00.483Z",
"dataMaximaDeConclusao": "2019-11-11T08:00:00.483Z",
"descricao": "Importação de dados de integração",
"id": 3,
"tempoEstimado": 6
Expand Down Expand Up @@ -196,12 +196,12 @@ Simply run on cli:

LocalHost:
```zsh
curl -X POST "http://localhost:8080/sequenceJobs" -H "accept: */*" -H "Content-Type: application/json" -d "{ \"fimJanelaDeExecucao\": \"2019-11-11T12:00:00.483Z\", \"inicioJanelaDeExecucao\": \"2019-11-10T09:00:00.483Z\", \"jobList\": [ { \"dataMaximaDeDuracao\": \"2019-11-10T12:00:00.483Z\", \"descricao\": \"Importação de arquivos de fundos\", \"id\": 1, \"tempoEstimado\": 2 }, { \"dataMaximaDeDuracao\": \"2019-11-11T12:00:00.483Z\", \"descricao\": \"Importação de dados da Base Legada\", \"id\": 2, \"tempoEstimado\": 4 }, { \"dataMaximaDeDuracao\": \"2019-11-11T08:00:00.483Z\", \"descricao\": \"Importação de dados de integração\", \"id\": 3, \"tempoEstimado\": 6 } ]}"
curl -X POST "http://localhost:8080/sequenceJobs" -H "accept: */*" -H "Content-Type: application/json" -d "{ \"fimJanelaDeExecucao\": \"2019-11-11T12:00:00.483Z\", \"inicioJanelaDeExecucao\": \"2019-11-10T09:00:00.483Z\", \"jobList\": [ { \"dataMaximaDeConclusao\": \"2019-11-10T12:00:00.483Z\", \"descricao\": \"Importação de arquivos de fundos\", \"id\": 1, \"tempoEstimado\": 2 }, { \"dataMaximaDeConclusao\": \"2019-11-11T12:00:00.483Z\", \"descricao\": \"Importação de dados da Base Legada\", \"id\": 2, \"tempoEstimado\": 4 }, { \"dataMaximaDeConclusao\": \"2019-11-11T08:00:00.483Z\", \"descricao\": \"Importação de dados de integração\", \"id\": 3, \"tempoEstimado\": 6 } ]}"
```

Or Heroku:
```zsh
curl -X POST "https://scheduling-job-777.herokuapp.com/sequenceJobs" -H "accept: */*" -H "Content-Type: application/json" -d "{ \"fimJanelaDeExecucao\": \"2019-11-11T12:00:00.483Z\", \"inicioJanelaDeExecucao\": \"2019-11-10T09:00:00.483Z\", \"jobList\": [ { \"dataMaximaDeDuracao\": \"2019-11-10T12:00:00.483Z\", \"descricao\": \"Importação de arquivos de fundos\", \"id\": 1, \"tempoEstimado\": 2 }, { \"dataMaximaDeDuracao\": \"2019-11-11T12:00:00.483Z\", \"descricao\": \"Importação de dados da Base Legada\", \"id\": 2, \"tempoEstimado\": 4 }, { \"dataMaximaDeDuracao\": \"2019-11-11T08:00:00.483Z\", \"descricao\": \"Importação de dados de integração\", \"id\": 3, \"tempoEstimado\": 6 } ]}"
curl -X POST "https://scheduling-job-777.herokuapp.com/sequenceJobs" -H "accept: */*" -H "Content-Type: application/json" -d "{ \"fimJanelaDeExecucao\": \"2019-11-11T12:00:00.483Z\", \"inicioJanelaDeExecucao\": \"2019-11-10T09:00:00.483Z\", \"jobList\": [ { \"dataMaximaDeConclusao\": \"2019-11-10T12:00:00.483Z\", \"descricao\": \"Importação de arquivos de fundos\", \"id\": 1, \"tempoEstimado\": 2 }, { \"dataMaximaDeConclusao\": \"2019-11-11T12:00:00.483Z\", \"descricao\": \"Importação de dados da Base Legada\", \"id\": 2, \"tempoEstimado\": 4 }, { \"dataMaximaDeConclusao\": \"2019-11-11T08:00:00.483Z\", \"descricao\": \"Importação de dados de integração\", \"id\": 3, \"tempoEstimado\": 6 } ]}"
```

And see the output response:
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/erickmob/schedulingjob/Dto/JobDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
public class JobDTO {
private long id;
private String descricao;
private LocalDateTime dataMaximaDeDuracao;
private LocalDateTime dataMaximaDeConclusao;
private long tempoEstimado;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ public class JobController {
public List<ArrayList> sequenceJobs(@RequestBody JobsDTO jobsDTO) {
log.info("Received request with body:"+jobsDTO.toString());
List<ArrayList> result;
List<Job> jobsList = new ArrayList<>();
try{
List<Job> jobsList = jobService.createFromJobListDto(jobsDTO.getJobList());
if(!jobsDTO.getJobList().isEmpty()){
jobsList = jobService.createFromJobListDto(jobsDTO.getJobList());
}
result = schedulingService.sortJobsForScheduling(jobsList, jobsDTO.getInicioJanelaDeExecucao(), jobsDTO.getFimJanelaDeExecucao());
return result;
}catch (TimeWindowException e){
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/erickmob/schedulingjob/model/Job.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
public class Job {
private long id;
private String descricao;
private LocalDateTime dataMaximaDeDuracao;
private LocalDateTime dataMaximaDeConclusao;
private Duration tempoEstimado;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public List<Job> createFromJobListDto(List<JobDTO> jobDTOList){
new Job(
jobDTO.getId(),
jobDTO.getDescricao(),
jobDTO.getDataMaximaDeDuracao(),
jobDTO.getDataMaximaDeConclusao(),
Duration.ofHours(jobDTO.getTempoEstimado())
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,47 +67,70 @@ List<Job> sortListByDateAndFilter(List<Job> jobsList, LocalDateTime inicioJanel
return jobsList.stream()
.filter(job -> job.getTempoEstimado().toHours() < maxDurationHour.toHours())
.filter(job -> conlusionInsideTimeWindow(job, inicioJanelaDeExecucao, fimJanelaDeExecucao))
.filter(job -> maxEstimatedDateInsideTimeWindow(job, inicioJanelaDeExecucao))
.sorted(
Comparator.comparing(Job::getDataMaximaDeDuracao)
Comparator.comparing(Job::getDataMaximaDeConclusao)
)
.collect(Collectors.toList());

}

boolean conlusionInsideTimeWindow(Job job, LocalDateTime inicioJanelaDeExecucao, LocalDateTime fimJanelaDeExecucao) {
LocalDateTime estimateConcludion = executionTimeWindowStart.plusHours(job.getTempoEstimado().toHours());
Duration duration = Duration.between(estimateConcludion, executionTimeWindowEnd);
LocalDateTime estimateConcludion = inicioJanelaDeExecucao.plusHours(job.getTempoEstimado().toHours());
Duration duration = Duration.between(estimateConcludion, fimJanelaDeExecucao);
return duration.toHours() > 0;
}

boolean maxEstimatedDateInsideTimeWindow(Job job, LocalDateTime inicioJanelaDeExecucao) {
return job.getDataMaximaDeConclusao().isAfter(inicioJanelaDeExecucao);
}

private List<ArrayList> createJobExecuteSequence(List<Job> jobsList, LocalDateTime inicioJanelaDeExecucao, LocalDateTime fimJanelaDeExecucao) {
ArrayList<ArrayList> expectedList = new ArrayList<>();
ArrayList<Long> longArray = new ArrayList<>();
long totalHoursForArray = 0;

ArrayList<ArrayList> resultList = new ArrayList<>();
ArrayList<Long> eightHoursArray = new ArrayList<>();

long countTotalHoursForArray = 0;

LocalDateTime currentDateTime = inicioJanelaDeExecucao;
LocalDateTime estimateJobConclusionDate;

for(Job job : jobsList){
if(jobFitsInsideArray(totalHoursForArray, job)){
longArray.add(job.getId());
totalHoursForArray += job.getTempoEstimado().toHours();

estimateJobConclusionDate = currentDateTime.plusHours(job.getTempoEstimado().toHours());

if(estimateJobConclusionDate.isAfter(fimJanelaDeExecucao)){
break;
}
if(estimateJobConclusionDate.isAfter(job.getDataMaximaDeConclusao())){
break;
}

if(jobFitsInsideEightHoursArray(countTotalHoursForArray, job)){
eightHoursArray.add(job.getId());
countTotalHoursForArray += job.getTempoEstimado().toHours();
}else{
addArrayToExpectedList(expectedList, longArray);
longArray = new ArrayList<>();
longArray.add(job.getId());
addEightHourArrayToResultList(resultList, eightHoursArray);
eightHoursArray = new ArrayList<>();
eightHoursArray.add(job.getId());
countTotalHoursForArray = job.getTempoEstimado().toHours();
}
currentDateTime = currentDateTime.plusHours(job.getTempoEstimado().toHours());

}

addArrayToExpectedList(expectedList, longArray);
addEightHourArrayToResultList(resultList, eightHoursArray);

return expectedList;
return resultList;
}

private void addArrayToExpectedList(ArrayList<ArrayList> expectedList, ArrayList<Long> longArray) {
private void addEightHourArrayToResultList(ArrayList<ArrayList> expectedList, ArrayList<Long> longArray) {
if (longArray.size() > 0) {
expectedList.add(longArray);
}
}

private boolean jobFitsInsideArray(long totalHoursForArray, Job job) {
private boolean jobFitsInsideEightHoursArray(long totalHoursForArray, Job job) {
return (totalHoursForArray + job.getTempoEstimado().toHours()) <= maxDurationHour.toHours();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ void whenJobListSameDateThenSort() throws Exception {
//when
List<Job> result = schedulingService.sortListByDateAndFilter(jobsList, executionTimeWindowStart, executionTimeWindowEnd);
assertEquals(1,result.get(0).getId());
assertEquals(3,result.get(1).getId());
assertEquals(4,result.get(2).getId());
assertEquals(5,result.get(3).getId());
assertEquals(4,result.get(1).getId());
assertEquals(5,result.get(2).getId());
assertEquals(3,result.get(3).getId());
assertEquals(2,result.get(4).getId());
}

Expand Down Expand Up @@ -200,26 +200,114 @@ void givenTestCaseFromDocTest() throws TimeWindowException {
}

@Test
void givenListWithNoValidJob() throws TimeWindowException {
void givenTestCaseFromDocTestOnShortWindown() throws TimeWindowException {
//given
jobsList = getJobsArrayMocked();
LocalDateTime jobDateTime = LocalDateTime.of(2019,
Month.NOVEMBER,
10,
12,
20,
0,
0);

jobsList = new ArrayList<Job>(Arrays.asList(
new Job(4,"Importação de arquivos de fundos 2", jobDateTime, Duration.ofHours(27))
));
//when
List<ArrayList> received = schedulingService.sortJobsForScheduling(jobsList, null, jobDateTime);

//then
assertEquals("[[1, 3]]", received.toString());
}


@Test
void givenJobWithEstimatedBeforeStartWindowTime() throws TimeWindowException {
//given
jobsList = getJobsArrayMocked();

LocalDateTime jobDateTime = LocalDateTime.of(2019,
Month.JANUARY,
11,
8,
0,
0);

jobsList.add(
new Job(
4,
"job com data max conclusao antes do inicio da janela",
jobDateTime,
Duration.ofHours(6)
)
);

//when
List<ArrayList> received = schedulingService.sortJobsForScheduling(jobsList, null, null);

//then
assertEquals("[]", received.toString());
assertEquals("[[1, 3], [2]]", received.toString());
}

@Test
void givenMultipleJobsWithSameMaxEstimated() throws TimeWindowException {
//given
LocalDateTime dataMaximaDeConclusao = LocalDateTime.of(
2019,
Month.NOVEMBER,
10,
19,
0,
0);
jobsList = new ArrayList<>();
jobsList.add(
new Job(
1,
"asd",
dataMaximaDeConclusao,
Duration.ofHours(6)
)
);
jobsList.add(
new Job(
2,
"asd",
dataMaximaDeConclusao,
Duration.ofHours(6)
)
);

jobsList.add(
new Job(
3,
"asd",
dataMaximaDeConclusao,
Duration.ofHours(6)
)
);

jobsList.add(
new Job(
4,
"asd",
dataMaximaDeConclusao,
Duration.ofHours(6)
)
);

jobsList.add(
new Job(
5,
"asd",
dataMaximaDeConclusao,
Duration.ofHours(6)
)
);


//when
List<ArrayList> received = schedulingService.sortJobsForScheduling(jobsList, null, null);

//then
assertEquals("[[1]]", received.toString());
}

private List<Job> getJobsArrayMocked() {
jobsList = new ArrayList<Job>(Arrays.asList(
Expand Down Expand Up @@ -254,8 +342,8 @@ private Job getJob2Mocked() {
private Job getJob3Mocked() {
LocalDateTime jobDateTime = LocalDateTime.of(2019,
Month.NOVEMBER,
10,
12,
11,
8,
0,
0);
return new Job(3,"Importação de dados de integração", jobDateTime, Duration.ofHours(6));
Expand Down

0 comments on commit 38d88e4

Please sign in to comment.