diff --git a/pom.xml b/pom.xml index bb6d9b8a..f30e7d03 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,11 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + diff --git a/src/main/java/hse/java/lectures/lesson7/dau/DauServiceImpl.java b/src/main/java/hse/java/lectures/lesson7/dau/DauServiceImpl.java new file mode 100644 index 00000000..60e8d564 --- /dev/null +++ b/src/main/java/hse/java/lectures/lesson7/dau/DauServiceImpl.java @@ -0,0 +1,52 @@ +package hse.java.lectures.lesson7.dau; + +import java.time.LocalDate; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class DauServiceImpl implements DauService { + + private Map> yesterday = new HashMap<>(); + private Map> today = new HashMap<>(); + private LocalDate currentDate = LocalDate.now(); + + @Override + public synchronized void postEvent(Event event) { + valiDate(); + today.computeIfAbsent(event.authorId(), id -> new HashSet<>()) + .add(event.userId()); + } + + @Override + public synchronized Map getDauStatistics(List authorIds) { + valiDate(); + Map result = new HashMap<>(); + for (int authorId : authorIds) { + result.put(authorId, getAuthorDauStatistics(authorId)); + } + return result; + } + + @Override + public synchronized Long getAuthorDauStatistics(int authorId) { + valiDate(); + Set users = yesterday.get(authorId); + return users == null ? 0L : (long) users.size(); + } + void nextDay() { + yesterday = today; + today = new HashMap<>(); + } + + private void valiDate() { + LocalDate now = LocalDate.now(); + if (now.isAfter(currentDate)) { + yesterday = today; + today = new HashMap<>(); + currentDate = now; + } + } +} diff --git a/src/test/java/hse/java/lectures/lesson7/dau/DauServiceTest.java b/src/test/java/hse/java/lectures/lesson7/dau/DauServiceTest.java new file mode 100644 index 00000000..c1800d16 --- /dev/null +++ b/src/test/java/hse/java/lectures/lesson7/dau/DauServiceTest.java @@ -0,0 +1,73 @@ +package hse.java.lectures.lesson7.dau; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +@Tag("dau") +class DauServiceTest { + + private DauServiceImpl service; + + @BeforeEach + void setUp() { + service = new DauServiceImpl(); + service.postEvent(new Event(1, 10)); + service.postEvent(new Event(2, 10)); + service.postEvent(new Event(3, 20)); + service.nextDay(); + } + + @Test + void sameUserClickedTwice_countedOnce() { + service.postEvent(new Event(5, 10)); + service.postEvent(new Event(5, 10)); + service.nextDay(); + + assertEquals(1L, service.getAuthorDauStatistics(10)); + } + + @Test + void twoUniqueUsers_countedCorrectly() { + assertEquals(2L, service.getAuthorDauStatistics(10)); + } + + @Test + void authorWithNoClicks_returnsZero() { + assertEquals(0L, service.getAuthorDauStatistics(99)); + } + + @Test + void differentAuthors_countedIndependently() { + Map stats = service.getDauStatistics(List.of(10, 20)); + assertEquals(2L, stats.get(10)); + assertEquals(1L, stats.get(20)); + } + + @Test + void getDauStatistics_unknownAuthorReturnsZero() { + Map stats = service.getDauStatistics(List.of(999)); + assertEquals(0L, stats.get(999)); + } + + @Test + void eventsPostedToday_notVisibleUntilTomorrow() { + service.postEvent(new Event(100, 10)); + assertEquals(2L, service.getAuthorDauStatistics(10)); + } + + @Test + void afterNewDay_previousDataReplaced() { + service.postEvent(new Event(7, 10)); + service.postEvent(new Event(8, 10)); + service.postEvent(new Event(9, 10)); + service.nextDay(); + + assertEquals(3L, service.getAuthorDauStatistics(10)); + } +}