Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,47 @@ CodeKiller777

## Автор решения

Стукен Виталий Андреевич

## Описание реализации

1. **Чтение файла с коммитами:** Программа начинается с чтения файла, который содержит информацию о коммитах. Это выполняется с помощью объекта BufferedReader, который читает файл построчно.
2. **Анализ коммитов:** Для каждой строки в файле программа извлекает имя автора коммита с помощью метода getAuthorFromLine(). Затем она подсчитывает количество коммитов для каждого автора, используя HashMap. Если автор уже есть в HashMap, увеличивается количество его коммитов; в противном случае автор добавляется в HashMap с начальным значением 1.
3. **Определение топ-3 авторов:** После анализа всех коммитов программа использует метод getTopAuthors(), который сортирует авторов по количеству их коммитов в порядке убывания и выбирает топ-3 авторов.
4. **Запись результатов в файл:** Наконец, топ-3 авторов записываются в другой файл с помощью метода writeAuthorsToFile(). Это делается с использованием объекта BufferedWriter, который записывает каждое имя автора в отдельной строке файла.

## Инструкция по сборке и запуску решения

### 1. Установите Java и Maven

Убедитесь, что на вашем компьютере установлены Java(19 или новее) и Maven. Вы можете проверить их наличие, выполнив следующие команды в терминале или командной строке:

```bash
java -version
mvn -version
```

### 2. Клонируйте репозиторий

```bash
git clone https://github.com/stukenvitalii/school2024-test-task4.git
```

### 3. Перейдите в директорию проекта

```bash
cd путь_к_директории_проекта
```

### 4. Сборка проекта
Выполните следующую команду Maven для сборки проекта:

```bash
mvn clean install
```

### 5. Запуск приложения
После успешной сборки вы можете запустить ваше приложение с помощью команды:
```bash
java -jar target/CROC-1.0-SNAPSHOT.jar
```
34 changes: 34 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>CROC</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>

</project>
95 changes: 95 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class Main {
private final static String fileIn = "src/main/resources/commits.txt";
private final static String fileOut = "src/main/resources/result.txt";
private final static Logger logger = Logger.getLogger(Main.class.getName());

public static void main(String[] args) {
try {
// Читаем данные из файла и записываем в Map
Map<String, Integer> authorCommitsMap = readDataAndGetFilledMap();

// Получаем топ-3 авторов по количеству коммитов
List<String> topAuthors = getTopAuthors(authorCommitsMap);

// Записываем топ-3 авторов в файл
writeAuthorsToFile(topAuthors);
} catch (IOException e) {
logger.warning(e.getMessage());
}
}

private static Map<String, Integer> readDataAndGetFilledMap() throws IOException {
HashMap<String, Integer> authorCommitsMap = new HashMap<>();
try (BufferedReader bf = new BufferedReader(new FileReader(fileIn))) {
String line = bf.readLine();
// Читаем файл построчно
while (line != null) {
// Получаем автора коммита из строки
String author = getAuthorFromLine(line);

// если не удалось получить автора из строки, то переходим к след. строке
if (author == null) {
line = bf.readLine();
continue;
}

// Проверяем, содержится ли уже автор в HashMap
if (authorCommitsMap.containsKey(author)) {
// Если автор уже есть, увеличиваем количество его коммитов на 1
authorCommitsMap.put(author, authorCommitsMap.get(author) + 1);
} else {
// Если автора еще нет, добавляем его в HashMap и устанавливаем количество его коммитов как 1
authorCommitsMap.put(author, 1);
}
line = bf.readLine(); // Читаем следующую строку
}
}
logger.info("Successfully read data from file");
return authorCommitsMap;
}

// Метод для получения топ-3 авторов по количеству коммитов
private static List<String> getTopAuthors(Map<String, Integer> authorCommitsMap) {
return authorCommitsMap
.entrySet()
.stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed()) // Сортируем по убыванию количества коммитов
.limit(3) // Ограничиваем топ-3 авторами
.map(Map.Entry::getKey) // Получаем только имена авторов
.collect(Collectors.toList()); // Собираем результат в список
}

// Метод для записи авторов в файл
private static void writeAuthorsToFile(List<String> keys) throws IOException {
try (BufferedWriter br = new BufferedWriter(new FileWriter(fileOut))) {
for (String s : keys) {
String line = s + "\n"; // Формируем строку для записи
br.write(line); // Записываем строку в файл
}
}
logger.info("Successfully written to file");
}

// Метод для извлечения имени автора из строки коммита
private static String getAuthorFromLine(String line) {
String[] tokens = line.split(" ");
if (
Validator.isValidAuthor(tokens[0]) // проверка имени автора
&& Validator.isValidHash(tokens[1]) // проверка хэша
&& Validator.isValidDate(tokens[2]) // проверка даты
&& Validator.isValidDateBounds(tokens[2]) // проверка принадлежности даты к спринту
) {
return line.split(" ")[0]; // Получаем автора, если все проверки прошли
}
logger.warning("Wrong data in line: " + line);
return null;
}

}
34 changes: 34 additions & 0 deletions src/main/java/Validator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public abstract class Validator {
public static boolean isValidAuthor(String username) {
/*
имя пользователя может содержать латинские символы
в любом регистре, цифры (но не начинаться с них), а также символ "_";
*/
return username.matches("[a-zA-Z_][a-zA-Z0-9_]*");
}

public static boolean isValidHash(String commitHash) {
/*
сокращенный хэш коммита представляет из себя строку в нижнем регистре,
состояющую из 7 символов: букв латинского алфавита, а также цифр;
*/
return commitHash.matches("[a-z0-9]{7}");
}

public static boolean isValidDate(String dateTime) {
// дата и время коммита в формате YYYY-MM-ddTHH:mm:ss.
String regex = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d+";
return dateTime.matches(regex);
}

public static boolean isValidDateBounds(String dateTime) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDateTime commitDateTime = LocalDateTime.parse(dateTime, formatter);
LocalDateTime sprintEnd = LocalDateTime.now().minusDays(1); // Учитываем, что проверка происходит на следующий день после спринта
LocalDateTime sprintStart = sprintEnd.minusDays(28); // Длительность спринта - 28 дней
return commitDateTime.isAfter(sprintStart) && commitDateTime.isBefore(sprintEnd);
}
}
38 changes: 38 additions & 0 deletions src/main/resources/commits.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
AIvanov 25ec001 2024-04-24T13:56:39.492
BSmith 35fd002 2024-04-24T14:02:18.641
AJohnson 40gh003 2024-04-24T14:08:47.790
CPetrov 15ab004 2024-04-24T14:15:16.939
AIvanov 25ec005 2024-04-24T14:21:46.088
BSmith 35fd006 2024-04-24T14:28:15.237
AJohnson 40gh007 2024-04-24T14:34:44.386
CPetrov 15ab008 2024-04-24T14:41:13.535
AIvanov 25ec009 2024-04-24T14:47:42.684
BSmith 35fd010 2024-04-24T14:54:11.833
AJohnson 40gh011 2024-04-24T15:00:40.982
CPetrov 15ab012 2024-04-24T15:07:10.131
AIvanov 25ec013 2024-04-24T15:13:39.280
BSmith 35fd014 2024-04-24T15:20:08.429
AJohnson 40gh015 2024-04-24T15:26:37.578
CPetrov 15ab016 2024-04-24T15:33:06.727
AIvanov 25ec017 2024-04-24T15:39:35.876
BSmith 35fd018 2024-04-24T15:46:05.025
AJohnson 40gh019 2024-04-24T15:52:34.174
CPetrov 15ab020 2024-04-24T15:59:03.323
AIvanov 25ec021 2024-04-24T16:05:32.472
BSmith 35fd022 2024-04-24T16:12:01.621
CPetrov 15ab024 2024-04-24T16:24:59.919
AIvanov 25ec025 2024-04-24T16:31:29.068
CPetrov 15ab004 2024-04-24T14:15:16.939
AIvanov 25ec005 2024-04-24T14:21:46.088
BSmith 35fd006 2024-04-24T14:28:15.237
CPetrov 15ab008 2024-04-24T14:41:13.535
AIvanov 25ec009 2024-04-24T14:47:42.684
BSmith 35fd010 2024-04-24T14:54:11.833
AJohnson 40gh011 2024-04-24T15:00:40.982
CPetrov 15ab012 2024-04-24T15:07:10.131
BSmith 35fd014 2024-04-24T15:20:08.429
AJohnson 40gh015 2024-04-24T15:26:37.578
CPetrov 15ab016 2024-04-24T15:33:06.727
CPetrov 15ab012 2024-04-24T15:07:10.131
BSmith 35fd014 2024-04-24T15:20:08.429
BSmith 35fd014 2024-04-24T15:20:08.429
3 changes: 3 additions & 0 deletions src/main/resources/result.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BSmith
CPetrov
AIvanov