Skip to content
This repository has been archived by the owner on Mar 7, 2024. It is now read-only.

Commit

Permalink
Feat: Add linechart
Browse files Browse the repository at this point in the history
  • Loading branch information
Lefeverw committed Oct 3, 2023
1 parent d416494 commit a679637
Show file tree
Hide file tree
Showing 18 changed files with 422 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
public class Application {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.IngestedMemberDto;
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.MemberDto;
import be.informatievlaanderen.vsds.demonstrator.member.rest.dtos.LineChartDto;
import org.locationtech.jts.geom.Geometry;

import java.time.LocalDateTime;
Expand All @@ -15,4 +16,6 @@ public interface MemberService {
MemberDto getMemberById(String memberId);

long getNumberOfMembers();

LineChartDto getLineChartDto();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import be.informatievlaanderen.vsds.demonstrator.member.application.exceptions.ResourceNotFoundException;
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.IngestedMemberDto;
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.MemberDto;
import be.informatievlaanderen.vsds.demonstrator.member.domain.member.valueobjects.HourCount;
import be.informatievlaanderen.vsds.demonstrator.member.domain.member.valueobjects.LineChart;
import be.informatievlaanderen.vsds.demonstrator.member.domain.member.entities.Member;
import be.informatievlaanderen.vsds.demonstrator.member.domain.member.repositories.MemberRepository;
import be.informatievlaanderen.vsds.demonstrator.member.rest.dtos.LineChartDto;
import be.informatievlaanderen.vsds.demonstrator.member.rest.websocket.MessageController;
import org.locationtech.jts.geom.Geometry;
import org.opengis.referencing.operation.TransformException;
Expand All @@ -19,6 +22,7 @@
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
public class MemberServiceImpl implements MemberService {
Expand Down Expand Up @@ -68,4 +72,15 @@ public MemberDto getMemberById(String memberId) {
public long getNumberOfMembers() {
return repository.getNumberOfMembers();
}

@Override
public LineChartDto getLineChartDto() {
long numberOfMembers = getNumberOfMembers();
LocalDateTime startDate = LocalDateTime.now().minusDays(7);
List<Member> membersAfterLocalDateTime = repository.findMembersAfterLocalDateTime(startDate);
Map<LocalDateTime, Integer> memberCountByHour = new HourCount(membersAfterLocalDateTime).getMemberCountByHour();
long numberOfMembersOutsideTimeFrame = numberOfMembers - membersAfterLocalDateTime.size();
LineChart lineChart = new LineChart(startDate,numberOfMembersOutsideTimeFrame,memberCountByHour);
return new LineChartDto(lineChart.getLabels(), lineChart.getValues());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public interface MemberRepository {
void saveMember(Member geometry);
List<Member> getMembersByGeometry(Geometry geometry, LocalDateTime startTime, LocalDateTime endTime);
Optional<Member> findByMemberId(String memberId);

long getNumberOfMembers();
List<Member> findMembersAfterLocalDateTime(LocalDateTime localDateTime);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package be.informatievlaanderen.vsds.demonstrator.member.domain.member.valueobjects;

import be.informatievlaanderen.vsds.demonstrator.member.domain.member.entities.Member;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class HourCount {
private final List<Member> memberList;

public HourCount(List<Member> memberList) {
this.memberList = memberList;
}

public Map<LocalDateTime, Integer> getMemberCountByHour(){
return memberList
.stream()
.map(Member::getTimestamp)
.map(localDateTime -> localDateTime.truncatedTo(ChronoUnit.HOURS))
.collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(e -> 1)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package be.informatievlaanderen.vsds.demonstrator.member.domain.member.valueobjects;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class LineChart {
private final Map<LocalDateTime, Integer> memberCountByHour;
private final long numberOfMembersOutsideFrame;
private final List<String> labels;
private final List<Integer> values;
private final LocalDateTime startDate;

public LineChart(LocalDateTime startDate, long numberOfMembersOutsideFrame, Map<LocalDateTime, Integer> memberCountByHour) {
this.startDate = startDate;
this.numberOfMembersOutsideFrame = numberOfMembersOutsideFrame;
this.memberCountByHour = memberCountByHour;
this.labels = new ArrayList<>();
this.values = new ArrayList<>();
}

private void calculatePointElements() {
LocalDateTime startTime = startDate.truncatedTo(ChronoUnit.HOURS);
long memberCount = numberOfMembersOutsideFrame;
while (startTime.isBefore(LocalDateTime.now())) {
memberCount = memberCount + memberCountByHour.getOrDefault(startTime, 0);
if (memberCount > 0) {
labels.add(startTime.toString());
values.add((int) memberCount);
}
startTime = startTime.plusHours(1);
}
}

public List<String> getLabels() {
if (labels.isEmpty())
calculatePointElements();
return labels;
}

//TODO multiple streams
public List<List<Integer>> getValues() {
if (values.isEmpty())
calculatePointElements();
return List.of(values);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ public interface MemberEntityJpaRepository extends JpaRepository<MemberEntity, S

@Query(value = "select l from member_entity l where intersects(l.geometry, :geometry) = true and l.timestamp >= :startTime and l.timestamp <= :endTime")
List<MemberEntity> getMemberGeometryEntitiesCoveredByGeometryInTimePeriod(@Param("geometry") Geometry geometry, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

List<MemberEntity> findByTimestampAfter(LocalDateTime localDateTime);

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,13 @@ public Optional<Member> findByMemberId(String memberId) {
public long getNumberOfMembers() {
return memberGeometryJpaRepo.count();
}

@Override
public List<Member> findMembersAfterLocalDateTime(LocalDateTime localDateTime) {
return memberGeometryJpaRepo
.findByTimestampAfter(localDateTime)
.stream()
.map(entity->new Member(entity.getMemberId(), entity.getGeometry(), entity.getTimestamp()))
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package be.informatievlaanderen.vsds.demonstrator.member.rest.dtos;

import java.util.List;

public class LineChartDto {
private final List<String> labels;
private final List<List<Integer>> values;

public LineChartDto(List<String> labels, List<List<Integer>> values) {
this.labels = labels;
this.values = values;
}

public List<String> getLabels() {
return labels;
}

public List<List<Integer>> getValues() {
return values;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package be.informatievlaanderen.vsds.demonstrator.member.rest.websocket;

import be.informatievlaanderen.vsds.demonstrator.member.application.services.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;

@Controller
public class LineChartController {
private final SimpMessagingTemplate template;
private final MemberService memberService;

@Autowired
public LineChartController(SimpMessagingTemplate template, MemberService memberService) {
this.template = template;
this.memberService = memberService;
}

@Scheduled(fixedDelay = 1000)
public void send() {
this.template.convertAndSend("/broker/linechart", memberService.getLineChartDto());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package be.informatievlaanderen.vsds.demonstrator.member.domain.member.valueobjects;

import be.informatievlaanderen.vsds.demonstrator.member.domain.member.entities.Member;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

class HourCountTest {

@Test
void test_HourCount(){
Member id1 = new Member("id1", null, LocalDateTime.of(2023, 1, 5, 1, 5));
Member id2 = new Member("id1", null, LocalDateTime.of(2023, 1, 5, 1, 5));
Member id3 = new Member("id1", null, LocalDateTime.of(2023, 1, 5, 1, 15));
Member id4 = new Member("id1", null, LocalDateTime.of(2023, 1, 5, 2, 5));
Member id5 = new Member("id1", null, LocalDateTime.of(2023, 1, 5, 2, 25));
Member id6 = new Member("id1", null, LocalDateTime.of(2023, 1, 6, 1, 5));
Member id7 = new Member("id1", null, LocalDateTime.of(2023, 1, 6, 1, 2));
Member id8 = new Member("id1", null, LocalDateTime.of(2023, 1, 6, 2, 5));
HourCount hourCount = new HourCount(List.of(id1, id2, id3, id4, id5, id6, id7, id8));

Map<LocalDateTime, Integer> memberCountByHour = hourCount.getMemberCountByHour();

assertEquals(4, hourCount.getMemberCountByHour().size());
assertEquals(3,memberCountByHour.get(LocalDateTime.of(2023,1,5,1,0)));
assertEquals(2,memberCountByHour.get(LocalDateTime.of(2023,1,5,2,0)));
assertEquals(2,memberCountByHour.get(LocalDateTime.of(2023,1,6,1,0)));
assertEquals(1,memberCountByHour.get(LocalDateTime.of(2023,1,6,2,0)));

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,28 @@ void test_Saving() {
}

@Test
void test_NumberCount(){
void test_NumberCount() {
repository.getNumberOfMembers();

verify(jpaRepository).count();
}

@Test
void test_findMembersAfterLocalDateTime() {
LocalDateTime now = LocalDateTime.now();
List<MemberEntity> memberEntities = List.of(new MemberEntity(ID, point, timestamp));
when(jpaRepository.findByTimestampAfter(now)).thenReturn(memberEntities);
List<Member> expectedMembers = memberEntities.stream()
.map(entity -> new Member(entity.getMemberId(), entity.getGeometry(), entity.getTimestamp()))
.toList();

List<Member> membersAfterLocalDateTime = repository.findMembersAfterLocalDateTime(now);

verify(jpaRepository).findByTimestampAfter(now);
assertEquals(1, membersAfterLocalDateTime.size());
assertEquals(expectedMembers, membersAfterLocalDateTime);
}

private List<MemberEntity> initMembers() throws ParseException {
final WKTReader reader = new WKTReader();
List<MemberEntity> members = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package be.informatievlaanderen.vsds.demonstrator.member.rest.websocket;

import be.informatievlaanderen.vsds.demonstrator.member.application.services.MemberService;
import be.informatievlaanderen.vsds.demonstrator.member.rest.dtos.LineChartDto;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.messaging.simp.SimpMessagingTemplate;

import java.util.List;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class LineChartControllerTest {

@Mock
private MemberService memberService;
@Mock
private SimpMessagingTemplate simpMessagingTemplate;
@InjectMocks
private LineChartController lineChartController;

@Test
void test_lineChartIsTransferredToWebsocket(){
LineChartDto lineChartDto = new LineChartDto(List.of(), List.of());
when(memberService.getLineChartDto()).thenReturn(lineChartDto);
lineChartController.send();

verify(memberService).getLineChartDto();
verify(simpMessagingTemplate).convertAndSend("/broker/linechart",lineChartDto);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MemberCounterControllerTest {
private MemberCounterController memberCounterController;

@Test
void test(){
void test_numberOfMembersIsTransferredToWebsocket(){
when(memberService.getNumberOfMembers()).thenReturn(76L);
memberCounterController.send();

Expand Down
Loading

0 comments on commit a679637

Please sign in to comment.