diff --git a/commander/src/main/java/hse/java/commander/CommanderApplication.java b/commander/src/main/java/hse/java/commander/CommanderApplication.java index 471f6fd5..efe291c1 100644 --- a/commander/src/main/java/hse/java/commander/CommanderApplication.java +++ b/commander/src/main/java/hse/java/commander/CommanderApplication.java @@ -8,6 +8,8 @@ import java.io.IOException; import java.nio.file.Paths; + + public class CommanderApplication extends Application { @Override public void start(Stage stage) throws IOException { diff --git a/pom.xml b/pom.xml index bb6d9b8a..2efcc4ac 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,12 @@ ${lombok.version} provided + + org.mockito + mockito-junit-jupiter + 5.23.0 + test + diff --git a/src/main/java/hse/java/Task.java b/src/main/java/hse/java/Task.java new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/hse/java/lectures/lecture3/practice/randomSet/Debub.java b/src/main/java/hse/java/lectures/lecture3/practice/randomSet/Debub.java new file mode 100644 index 00000000..ed17fec7 --- /dev/null +++ b/src/main/java/hse/java/lectures/lecture3/practice/randomSet/Debub.java @@ -0,0 +1,20 @@ +package hse.java.lectures.lecture3.practice.randomSet; + +public class Debub { + public static void main(String[] args) { + RandomSet rs = new RandomSet(); + + rs.insert(10); + rs.insert(20); + + for (int i = 0; i < 20; i++) { + System.out.println(rs.getRandom()); + } + + rs.remove(10); + for (int i = 0; i < 20; i++) { + System.out.println(rs.getRandom()); + } + System.out.println(rs.remove(10)); + } +} diff --git a/src/main/java/hse/java/lectures/lecture3/tasks/html/HtmlDocument.java b/src/main/java/hse/java/lectures/lecture3/tasks/html/HtmlDocument.java index 1ddf27bf..e69de29b 100644 --- a/src/main/java/hse/java/lectures/lecture3/tasks/html/HtmlDocument.java +++ b/src/main/java/hse/java/lectures/lecture3/tasks/html/HtmlDocument.java @@ -1,32 +0,0 @@ -package hse.java.lectures.lecture3.tasks.html; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Set; - -public class HtmlDocument { - - public HtmlDocument(String filePath) { - this(Path.of(filePath)); - } - - public HtmlDocument(Path filePath) { - String content = readFile(filePath); - validate(content); - } - - private String readFile(Path filePath) { - try { - return Files.readString(filePath, StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RuntimeException("Failed to read file: " + filePath, e); - } - } - - private void validate(String content){} - -} diff --git a/src/main/java/hse/java/lectures/lesson7/dau/DauService.java b/src/main/java/hse/java/lectures/lesson7/dau/DauService.java index a02a0384..60e96694 100644 --- a/src/main/java/hse/java/lectures/lesson7/dau/DauService.java +++ b/src/main/java/hse/java/lectures/lesson7/dau/DauService.java @@ -1,7 +1,12 @@ package hse.java.lectures.lesson7.dau; +import java.sql.Time; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; public interface DauService { 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..ab3a9cd3 --- /dev/null +++ b/src/main/java/hse/java/lectures/lesson7/dau/DauServiceImpl.java @@ -0,0 +1,66 @@ +package hse.java.lectures.lesson7.dau; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.concurrent.*; + +public class DauServiceImpl implements DauService { + private ConcurrentMap yesterdayStat = new ConcurrentHashMap<>(); + private ConcurrentMap> nowStat = new ConcurrentHashMap<>(); + + private ScheduledExecutorService s = Executors.newScheduledThreadPool(1); + + DauServiceImpl() { + + ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault()); + ZonedDateTime nextRun = now.withHour(0).withMinute(0).withSecond(0).withNano(0); + + long initialDelay = Duration.between(now, nextRun).getSeconds(); + long period = TimeUnit.DAYS.toSeconds(1); + + s.scheduleAtFixedRate(this::update, + initialDelay, period, TimeUnit.SECONDS + ); + } + + void update() { + yesterdayStat.clear(); + for (var entry : nowStat.entrySet()) { + yesterdayStat.put(entry.getKey(), (long) entry.getValue().size()); + } + nowStat.clear(); + } + + + @Override + public void postEvent(Event event) { + nowStat.computeIfAbsent(event.authorId(), k -> ConcurrentHashMap.newKeySet()).add(event.userId()); + } + + @Override + public Map getDauStatistics(List authorIds) { + HashMap result = new HashMap<>(); + for (var id : authorIds) { + var stat = yesterdayStat.get(id); + result.put(id, stat == null ? 0 : stat); + } + return result; + } + + @Override + public Long getAuthorDauStatistics(int authorId) { + var res = yesterdayStat.get(authorId); + return (res == null ? 0 : res); + } + + void goToNextDay() { + update(); + } + + void stopScheduler() { + s.shutdownNow(); + } +} diff --git a/src/main/java/hse/java/practice/task1/Debug.java b/src/main/java/hse/java/practice/task1/Debug.java new file mode 100644 index 00000000..e69de29b diff --git a/src/test/java/hse/java/lectures/lecture3/tasks/html/HtmlDocumentTest.java b/src/test/java/hse/java/lectures/lecture3/tasks/html/HtmlDocumentTest.java index dcdb6459..e69de29b 100644 --- a/src/test/java/hse/java/lectures/lecture3/tasks/html/HtmlDocumentTest.java +++ b/src/test/java/hse/java/lectures/lecture3/tasks/html/HtmlDocumentTest.java @@ -1,114 +0,0 @@ -package hse.java.lectures.lecture3.tasks.html; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.Arguments; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; - -@Disabled -class HtmlDocumentTest { - - @Test - void validDocumentPasses() throws IOException { - String html = "

Hello

"; - Path path = writeTemp(html); - assertDoesNotThrow(() -> new HtmlDocument(path)); - } - - @Test - void validDocumentWithAttributesAndCasePasses() throws IOException { - String html = "

Ok

"; - Path path = writeTemp(html); - assertDoesNotThrow(() -> new HtmlDocument(path)); - } - - @Test - void unsupportedTagFails() throws IOException { - String html = ""; - Path path = writeTemp(html); - assertThrows(UnsupportedTagException.class, () -> new HtmlDocument(path)); - } - - @Test - void unexpectedClosingTagFails() throws IOException { - String html = ""; - Path path = writeTemp(html); - assertThrows(UnexpectedClosingTagException.class, () -> new HtmlDocument(path)); - } - - @Test - void mismatchedClosingTagFails() throws IOException { - String html = "

"; - Path path = writeTemp(html); - assertThrows(MismatchedClosingTagException.class, () -> new HtmlDocument(path)); - } - - @Test - void unclosedTagFails() throws IOException { - String html = "
"; - Path path = writeTemp(html); - assertThrows(UnclosedTagException.class, () -> new HtmlDocument(path)); - } - - @Test - void invalidStructureBodyBeforeHeadFails() throws IOException { - String html = ""; - Path path = writeTemp(html); - assertThrows(InvalidStructureException.class, () -> new HtmlDocument(path)); - } - - @Test - void invalidStructureMultipleHtmlFails() throws IOException { - String html = ""; - Path path = writeTemp(html); - assertThrows(InvalidStructureException.class, () -> new HtmlDocument(path)); - } - - @Test - void invalidStructureHeadNotDirectChildFails() throws IOException { - String html = "
"; - Path path = writeTemp(html); - assertThrows(InvalidStructureException.class, () -> new HtmlDocument(path)); - } - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("fileCases") - void fileCases(String resourcePath, Class expected) throws Exception { - Path path = Path.of(getClass().getClassLoader().getResource(resourcePath).toURI()); - if (expected == null) { - assertDoesNotThrow(() -> new HtmlDocument(path)); - } else { - assertThrows(expected, () -> new HtmlDocument(path)); - } - } - - static Stream fileCases() { - return Stream.of( - Arguments.of("html/valid_basic.html", null), - Arguments.of("html/valid_attrs_case.html", null), - Arguments.of("html/invalid_unsupported_tag.html", UnsupportedTagException.class), - Arguments.of("html/invalid_unexpected_closing.html", UnexpectedClosingTagException.class), - Arguments.of("html/invalid_mismatched.html", MismatchedClosingTagException.class), - Arguments.of("html/invalid_unclosed.html", UnclosedTagException.class), - Arguments.of("html/invalid_structure_body_before_head.html", InvalidStructureException.class), - Arguments.of("html/invalid_structure_multiple_html.html", InvalidStructureException.class), - Arguments.of("html/invalid_structure_head_not_direct_child.html", InvalidStructureException.class) - ); - } - - private Path writeTemp(String content) throws IOException { - Path path = Files.createTempFile("html-doc", ".html"); - Files.writeString(path, content); - path.toFile().deleteOnExit(); - return path; - } -} diff --git a/src/test/java/hse/java/lectures/lesson7/dau/DauServiceImplTest.java b/src/test/java/hse/java/lectures/lesson7/dau/DauServiceImplTest.java new file mode 100644 index 00000000..c2a4bdab --- /dev/null +++ b/src/test/java/hse/java/lectures/lesson7/dau/DauServiceImplTest.java @@ -0,0 +1,54 @@ +package hse.java.lectures.lesson7.dau; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + + +import java.time.LocalDate; +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.*; +@Tag("dau") +class DauServiceImplTest { + + @Test + void JustWorks() { + DauServiceImpl service = new DauServiceImpl(); + service.stopScheduler(); + service.postEvent(new Event(0,0)); + service.postEvent(new Event(0,1)); + service.postEvent(new Event(0,2)); + service.postEvent(new Event(1,0)); + service.goToNextDay(); + assertEquals(2L, service.getAuthorDauStatistics(0)); + assertEquals(1L, service.getAuthorDauStatistics(1)); + + } + + @Test + void ManyThreads() throws InterruptedException { + + ArrayList threads = new ArrayList<>(); + DauServiceImpl service = new DauServiceImpl(); + service.stopScheduler(); + for (int i = 0; i < 10; i++) { + int ii = i; + var thread = new Thread(() -> { + for (int j = 0; j < 10000; j++) { + service.postEvent(new Event(ii,j)); + } + }); + thread.start(); + threads.add(thread); + } + + for (var thr : threads) { + thr.join(); + } + service.goToNextDay(); + for (int i = 0; i < 10000; i++) { + assertEquals(10L, service.getAuthorDauStatistics(i)); + } + + } +} \ No newline at end of file