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
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,31 @@ CodeKiller777
Ручной ввод пути к файлу (через консоль, через правку переменной в коде и т.д.) недопустим. Необходимость любых ручных действий с файлами в процессе работы программы будут обнулять решение.

## Автор решения
Линт Артем Дмитриевич

## Описание реализации
### Работа с файловой системой:
Работа с файловой системой реализована через классы из пакета fileOperations:
- FileOperator - абстрактный, содержит путь до файла проперти (settings.txt) и метод получения из него путей до файлов ввода и вывода
- CommitReader extends FileOperator, считывает из файла ввода данные о коммитах в ArrayList коммитов
- ContributorWriter extends FileOperator, записывает победителей конкурса в файл вывода из ArrayList с именами победителей
### Работа с данными:
Работа с данными реализована через классы из пакета dataOperations:
- Commit - record, контейнер для данных из записи о коммите (name, hash, dTime)
- validation.Validator - содержится в подпакете validation, проверяет данные коммита на соответствие требованиям и банальной логике
- sorting.CommitSorter - содержится в подпакете sorting, сортирует входные данные и выдает на выход ArrayList с number_of_winners именами победителей
### Ресурсы:
- settings.txt - проперти-файл, содержащий информацию о путях до файлов ввода и вывода
- commits.txt - файл ввода
- result.txt - файл вывода

## Инструкция по сборке и запуску решения
Точкой входа в процедуру является метод класса getMostHardworkingContributors, находящийся по пути src/getMostHardworkingContributors.java, public static void main(String[] args).

Файл настроек settings.txt находится в каталоге src/resources/

Настройки, заданные в файле settings.txt по-умолчанию:

Файл ввода commits.txt находится в каталоге src/resources/

Файл вывода result.txt находится в каталоге src/resources/
11 changes: 11 additions & 0 deletions croc.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
3 changes: 3 additions & 0 deletions src/dataOperations/Commit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package dataOperations;

public record Commit(String name, String hash, String dTime) {}
47 changes: 47 additions & 0 deletions src/dataOperations/sorting/CommitSorter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package dataOperations.sorting;

import dataOperations.Commit;
import dataOperations.validation.Validator;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;


public class CommitSorter {
private final static int number_of_winners = 3;
private CommitSorter(){}
//удаление невалидированных коммитов
private static void validateCommits(ArrayList<Commit> commits){
commits.removeIf(commit -> !Validator.validateCommit(commit));
}
//получение статистики по кол-ву коммитов (имя-колво)
private static HashMap<String,Integer> mapCommits(ArrayList<Commit> commits){
HashMap<String,Integer> out = new HashMap<>();
for(Commit commit: commits){
String name = commit.name();
if(out.containsKey(name)){
out.put(name, out.get(name) + 1);
}
else{
out.put(name,1);
}
}
return out;
}
private static ArrayList<String> sortContributors(HashMap<String,Integer> contributors){
ArrayList<String> out = new ArrayList<>();
contributors.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).forEach(contributor -> out.add(contributor.getKey()));
return out;
}
public static ArrayList<String> sort(ArrayList<Commit> commits){
HashMap<String,Integer> contributors = mapCommits(commits);
ArrayList<String> out = sortContributors(contributors);
if (out.size() < number_of_winners){
System.out.println("Only " + out.size() + " contributors!");
System.exit(-1);
}
return new ArrayList<>(out.subList(0, number_of_winners));
}
}
49 changes: 49 additions & 0 deletions src/dataOperations/validation/Validator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package dataOperations.validation;

import dataOperations.Commit;

import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.regex.Pattern;

public class Validator {
private Validator(){}
//регулярные выражения в соответствии требованиям
private static final Pattern name_pattern = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$");
private static final Pattern hash_pattern = Pattern.compile("^[a-z0-9]{7}$");
private static final Pattern dTime_pattern = Pattern.compile("\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}\\\\.\\\\d{0,9}");

private static boolean validateName(String name){
if(name.isEmpty()){
return false;
}
return name_pattern.matcher(name).matches();
}
private static boolean validateHash(String hash){
if(hash.isEmpty()){
return false;
}
return hash_pattern.matcher(hash).matches();
}
//проверка соответствия логике времени и даты (не более 60 минут, и т.д)
private static boolean checkDTime(String dTime){
String[] split = dTime.split("[.\\-T:]");
int[] dTimeNumbers = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();
try{
LocalDateTime.of(dTimeNumbers[0],dTimeNumbers[1],dTimeNumbers[2],dTimeNumbers[3],dTimeNumbers[4],dTimeNumbers[5],dTimeNumbers[6]);
} catch (DateTimeException e){
return false;
}
return true;
}
private static boolean validateDTime(String dTime){
if(dTime.isEmpty()){
return false;
}
return dTime_pattern.matcher(dTime).matches() && checkDTime(dTime);
}
public static boolean validateCommit(Commit commit){
return validateDTime(commit.dTime()) && validateHash(commit.hash()) && validateName(commit.name());
}
}
28 changes: 28 additions & 0 deletions src/fileOperations/CommitReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package fileOperations;

import dataOperations.Commit;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Scanner;

public class CommitReader extends FileOperator{
private CommitReader(){}
public static ArrayList<Commit> read(){
ArrayList<Commit> out = new ArrayList<>();
try(Scanner fstream = new Scanner(new File(readPathByKey("inputPath")))){
while(fstream.hasNextLine()){
String[] split = fstream.nextLine().split(" ");
out.add(new Commit(split[0], split[1], split[2]));
}
}catch(IOException e){
System.out.println("No such input file found");
System.exit(-111);
}
return out;
}

}
23 changes: 23 additions & 0 deletions src/fileOperations/ContrubutorsWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package fileOperations;

import dataOperations.Commit;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ContrubutorsWriter extends FileOperator {
private ContrubutorsWriter(){}
public static void write(ArrayList<String> contributors){
String path = readPathByKey("outputPath");
try(FileWriter wr = new FileWriter(path, false)){
for(String contributor: contributors){
wr.write(contributor+"\n");
}
wr.flush();
} catch (IOException e){
System.out.println("Output file IO error");
System.exit(-112);
}
}
}
19 changes: 19 additions & 0 deletions src/fileOperations/FileOperator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fileOperations;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public abstract class FileOperator {
protected static final String settings_path = "src/resources/settings.txt";
protected static String readPathByKey(String key){
Properties settings = new Properties();
try(FileInputStream fstream = new FileInputStream(settings_path)){
settings.load(fstream);
} catch (IOException e){
System.out.println("Settings file not found");
System.exit(-110);
}
return settings.getProperty(key);
}
}
17 changes: 17 additions & 0 deletions src/getMostHardworkingContributors.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import dataOperations.Commit;
import dataOperations.sorting.CommitSorter;
import fileOperations.CommitReader;
import fileOperations.ContrubutorsWriter;

import java.util.ArrayList;

public class getMostHardworkingContributors {
public static void main(String[] args) {
//считываем информацию о коммитах по пути из settings.txt
ArrayList<Commit> commits = CommitReader.read();
//находим победителей
ArrayList<String> sorted = CommitSorter.sort(commits);
//записываем в файл по пути из settings.txt
ContrubutorsWriter.write(sorted);
}
}
14 changes: 14 additions & 0 deletions src/resources/commits.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
AIvanov 25ec001 2023-05-24T12:24:49.5425
AIvanov 25ec001 2024-01-22T23:04:03.44223
AIvanov 25ec001 2024-04-24T13:56:39.492
CBeast 8baffc3 2024-04-26T15:42:05.678
CodeMaster1337 534ker1 2022-01-20T23:34:53.421411
AIvanov 25ec001 2024-12-19T22:14:12.49
AIvanov 25ec001 2024-05-01T09:30:15.123
CKim 8baffc3 2024-05-02T11:20:30.456
EOsipov 3f8b19a 2024-05-03T13:45:55.789
EOsipov 7cfe69a 2024-05-04T14:55:05.321
FJ b1ed29e 2024-05-05T16:10:20.654
GMoog 1d6bfac 2024-05-06T18:20:35.987
ALint 232fse1 20111-04-24T13:34:3492
ALint 979dh 2024-01-24T13:56:39.492
3 changes: 3 additions & 0 deletions src/resources/result.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
AIvanov
EOsipov
ALint
2 changes: 2 additions & 0 deletions src/resources/settings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
inputPath = src/resources/commits.txt
outputPath = src/resources/result.txt