diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6b8dde0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: java +jdk: + - oraclejdk8 +os: + - linux +script: + - chmod +x buildscript.sh && ./buildscript.sh diff --git a/02.TicTacToe/pom.xml b/02.TicTacToe/pom.xml new file mode 100644 index 0000000..ead7aac --- /dev/null +++ b/02.TicTacToe/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + 02 + TicTacToe + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + junit + junit + 4.12 + + + junit + junit + 4.12 + + + + + \ No newline at end of file diff --git a/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/CreateElements.java b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/CreateElements.java new file mode 100644 index 0000000..b788eb6 --- /dev/null +++ b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/CreateElements.java @@ -0,0 +1,201 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + + +import javafx.application.Platform; +import javafx.geometry.Insets; +import javafx.scene.control.Button; +import javafx.scene.control.TextArea; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; + +import java.util.function.Consumer; + +/** Create UI elements */ +public class CreateElements { + + /** + * Create button + * + * @param x abscissa coordinate + * @param y ordinate coordinate + * @param text this text will be on the button + * @return new button + */ + public static Button createButton(GridPane gridPane, double height, double width, int x, int y, String text) { + Button button = new Button(); + gridPane.add(button, x, y); + button.setText(text); + button.setPrefHeight(height); + button.setPrefWidth(width); + button.setLayoutX(x); + button.setLayoutY(y); + return button; + } + + + /** + * Create board for TicTacToe. Every cell is button + * + * @return array of buttons + */ + public static Button[] createTableView(GridPane gridPane) { + Button[] buttons = new Button[9]; + for (int i = 0; i < 9; i++) { + buttons[i] = createButton(gridPane, 60, 60, 210 + 60 * (i % 3), 110 + 60 * (i / 3), ""); + } + return buttons; + } + + /**Create Menu for Main Activity */ + public static void createMainActivity(GridPane gridPane) { + Button buttonPlayWithComp = CreateElements.createButton(gridPane, 50, 200, 0, 0, "Играть с компьютером"); + Button buttonPlayWithFriend = CreateElements.createButton(gridPane, 50, 200, 0, 1, "Играть с другом"); + Button buttonExit = CreateElements.createButton(gridPane, 50, 200, 0, 2, "Выход"); + buttonPlayWithComp.setOnAction(actionEvent -> { + GameWithComp gameWithComp = new GameWithComp(gridPane, new Statistics()); + gameWithComp.menu(); + }); + + buttonPlayWithFriend.setOnAction(actionEvent -> { + GameWithFriend gameWithFriend = new GameWithFriend(gridPane, new Statistics()); + gameWithFriend.menu(); + }); + buttonExit.setOnAction(value -> Platform.exit()); + } + + /** + * Create button for new game + * + * @param statistics is parameter for consumer + * @param consumer will be accepted after clicking on the button + */ + public static void createButtonReplay(GridPane gridPane, Statistics statistics, Consumer consumer) { + Button rePlay = CreateElements.createButton(gridPane, 50, 200, 400, 20, "Начать новую партию"); + rePlay.setOnAction(actionEvent -> { + gridPane.getChildren().clear(); + consumer.accept(statistics); + }); + } + + + /** Create button to go to the main activity */ + public static void createButtonToMainActivity(GridPane gridPane) { + Button buttonToMainActivity = CreateElements.createButton(gridPane, 50, 200, 400, 350, "В главное меню"); + buttonToMainActivity.setOnAction(actionEvent -> { + gridPane.getChildren().clear(); + createMainActivity(gridPane); + }); + } + + + /** + * Create button to go to statistics for hot seat. After clicking go to new activity + * + * @param go will be accepted after clicking button back + */ + public static void createButtonGetStatisticsForOnePlayers(GridPane gridPane, Statistics statistics, Consumer go) { + Button getStatistics = CreateElements.createButton(gridPane, 50, 200, 200, 270, "Статистика"); + getStatistics.setOnAction(actionEvent -> { + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + Button buttonBack = CreateElements.createButton(gridPane, 50, 200, 400, 20, "Назад"); + buttonBack.setOnAction(actionEvent1 -> { + gridPane.getChildren().clear(); + go.accept(statistics); + }); + TextArea textArea = new TextArea(); + textArea.setLayoutY(0); + textArea.setLayoutX(0); + textArea.setPrefHeight(600); + textArea.setPrefWidth(200); + gridPane.getChildren().add(textArea); + textArea.setText("количество побед: " + statistics.getCountWins().toString() + + "\nколичество поражений: " + statistics.getCountLose().toString() + + "\nколичество ничьих: " + statistics.getCountDraw().toString()); + + }); + } + + + /** + * Create button to go to statistics for two players. After clicking go to new activity + * + * @param go will be accepted after clicking button back + */ + public static void createButtonGetStatisticsForTwoPlayers(GridPane gridPane, Statistics statistics, Consumer go) { + Button getStatistics = CreateElements.createButton(gridPane, 50, 200, 200, 240, "Статистика"); + getStatistics.setOnAction(actionEvent -> { + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + Button button = CreateElements.createButton(gridPane, 50, 200, 400, 20, "Назад"); + button.setOnAction(actionEvent1 -> { + gridPane.getChildren().clear(); + go.accept(statistics); + }); + TextArea textAreaForFirst = new TextArea(); + //textAreaForFirst.setLayoutY(0); + //textAreaForFirst.setLayoutX(0); + textAreaForFirst.setPrefHeight(600); + textAreaForFirst.setPrefWidth(200); + gridPane.add(textAreaForFirst, 0, 0); + textAreaForFirst.setText("Х \nколичество побед: " + statistics.getCountLose().toString() + + "\nколичество поражений: " + statistics.getCountWins().toString() + + "\nколичество ничьих: " + statistics.getCountDraw().toString()); + + + TextArea textAreaForSecond = new TextArea(); + textAreaForSecond.setLayoutY(0); + textAreaForSecond.setLayoutX(200); + textAreaForSecond.setPrefHeight(600); + textAreaForSecond.setPrefWidth(200); + gridPane.add(textAreaForSecond, 5, 0); + textAreaForSecond.setText("О \nколичество побед: " + statistics.getCountWins().toString() + + "\nколичество поражений: " + statistics.getCountLose().toString() + + "\nколичество ничьих: " + statistics.getCountDraw().toString()); + }); + } + + /** Print result on screen and update statistics */ + public static void setResult(GridPane gridPane, Statistics statistics, String win) { + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + switch (win) { + case "draw": { + TextArea textArea = new TextArea(); + textArea.setLayoutY(150); + textArea.setLayoutX(250); + textArea.setPrefHeight(50); + textArea.setPrefWidth(100); + textArea.setText("draw"); + gridPane.getChildren().add(textArea); + statistics.incDraw(); + break; + } + case "X": { + TextArea textArea = new TextArea(); + textArea.setLayoutY(150); + textArea.setLayoutX(250); + textArea.setPrefHeight(50); + textArea.setPrefWidth(100); + textArea.setText("X wins"); + gridPane.getChildren().add(textArea); + statistics.incLose(); + break; + } + default: { + TextArea textArea = new TextArea(); + textArea.setLayoutY(150); + textArea.setLayoutX(250); + textArea.setPrefHeight(50); + textArea.setPrefWidth(100); + gridPane.getChildren().add(textArea); + textArea.setText("O wins"); + statistics.incWins(); + break; + } + } + + } + +} diff --git a/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Game.java b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Game.java new file mode 100644 index 0000000..bedd786 --- /dev/null +++ b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Game.java @@ -0,0 +1,138 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + +import javafx.scene.control.Button; +import javafx.scene.layout.GridPane; + +/** + * Class for key actions of game + */ +public class Game { + /** + * GridPane for current game + */ + protected GridPane gridPane; + /** + * Number playing + */ + protected int numberGames = 0; + /** + * Statistics for current game + */ + protected Statistics statistics; + + /** + * Constructor + */ + public Game(GridPane gridPane, Statistics statistics) { + this.gridPane = gridPane; + this.statistics = statistics; + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + } + + /** + * Translated text from buttons array in string array + */ + protected String[] toStringArray(Button[] table) { + String[] tableString = new String[table.length]; + for (int i = 0; i < table.length; i++) { + tableString[i] = table[i].getText(); + } + return tableString; + } + + /** + * Check the state of the game + * + * @param tableString state board, "" - if cell is empty + * @return "X" - if X wins , "O" - if O wins, "" - if state is unknown, else - draw + */ + public static String check(String[] tableString) { + + boolean existEmpty = false; + for (int i = 0; i < tableString.length; i++) { + if (tableString[i].equals("")) { + existEmpty = true; + } + } + + for (int i = 0; i < 9; i += 3) { + if (!tableString[i].equals("") && tableString[i].equals(tableString[i + 1]) && tableString[i + 1].equals(tableString[i + 2])) { + return tableString[i]; + } + } + + for (int i = 0; i < 3; i++) { + if (!tableString[i].equals("") && tableString[i].equals(tableString[i + 3]) && tableString[i + 3].equals(tableString[i + 6])) { + return tableString[i]; + } + } + + if (!tableString[0].equals("") && tableString[0].equals(tableString[4]) && tableString[4].equals(tableString[8])) { + return tableString[0]; + } + + if (!tableString[2].equals("") && tableString[2].equals(tableString[4]) && tableString[4].equals(tableString[6])) { + + return tableString[2]; + } + if (existEmpty) { + return ""; + } else { + return "draw"; + } + } + + /** + * /** + * Check the state of the game + * + * @param tableString state board, "" - if cell is empty + * @param isPreliminaryCheck, true - if real state, false - if we want check move + * @return "X" - if X wins , "O" - if O wins, "" - if state is unknown, else - draw + */ + protected String check(String[] tableString, boolean isPreliminaryCheck) { + String result = check(tableString); + if (!isPreliminaryCheck && !result.equals("")) { + setResult(result); + } + return result; + } + + /** + * Print result games + */ + private void setResult(String win) { + numberGames++; + CreateElements.setResult(gridPane, statistics, win); + CreateElements.createButtonReplay(gridPane, statistics, this::goBack); + } + + /** + * For return in this activity + */ + protected void goBack(Statistics statistics) { + this.statistics = statistics; + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + menu(); + } + + /** + * Symbol to which the player move + */ + + public String getCompSymb(int player) { + return (numberGames % 2 == player) ? "X" : "O"; + } + + + /** + * Before games we should choose characteristics game + */ + public void menu() { + CreateElements.createButton(gridPane, 50, 200, 200, 70, "Легкий"); + CreateElements.createButton(gridPane, 50, 200, 200, 170, "Сложный"); + } + +} diff --git a/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithComp.java b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithComp.java new file mode 100644 index 0000000..ea5fd07 --- /dev/null +++ b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithComp.java @@ -0,0 +1,125 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + + +import javafx.scene.control.Button; +import javafx.scene.layout.GridPane; + +import java.util.Random; +import java.util.function.Consumer; + +public class GameWithComp extends Game { + /** + * Constructor + * + * @param statistics for collection information + */ + public GameWithComp(GridPane gridPane, Statistics statistics) { + super(gridPane, statistics); + } + + + /** + * Menu. + * Choose level or get statistics + */ + @Override + public void menu() { + CreateElements.createButtonGetStatisticsForOnePlayers(gridPane, statistics, value -> menu()); + Button buttonEasyLevel = CreateElements.createButton(gridPane, 50, 200, 200, 70, "Легкий"); + Button buttonHardLevel = CreateElements.createButton(gridPane, 50, 200, 200, 170, "Сложный"); + buttonEasyLevel.setOnAction(value -> { + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + playGame(this::moveCompEasyLevel); + }); + buttonHardLevel.setOnAction(value -> { + gridPane.getChildren().clear(); + CreateElements.createButtonToMainActivity(gridPane); + playGame(this::moveCompHardLevel); + }); + } + + /** + * Start game + * + * @param moveComp move computer + */ + private void playGame(Consumer moveComp) { + CreateElements.createButtonReplay(gridPane, statistics, this::goBack); + Button[] table = CreateElements.createTableView(gridPane); + if (numberGames % 2 == 0) { + moveComp.accept(table); + } + for (Button button : table) { + button.setOnAction(actionEvent -> { + button.setText(getCompSymb(1)); + button.setDisable(true); + moveComp.accept(table); + }); + } + + + } + + /** Move will be get with help random */ + private void moveCompEasyLevel(Button[] table) { + Random random = new Random(); + if (check(toStringArray(table), false).equals("")) { + while (true) { + int x = random.nextInt(table.length); + if (table[x].getText().equals("")) { + table[x].setText(getCompSymb(0)); + table[x].setDisable(true); + break; + } + } + check(toStringArray(table), false); + } + } + + /** + * Analyze board. + * It's guaranteed if there is a possibility of winning in one step, then this step will be taken + */ + private void moveCompHardLevel(Button[] table) { + int move = goodMove(toStringArray(table), getCompSymb(0), getCompSymb(1)); + if (move == -1) { + moveCompEasyLevel(table); + } else { + table[move].setText(getCompSymb(0)); + table[move].setDisable(true); + check(toStringArray(table), false); + } + } + + /** + * Check, if there is a possibility of winning in one step, then return index of cell + * And interfere enemy win in the next move + * + * @return number cell + */ + public static int goodMove(String[] tableString, String symbolPlayer1, String symbolPlayer2) { + + for (int i = 0; i < tableString.length; i++) { + if (tableString[i].equals("")) { + tableString[i] = symbolPlayer1; + String whoWin = Game.check(tableString); + if (whoWin.equals(symbolPlayer1)) { + return i; + } + tableString[i] = ""; + } + } + for (int i = 0; i < tableString.length; i++) { + if (tableString[i].equals("")) { + tableString[i] = symbolPlayer2; + String whoWin = check(tableString); + if (whoWin.equals(symbolPlayer2)) { + return i; + } + tableString[i] = ""; + } + } + return -1; + } +} diff --git a/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithFriend.java b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithFriend.java new file mode 100644 index 0000000..1e7ae0b --- /dev/null +++ b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithFriend.java @@ -0,0 +1,52 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + +import javafx.scene.control.Button; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; + + +public class GameWithFriend extends Game { + + /** + * Constructor + * + * @param statistics for collection information + */ + public GameWithFriend(GridPane gridPane, Statistics statistics) { + super(gridPane, statistics); + } + + /** Menu. Two categories : play and get statistics */ + @Override + public void menu() { + Button buttonPlay = CreateElements.createButton(gridPane, 50, 200, 200, 110, "Играть"); + buttonPlay.setOnAction(actionEvent -> { + gridPane.getChildren().clear(); + CreateElements.createButtonReplay(this.gridPane, statistics, this::goBack); + playGame(); + }); + CreateElements.createButtonGetStatisticsForTwoPlayers(gridPane, statistics, value -> menu()); + } + + /** Start play */ + private void playGame() { + Button[] table = CreateElements.createTableView(gridPane); + changeMove(table, 0); + } + + /** Change players move */ + private void changeMove(Button[] table, int x) { + String c = getCompSymb(x); + for (Button button : table) { + button.setOnAction(actionEvent -> { + button.setText(c); + button.setDisable(true); + check(toStringArray(table), false); + changeMove(table, 1 - x); + }); + } + + } + + +} diff --git a/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Main.java b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Main.java new file mode 100644 index 0000000..29ddc41 --- /dev/null +++ b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Main.java @@ -0,0 +1,31 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + +import javafx.application.Application; + +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setTitle("Крестики - Нолики"); + GridPane gridPane = new GridPane(); + gridPane.setAlignment(Pos.CENTER); + CreateElements.createMainActivity(gridPane); + primaryStage.setScene(new Scene(gridPane, 600, 400)); + primaryStage.show(); + + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Statistics.java b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Statistics.java new file mode 100644 index 0000000..7ca02a9 --- /dev/null +++ b/02.TicTacToe/src/main/java/ru/spbau/mit/alyokhina/TicTacToe/Statistics.java @@ -0,0 +1,30 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + +/** Class for collection information about games */ +public class Statistics { + private int countWins = 0; + private int countLose = 0; + private int countDraw = 0; + + public void incWins() { + countWins++; + } + + public void incLose() { + countLose++; + } + public void incDraw() { + countDraw++; + } + public Integer getCountWins() { + return countWins; + } + + public Integer getCountLose() { + return countLose; + } + + public Integer getCountDraw() { + return countDraw; + } +} diff --git a/02.TicTacToe/src/test/java/ru/spbau/mit/alyokhina/TicTacToe/GameTest.java b/02.TicTacToe/src/test/java/ru/spbau/mit/alyokhina/TicTacToe/GameTest.java new file mode 100644 index 0000000..1c99265 --- /dev/null +++ b/02.TicTacToe/src/test/java/ru/spbau/mit/alyokhina/TicTacToe/GameTest.java @@ -0,0 +1,109 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class GameTest { + @Test + public void checkIfNoResult() { + String board[] = new String[]{ + "", "", "", + "", "", "", + "", "", "" + }; + + assertEquals("", Game.check(board)); + } + + @Test + public void checkIfXWinInDiagonal() { + String board[] = new String[]{ + "X", "O", "O", + "", "X", "", + "", "", "X" + }; + + assertEquals("X", Game.check(board)); + } + + @Test + public void checkIfXWinInVertical() { + String board[] = new String[]{ + "X", "O", "", + "X", "", "O", + "X", "", "" + }; + + assertEquals("X", Game.check(board)); + } + + @Test + public void checkIfXWinInHorizontal() { + String board[] = new String[]{ + "", "O", "", + "X", "X", "X", + "", "O", "" + }; + + assertEquals("X", Game.check(board)); + } + + @Test + public void checkIfOWinInDiagonal() { + String board[] = new String[]{ + "O", "X", "X", + "", "O", "", + "", "", "O" + }; + + assertEquals("O", Game.check(board)); + } + + @Test + public void checkIfOWinInVertical() { + String board[] = new String[]{ + "O", "X", "", + "O", "", "X", + "O", "", "" + }; + + assertEquals("O", Game.check(board)); + } + + @Test + public void checkIfOWinInHorizontal() { + String board[] = new String[]{ + "", "X", "", + "O", "O", "O", + "", "X", "" + }; + + assertEquals("O", Game.check(board)); + } + + + @Test + public void checkIfDraw() { + String board[] = new String[]{ + "X", "O", "X", + "O", "X", "X", + "O", "X", "O" + }; + + assertEquals("draw", Game.check(board)); + } + + @Test + public void checkIfExistMove() { + String board[] = new String[]{ + "X", "O", "", + "O", "X", "X", + "O", "X", "O" + }; + + assertEquals("", Game.check(board)); + } + + +} \ No newline at end of file diff --git a/02.TicTacToe/src/test/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithCompTest.java b/02.TicTacToe/src/test/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithCompTest.java new file mode 100644 index 0000000..f00d64a --- /dev/null +++ b/02.TicTacToe/src/test/java/ru/spbau/mit/alyokhina/TicTacToe/GameWithCompTest.java @@ -0,0 +1,51 @@ +package ru.spbau.mit.alyokhina.TicTacToe; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class GameWithCompTest { + @Test + public void goodMoveEmptyBoard() { + String board[] = new String[]{ + "", "", "", + "", "", "", + "", "", "" + }; + + assertEquals(-1, GameWithComp.goodMove(board, "X", "O")); + } + + @Test + public void goodMoveifCanBeMoveOnDiagonal() { + String board[] = new String[]{ + "X", "", "", + "", "", "", + "O", "", "X" + }; + + assertEquals(4, GameWithComp.goodMove(board, "X", "O")); + } + + @Test + public void goodMoveIfCanBeMoveOnVertical() { + String board[] = new String[]{ + "X", "X", "", + "", "", "", + "O", "", "O" + }; + + assertEquals(2, GameWithComp.goodMove(board, "X", "O")); + } + + @Test + public void goodMoveIfCanBeMoveOnHorizontal() { + String board[] = new String[]{ + "X", "", "", + "", "X", "X", + "O", "", "O" + }; + + assertEquals(3, GameWithComp.goodMove(board, "X", "O")); + } +} \ No newline at end of file diff --git a/buildscript.sh b/buildscript.sh new file mode 100755 index 0000000..1cc07e7 --- /dev/null +++ b/buildscript.sh @@ -0,0 +1,9 @@ +#!/bin/bash +files=$(find . -maxdepth 1 -type d | grep "./0.*") +for file in $files +do + cd $file + mvn test -B + cd ../ +done + diff --git a/test/2.txt b/test/2.txt new file mode 100644 index 0000000..a30e194 --- /dev/null +++ b/test/2.txt @@ -0,0 +1,264 @@ +Абстрактные +С момента первого описания канонической двойной спирали ДНК В-формы было предложено +что существуют альтернативные ДНК, ДНК-РНК и РНК-структуры и действуют как функциональные геномные +элементы. Действительно, за последние несколько лет стало ясно, что помимо +хранилище для генетической информации, геномная ДНК выявляет биологические ответы путем принятия +которые отличаются от канонической правой правой спирали и взаимодействием +с молекулами РНК для образования сложных вторичных структур. В этом обзоре основное внимание уделяется последним +достижения трехцепочечных (триплексных) нуклеиновых кислот с акцентом на ДНК-РНК и +РНК-РНК-взаимодействия. В новой работе показано, что триплексные взаимодействия между некодированием +РНК и дуплексная ДНК служат платформами для доставки эпигенетических меток, специфичных для сайта, критических +для регуляции экспрессии генов. Кроме того, растущий объем генетических и +структурные исследования показывают, что триплексные РНК-РНК-взаимодействия необходимы для выполнения +каталитические и регуляторные функции в клеточных нуклеопротеиновых комплексах, включая +spliceosomes и теломеразы, а также для обеспечения возможности перекодирования белка во время запрограммированного рибосомального +frameshifting. Таким образом, доказано, что взаимодействие триплексов ДНК и РНК +для осуществления целого ряда разнообразных биологических активностей в клетке, некоторые из которых будут +в этом обзоре. +Введение +В последнее десятилетие прогресс в области структуры ДНК и в генетическом и биологическом +функции его полиморфных конформаций привели к важной реализации того, что ДНК +а не просто пассивный носитель генетической информации. Скорее, приняв конформации, которые различаются +из канонической двойной спирали ДНК В-формы ДНК сама играет активную роль в клеточной +процессы. Знание того, что основания ДНК могут участвовать в взаимодействиях с водородной связью, которые различаются +от канонических шаблонов связывания Уотсона-Крика и что нити ДНК способны образовывать +вторичные структуры, которые отклоняются от общей (В-формы) правой правой спирали, даты +к началу 1950-х годов [1,2]. С тех пор более дюжины таких альтернативных конформаций ДНК, +были названы не-B-ДНК. Параллельно с этим новатором +работа, последовательность усилий, предшествовавших разработке последовательности генома человека, четко выявленной +что не-B ДНК-образующие мотивы сильно перепредставлены у млекопитающих и других +геномов и что не-B-структуры ДНК формируются in vivo, что вызывает интерес к вопросу о +их потенциальная биологическая функция [3,4]. + +В 1991 году открытие нового класса наследственных неврологических заболеваний, вызванных +расширение нестабильных микросателлитных повторов, обозначенных точкой поворота в области не-B-ДНК, +с исследованиями, которые последовали за твердой установкой прямой связи между образованием +неканонических структур ДНК в геномах и заболеваниях человека [5-8], преимущественно опосредованных +с помощью механизмов восстановления ДНК [9-12]. В последние годы поле значительно диверсифицировалось, +отчасти из-за осознания того, что вследствие широко распространенного транскрипционного +активности генома, возможности взаимодействия РНК и ДНК-РНК, приводящие к сложному +вторичные структуры нуклеиновой кислоты огромны. Здесь мы предоставляем обновленную информацию о ДНК- +РНК и РНК триплексных структур с акцентом на их новые роли в качестве эффекторов биологических +и ссылаются на недавние обзоры триплексов ДНК [10,13,14]. +Триплексные взаимодействия +Тройные спиральные взаимодействия нуклеиновых кислот были охарактеризованы различными методами на +олигонуклеотидов и плазмидной ДНК [2,3]. Триплетные взаимодействия опосредуются при гомопурине- +гомопиримидиновые последовательности с зеркальной повторной симметрией с помощью водородной связи Hoogsteen +между богатой пурином нитью дуплексной ДНК и либо богатым пиримидином, либо богатым пурином +третья нить (рис. 1). Пиримидиноподобные взаимодействия с третьей цепью стабилизируются T • A-T и +C + +• Водородные связи G-C Hoogsteen («•» = водородные связи Hoogsteen; »-« = Watson-Crick +водородные связи; R = A или G; Y = C или T) и особенно предпочтительны при низком рН, что облегчает +потребность в протонизации цитозина в положении N3 (рис. 1, справа). Напротив, +богатые пурином взаимодействия с третьей цепью образуют A • A-T и G • G-C обратный Hoogsteen водород +(рис. 1, слева), которые не требуют кислотного рН, но стабилизируются двухвалентными катионами, такими как +Mg2 +. +Триплетные ДНК-образующие последовательности были вовлечены в широкий спектр биологических активностей, +включая регуляцию экспрессии генов [15-17], приостановку репликации [18-20] и генетическую +нестабильность, ведущая к расстройствам человека, включая рак [6,7,21-26]. В контексте геномных +нестабильность, последовательности человеческого триплекса, образующие ДНК, интегрированные в геном мыши +более высокие скорости больших делеций, в то время как не было обнаружено никакой неустойчивости в контроле образования B-ДНК +последовательностей [22]. В ряде сообщений предполагается, что триплексная ДНК может вызывать генетическую нестабильность +с помощью нескольких механизмов, таких как использование контрольного блока для репликации ДНК и транскрипции +удлинение [25, 27-29]. Также предложены модели, не зависящие от тиражирования; например, +спиральные искажения и структурные изменения, индуцированные триплексной ДНК, могут быть распознаны как +«Повреждение ДНК», а затем обработано с ошибкой (рис. 2) [23]. +Роли некодирующей РНК в биологически активных ДНК-РНК-триплетах +Недавнее открытие, что транскрипция не ограничивается белок-кодирующими генами у человека +генома, но является широко распространенной активностью, происходящей в большинстве (приблизительно 80%) хромосомных +ДНК, дающая семьи некодирующих РНК, повысила осведомленность о ключевых клетках +функции, которые играют взаимодействия между некодирующими РНК и белками, белок-кодирующая РНК +транскриптов и геномной ДНК [30-32]. Наиболее распространенные типы некодирующей РНК включают +микроРНК, короткие (22 нт) РНК, которые ингибируют синтез белка путем связывания с конкретными мРНК, +(> 200 нт) некодирующих РНК (lncRNAs), некоторые из которых были связаны с +регуляция транскрипции гена, сплайсинга и трансляции [33] и небольших нуклеолярных РНК, +которые участвуют в химических модификациях других РНК, включая рибосомальные (рДНК) и +перенос РНК (тРНК). +Связь между некодирующими транскриптами РНК и геномной ДНК особенно актуальна +в контексте этого обзора из-за образования биологически активного трисплекса РНК-дцДНК +структур [34]. Предполагается, что одна такая структура, описанная в локусе Foxf1 мыши + +роль лесов для доставки эпигенетических модификаций, специфичных для сайта, приводящих к гену +глушители. В частности, расходящаяся транскрипция из промотора Foxf1 генерирует lncRNA, +называемый Fenddr, чье выражение имеет решающее значение для эмбрионального развития у мышей. Fendrr имеет +было показано, что он специфически связывается с поликомбическим репрессивным комплексом эпигенетической модификации +2 (PRC2), белковый комплекс, который выполняет триметилирование остатков гистона 3 лизина 27 +(H3K27me3), что, в свою очередь, ингибирует транскрипцию. Целевые гены ингибирующей активности +комплекс Fendrr-PRC2 включает сам ген Foxf1 и Pitx2, что имеет решающее значение для +развитие внутренних органов. Считается, что РНК Fendrr выполняет две отдельные операции: (1) +связывание с дуплексными промоторными последовательностями с образованием триплекса РНК-дцДНК; и (2) закрепление +PCR2 (фиг. 3A и 3B). Fendrr также связывает другие молекулы, такие как группа триторакса +белка TrxG / Mll, который устанавливает активные метки транскрипции путем метилирования остатков лизина 4, также +на гистоне H3 (H3K4me3). Следовательно, образование триплексов, по-видимому, служит общим лесам +роль, независимо от ферментативной функции родственных комплексов. Действительно, строительные леса +возникающая как общая роль для lncRNAs, такая как транскрипционная антисмысловая РНК HOX +(HOTAIR, также партнер PRC2), который сверхэкспрессируется во многих раках, включая +первичные и метастатические опухоли молочной железы [35,36]. +Была также предложена роль для образования некодирующего триплексного образования РНК-дцДНК при молчании генов +для рибосомных РНК-кодирующих (рДНК) генов [37]. В геномах млекопитающих только подмножество +тандемных массивов генов рДНК транскрибируется, при этом молчание достигается комбинацией +репрессивных следов хроматина и метилирования основного сайта CpG на rDNA + +промотор [38]. Состояние гетерохроматина поддерживается нуклеолярным ремоделирующим комплексом +NorC, который включает в себя TTF-I-взаимодействующий белок 5 (TIP5) и SNF2h и не кодирующий +РНК, транскрибируемая из самого промотора рДНК (рРНК). Текущая модель гена rDNA +молчание предполагает критическую роль для рРНК, которая взаимодействует с комплексом TIP5-SNF2h и +образует триплекс РНК-дцДНК с областью промотора рДНК [37]. Триплекс РНК-дцДНК +структуры предлагается вытеснить гниение молчания тремя способами: во-первых, путем окклюзии To, критического +сайт связывания для активатора транскрипции TTF-I; во-вторых, путем набора ДНК-цитозин-5-метилтрансферазы +DNMT3b для метилирования основного участка CpG; и в-третьих, путем набора гистонов +деацетилазы и гистон-метилтрансферазы через комплекс TIP5-SNF2h для консолидации +гетерохроматиновая структура (рис. 3С) [37]. +Недавно возникла гипотетическая гипотеза о работе с инфицированными lentiviral +клеток, что предполагает критическую роль микроРНК в поддержании вирусной латентности через РНК- +dsDNA триплекс-образование [39,40]. Основываясь на ряде выводов, включая ключевые наблюдения +что вирусные нагрузки ВИЧ-1 в мононуклеарных клетках периферической крови ВИЧ-1-инфицированных лиц +отрицательно коррелируют с окрашиванием иммунофлюоресценцией для триплексных нуклеиновых кислот, авторы +предложить, чтобы одна из ролей микроРНК заключалась в противодействии вирусной инфекции. Модель предполагает +что у приматов микроРНК, синтезированные из транспозонов, ретровирусов и других +ретро-элементы образуют триплексы РНК-дцДНК с соответствующим гомопурином-гомопиримидином +области провирусных геномов в цитоплазме, тем самым предотвращая миграцию, интеграцию, +и вирусная репликация в ядре [40]. + +Эти составные данные открывают новые границы в роли некодирующих РНК как биологических +эффекторы функциональных вторичных структур нуклеиновой кислоты высокого порядка в клетке. тем не менее, +необходимы дальнейшие исследования, чтобы уточнить детали взаимодействия между некодирующими РНК и +их дуплексные целевые сайты ДНК. +Триплексы РНК +Сообщает, что в РНК могут образовываться от двух до шести последовательных базовых триплетов, либо путем сгибания +одной молекулы или взаимодействием между двумя молекулами РНК или лигандами РНК, были +представленный в литературе с конца 1970-х годов [41]. Однако представление о том, что триплексы РНК +занимают значительную нишу в различных биологических процессах, только в последнее время реализуются. из +примечание, было показано, что внутримолекулярное триплексное образование резко стабилизирует некоторые lncRNAs, +таких как человеческий MALAT1, один из наиболее распространенных и высококонсервативных lncRNAs, который +функционирует как цис-фактор в регуляции экспрессии генов [42, 43] и полиаденилированного ядерного +РНК из связанного с саркомой Капоши герпесвируса [44]. Здесь мы рассматриваем прогресс, достигнутый в +Триплексы РНК с акцентом на работу, опубликованную в течение последних нескольких лет, и отсылают читателя к +недавние обзоры [45,46] и конкретные публикации о связанных рибосвитчи [47] и структурных +Мотивы РНК [48]. +Триплекс РНК в каталитическом центре Spliceosomes +Значительным достижением, связанным с трипсерами РНК, является недавнее открытие каталитической роли в РНК +сплайсинга, ключевого клеточного механизма, через который интроны удаляются из пре-мРНК. + +Недавно опубликованные генетические и биохимические исследования показали, что образование триплексов РНК +внутри промотированного каталитическим связыванием сплайсосом и последовательных стадий расщепления (фиг. +4А) [49]. Spliceosomes, крупные рибонуклеопротеиновые механизмы, содержащие приблизительно 170 +белки у людей и пять небольших ядерных РНК (U1, U2, U4, U5 и U6 snRNAs), собирают +в динамические комплексы для сращивания [50]. Сильное сходство в сохранении последовательности +и складывающиеся промежуточные соединения между субъединицей UR snRNA из spliceosomes и областью V +интроны II группы [51], транспонируемые элементы, кодирующие РНК, которые являются самосплавками в отсутствие +белки, внесли свой вклад в давние предположения о том, что сплаксисомовый катализ RNAbased +[52-54]. Использование кристаллографической структуры интронов группы Oceanobacillus ihejensis II +[55], в котором триплекс РНК координирует два иона магния, необходимые для катализа, металл +эксперименты по спасению, генетические мутационные анализы и сшивающие анализы показали, что оба +стадии сращивания требуют триплексной структуры, образованной компонентами РНК сплайсомы +[56,57]. В дрожжах высококонсервативные 50 +-AGC-30 в спирали 1b пар оснований U6 с обоими 50 +- +Остатки GCU-30 U2 через канонические водородные связи Ватсона-Крика и через третичные +взаимодействия с удаленными базами в U6 и консервативным выпуклым U80, чтобы получить три триплета (рис. +4B). Остатки U80, A59 и G78 вступают в прямой контакт с двумя ионами магния, которые помогают +как каталитические стадии расщепления до мРНК [56,57]. +Хотя структура с высоким разрешением каталитического сайта spliceosome еще недоступна, +аналогия с интронами группы II подтверждает мнение о том, что оба механизма функционируют как рибозимы +и обмениваются общим эволюционным предком. В кристаллических структурах О. ihejensis и +бурые водоросли Pylaiella littoralis II группы интронов, триплексные структуры служат для создания геометрических +и отрицательно заряженная клетка для вербовки двух ионов металлов и их размещение на +критическое расстояние около 3,9 Å друг от друга. Это позволяет классическим +двухкомпонентный ионный катализ [58], механизм, обычно встречающийся в ферментах, таких как ДНК и +РНК-полимеразы [52]. Остается ряд вопросов, в том числе и тот же триплекс +структура работает во время обеих стадий катализа, и является ли белковый эшафот индуцированным триплексом +образование и опосредует его взаимодействия с пре-мРНК [59-61]. +Два триплета РНК необходимы для активности теломеразы +Теломеры, специализированные ДНК-белковые комплексы на конце линейных хромосом, защищают +хромосомы от сквозного слияния и эрозии. Их длина поддерживается теломеразой, +рибонуклеопротеидный комплекс, который добавляет видоспецифичные повторы ДНК с использованием обратной транскриптазы +активности (TERT) на внутреннем компоненте РНК (TR) [62]. В основе ТР лежит +pseudoknot (фиг.4C), общая складка РНК [48], содержащая две петли и две стебли, которые в +дополнение к дуплексным взаимодействиям, далее стабилизируется триплексной структурой, которая была показана +для обеспечения оптимальной активности теломеразы [45]. Также были предсказаны базовые троек в псевдокнотах TR +в инфузориях [63], и недавнее исследование дрожжей Kluyveromyces lactis подтвердило +структурное сходство с триплексом человека TR и его потребность в теломеразе +деятельности [64]. ЯМР и мутационные анализы подтверждают образование расширенного пиримидинера +триплекс в теломеразе K. lactis TR. Основные проблемы, которые еще предстоит решить, включают роль +триплексов TR в активности теломеразы, как триплетные структуры способствуют катализу, и +как геометрические механизмы, налагаемые триплексами, также играют роль в катализе [45]. +Тем не менее, обнаружение того, что триплексы находятся в непосредственной близости от каталитического центра и +шаблон был взят как указание на то, что триплексные структуры в теломеразах необходимы для +функции in vivo [64]. +Недавно в CB4 / 5 субдомен позвоночных был отмечен второй 2-тройной минихеликс +Oryzias latipes (японская медака) TR в комплексе с TR-связывающим доменом (TRBD) +TERT (рис. 4C и 4D) [65]. Эти и другие изменения, вызванные TRBD, происходят с трех сторон +соединение между спиралями P5, P6 и P6.1, в результате чего P5 и P6 складываются соосно, а P6.1 - +поверните на 180 ° вокруг области соединения и на TRBD (рис. 4D). Однако точное +роль этого двухуровневого триплета и связанные с ним CR4 / 5 конформационные изменения в теломеразе +функция остается неразрешенной. Например, A199, высококонсервативный остаток на P6 / P6.1 +соединение, образует неканоническую пару с G213 в CR4 / 5-TRBD, но она непарена в свободном CR4 / +5 (фиг. 4D) [65,66]. Анализ мутаций в A199 и на соответствующем остатке в Schizosaccharomyces +pombe, Neurospora crassa и люди произвели противоречивые результаты либо +нарушая взаимодействие CR4 / 5 с TRBD и нарушая функцию теломеразы [65] или вызывая +мелкие дефекты [66]. +Триплексы РНК выступают как дорожные блоки, способствующие перекодировке +Запрограммированное рибосомальное смещение кадров (PRF) относится к свойству, наблюдаемому в нескольких вирусных +мРНК для генерации альтернативных белков рамки считывания посредством перекодирования, в результате чего рибосомы +вынуждены сдвигаться на +/- 1 или +/- 2 базы для продолжения перевода [67]. МРНК сигнализирует, что +индуцировать -1 PRF включают «скользкую» последовательность, такую ​​как UUUAAAC, UUUUUUUA и т. д., затем +стимулирующей структурой (физическим барьером, часто представленным псевдокнотом). «Скользкий» +последовательность и физический барьер, как полагают, действуют согласованно, чтобы приостановить рибосому +повторяющаяся последовательность, стимулирующая ее перепозиционирование на альтернативных кадрах считывания до +возобновляемый перевод. В некоторых вирусах, таких как вирус западной свеклы свеклы, Pea enanion +вируса типа 1, вируса желтого листа сахарного тростника и тианинового ретровируса типа 1, псевдоокноты стабилизируются +триплексными взаимодействиями [68], аналогичными описанной выше Т-теломеразе. В отсутствие +таких тройных взаимодействий РНК, PRF неэффективен, и мутационные анализы поддерживают представление +что триплексные структуры служат для увеличения псевдостойкости стебля и устойчивости к кручению, как +из которых усиливаются механические препятствия для транслокации мРНК на рибосомы [69,70]. +Монтажные данные подтверждают мнение, что -1 PRF не ограничивается вирусными мРНК. В стороне +из того, что предполагается, что приблизительно 10% генов в геномах эукариот содержат +-1 PRF и что -1 PRF контролирует содержание теломеразы в дрожжах [71], роман +механизм для -1 PRF, основанный на взаимодействии между микроРНК и псевдокнотами, +недавно были зарегистрированы в мРНК рецептора цитокинов человека [72]. В конкретном случае CCR5, +Предполагается, что miR-1224 образует триплекс с псевдокнотом мРНК CCR5 и повышает -1 +PRF. Поскольку после этого PRF следует деградация мРНК через несущую нонсенс мРНК +распад, предполагается, что он представляет собой механизм регулирования клеточного ответа на +цитокинов [72]. Непосредственное доказательство для miR / pseudoknot триплексных структур требует дальнейшего изучения. +Тем не менее, вывод о том, что сигналы PRF распространены в геномах эукариот и что не кодирование +РНК, богатый пул геномных транскриптов, могут участвовать в триплексных взаимодействиях +либо с РНК, либо ДНК [37,38,73,74] предполагает, что триплексные взаимодействия РНК в геномах могут +происходят чаще, чем в настоящее время оцениваются. +Выводы +Все шире признается, что триплексная ДНК, а также другие не-B-структуры ДНК +не обсуждаются здесь, такие как квадруплексная ДНК, крестообразные формы, сложенные структуры и левые +Z-ДНК, являются внутренним источником генетической нестабильности внутри клетки ([10,75] и ссылки +в нем). Это новая концепция, поскольку традиционная точка зрения заключается в том, что генетические +нестабильность возникает в результате оскорблений ДНК из внешних факторов (например, окислителей, ультрафиолетовых лучей +свет, канцерогены) и дефектный ремонт ДНК. Основной сферой исследования на будущее будет +идентифицировать клеточные пути, которые распознают структуры ДНК, отличные от B, и обрабатывать их для получения +генетические перегруппировки (например, делеции, инверсии и транслокации). Выяснение этих путей +будет иметь особое значение для биологии рака, поскольку, как и было предсказано [10,76], не-B-ДНК +конформации могут играть активную роль в индуцировании мутаций в онкологических геномах. +В клетке синтезируется несколько семейств некодирующих РНК, некоторые из которых взаимодействуют с +дуплексной ДНК для формирования триплексных структур, которые играют важную функциональную роль. Таким образом, триплексные взаимодействия +позволяют lncRNAs повышать свою регуляторную активность транскрипции, предоставляя строительные леса +платформу для эффективной доставки эпигенетических модификаций сайта. Учитывая большие +фракция геномной ДНК, транскрибируемая, будет интересно оценить, насколько широко распространена +использование третичных взаимодействий ДНК-РНК в регуляции генов in vivo. + +Последняя работа показала, что тройные взаимодействия между молекулами РНК и внутри них +служат критическим функциям для клеточных процессов, таких как сращивание, теломеразная активность и белок +перекодирование, деятельность, которая, как представляется, выходит за рамки вирусов. Однако многие детали остаются +уточнить относительно точных механизмов, посредством которых эти третичные структуры вызывают +их роли, особенно в отношении теломеразной функции. +В нашей дискуссии основное внимание было уделено возникающим ролям триплексных нуклеиновых структур в качестве эффекторов +биологической активности и, как следствие, не занимались другими областями исследования, такими как триплекс-формирование +олигонуклеотидов (TFO), в которых триплетные взаимодействия преследуются как +означает искусственно изменять структуру и функцию гена, такие как регуляция экспрессии генов. +Таким образом, в контексте выяснения механизмов, которые приводят к вызванным триплеком генетическим неустойчивостям, +будет важно оценить, существуют ли различия в ремонтных путях, связанных с обработкой +эндогенные (то есть H-ДНК) и экзогенные (т. е. ТФО-производные) триплексные структуры. +Таким образом, последние годы стали свидетелями расширения исследований по триплексной базовой паре +взаимодействий, из исследований, преимущественно ориентированных на взаимодействие ДНК-ДНК с исследованиями +направленных на выяснение триплексов ДНК-РНК и РНК-РНК. Сейчас важно сосредоточиться на +как эти структуры распознаются, используются функционально и обрабатываются в ячейках. + +libboost_iostreams.so.1.58.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.58.0 +\nlibboost_iostreams.so.1.58.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.58.0 diff --git a/test/pom.xml b/test/pom.xml new file mode 100644 index 0000000..1a3e641 --- /dev/null +++ b/test/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + test + test + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + junit + junit + 4.12 + + + + + \ No newline at end of file diff --git a/test/src/main/java/ru/spbau/mit/alyokhina/Hasher.java b/test/src/main/java/ru/spbau/mit/alyokhina/Hasher.java new file mode 100644 index 0000000..a7ee243 --- /dev/null +++ b/test/src/main/java/ru/spbau/mit/alyokhina/Hasher.java @@ -0,0 +1,105 @@ +package ru.spbau.mit.alyokhina; + +import java.io.*; +import java.nio.file.Path; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.function.BiConsumer; + + +public class Hasher { + + public Md5 getMd5(Path path) throws NoSuchAlgorithmException, IOException { + MessageDigest messageDigest; + messageDigest = MessageDigest.getInstance("MD5"); + update(messageDigest, path.toFile(), new BiConsumer() { + @Override + public void accept(MessageDigest message, File file) { + try { + update(message, file, this); + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + }); + return new Md5(messageDigest.digest()); + } + + + private static void update(MessageDigest message, File file, BiConsumer action) throws IOException { + if (file.isFile()) { + try (FileInputStream stream = new FileInputStream(file)) { + int sizeBuffer = 2048; + byte[] buffer = new byte[sizeBuffer]; + try (BufferedInputStream bufferedStream = new BufferedInputStream(stream)) { + while (true) { + int bytesRead = bufferedStream.read(buffer, 0, sizeBuffer); + if (bytesRead == -1) { + break; + } + message.update(buffer, 0, bytesRead); + } + } + } + return; + } + File[] files = file.listFiles(); + message.update(file.getName().getBytes()); + assert files != null; + for (File file1 : files) { + action.accept(message, file1); + } + } + + + public Md5 getMd5forThreads(Path path) { + ForkJoinPool pool = new ForkJoinPool(); + return pool.invoke(new Task(path.toFile())); + } + + + public class Task extends RecursiveTask { + MessageDigest message; + File file; + + private Task(File file) { + try { + this.message = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + System.out.println(e.getMessage()); + } + this.file = file; + } + + @Override + protected Md5 compute() { + final List> taskList = new ArrayList<>(); + + try { + update(message, file, (messageDigest, file) -> { + Task task = new Task(file); + task.fork(); + taskList.add(task); + } + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + + for (ForkJoinTask task : taskList) { + message.update(task.join().get()); + } + + return new Md5(message.digest()); + } + } + + +} + + diff --git a/test/src/main/java/ru/spbau/mit/alyokhina/Main.java b/test/src/main/java/ru/spbau/mit/alyokhina/Main.java new file mode 100644 index 0000000..46125aa --- /dev/null +++ b/test/src/main/java/ru/spbau/mit/alyokhina/Main.java @@ -0,0 +1,22 @@ +package ru.spbau.mit.alyokhina; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; + +public class Main { + public static void main(String[] args) throws IOException, NoSuchAlgorithmException { + Path path = Paths.get(args[0]); + Hasher hasher = new Hasher(); + long startTime1 = System.currentTimeMillis(); + Md5 hash1 = hasher.getMd5(path); + long endTime1 = System.currentTimeMillis(); + long startTime2 = System.currentTimeMillis(); + Md5 hash2 = hasher.getMd5forThreads(path); + long endTime2 = System.currentTimeMillis(); + System.out.println( endTime1 - startTime1); + System.out.println(endTime2 - startTime2); + + } +} diff --git a/test/src/main/java/ru/spbau/mit/alyokhina/Md5.java b/test/src/main/java/ru/spbau/mit/alyokhina/Md5.java new file mode 100644 index 0000000..ec5d349 --- /dev/null +++ b/test/src/main/java/ru/spbau/mit/alyokhina/Md5.java @@ -0,0 +1,11 @@ +package ru.spbau.mit.alyokhina; + +public class Md5 { + private byte[] bytes; + public Md5(byte[] bytes) { + this.bytes = bytes; + } + public byte[] get() { + return bytes; + } +} \ No newline at end of file diff --git a/test/src/test/java/ru/spbau/mit/alyokhina/HasherTest.java b/test/src/test/java/ru/spbau/mit/alyokhina/HasherTest.java new file mode 100644 index 0000000..72ee3ef --- /dev/null +++ b/test/src/test/java/ru/spbau/mit/alyokhina/HasherTest.java @@ -0,0 +1,23 @@ +package ru.spbau.mit.alyokhina; + +import org.junit.Test; + +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; + +public class HasherTest { + @Test + public void testCompareGetMdt() throws Exception { + Hasher hash = new Hasher(); + Md5 hash1 = hash.getMd5(Paths.get("2.txt")); + Md5 hash2 = hash.getMd5forThreads(Paths.get("2.txt")); + byte[] bytes1 = hash1.get(), bytes2 = hash2.get(); + assertEquals(bytes1.length, bytes2.length); + for (int i = 0; i < bytes1.length; i++) { + assertEquals(bytes1[i], bytes2[i]); + } + + } + +} \ No newline at end of file diff --git a/test/test.iml b/test/test.iml new file mode 100644 index 0000000..319f82b --- /dev/null +++ b/test/test.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file