Skip to content

Commit af90fc5

Browse files
prepare the automatic download and the automatic creation of structure for code and tests; better documentation
Took 2 hours 9 minutes
1 parent 5e80363 commit af90fc5

File tree

7 files changed

+304
-8
lines changed

7 files changed

+304
-8
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ build/
3636
.vscode/
3737

3838
### Mac OS ###
39-
.DS_Store
39+
.DS_Store
40+
/src/main/resources/cookie.txt

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ Solutions in Java for the Advent of Code in 2024
55
## Goals
66

77
1. Do not spend too much development time on a solution
8-
2. Write tests with the example input to ensure that everything works and keeps working
8+
2. Write tests with the example input to ensure that everything works and keeps working (also to test the second part)
99
3. Improve readability when writing an algorithm
10-
4. Lower down the complexity when not impacting too much the readability
10+
4. Lower down the complexity and improve the performances when not impacting too much the readability
1111
5. Try some new features of the languages or libraries when possible
1212
6. Use the [Darkyen's Time Tracker](https://plugins.jetbrains.com/plugin/9286-darkyen-s-time-tracker) to inject the time spend of each puzzle`
1313

14+
## Automatic tool
15+
16+
This year I create an automation to quickly setup the environment; the script download the daily input to the `test/resources` folder, it prepares the initial Java code for the main algorithm and it prepares the tests to run the algorithm with the proper input. The code is in [DaySetup.java](src/main/aminetti/adventofcode2024/DaySetup.java) and it uses [DayXX.java](src/main/aminetti/adventofcode2024/dayXX/DayXX.java) and [DayXXTest.java](src/test/aminetti/adventofcode2024/dayXX/DayXXTest.java) as templates for the main code and the tests.

pom.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@
2020
<artifactId>commons-io</artifactId>
2121
<version>2.18.0</version>
2222
</dependency>
23-
<dependency>
24-
<groupId>org.apache.commons</groupId>
25-
<artifactId>commons-lang3</artifactId>
26-
<version>3.17.0</version>
27-
</dependency>
2823
<dependency>
2924
<groupId>org.apache.commons</groupId>
3025
<artifactId>commons-text</artifactId>
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package aminetti.adventofcode2024;
2+
3+
import org.apache.commons.io.IOUtils;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import java.io.IOException;
8+
import java.net.CookieHandler;
9+
import java.net.CookieManager;
10+
import java.net.HttpCookie;
11+
import java.net.URI;
12+
import java.net.http.HttpClient;
13+
import java.net.http.HttpRequest;
14+
import java.net.http.HttpResponse;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.nio.file.Paths;
18+
import java.time.Duration;
19+
import java.time.LocalDate;
20+
import java.time.Month;
21+
import java.util.regex.Matcher;
22+
import java.util.regex.Pattern;
23+
24+
import static java.nio.charset.StandardCharsets.UTF_8;
25+
import static java.nio.file.StandardOpenOption.*;
26+
27+
public class DaySetup {
28+
private static final Logger LOGGER = LoggerFactory.getLogger(DaySetup.class);
29+
30+
public static void main(String... args) throws IOException, InterruptedException {
31+
prepareCookie();
32+
33+
int year = LocalDate.now().getYear();
34+
int day = getCurrentDay();
35+
36+
cleanCodeAndTestAndInputForDay(year, day);
37+
38+
downloadDayInput(year, day);
39+
prepareCodeForDay(year, day);
40+
prepareTestsForDay(year, day);
41+
42+
}
43+
44+
static void cleanCodeAndTestAndInputForDay(int year, int day) throws IOException, InterruptedException {
45+
String basePackageName = String.format("adventofcode%d", year);
46+
String packageName = String.format("day%02d", day);
47+
48+
String testClassName = String.format("Day%02dTest", day);
49+
Path testClassPath = Paths.get("src", "test", "java", "aminetti", basePackageName, packageName, testClassName + ".java");
50+
Files.deleteIfExists(testClassPath);
51+
52+
53+
String className = String.format("Day%02d", day);
54+
Path classPath = Paths.get("src", "test", "java", "aminetti", basePackageName, packageName, className + ".java");
55+
Files.deleteIfExists(classPath);
56+
57+
String folderName = String.format("day%02d", day);
58+
String fileName = String.format("day%02d_input.txt", day);
59+
Path inputFile = Paths.get("src", "test", "resources", folderName, fileName);
60+
Files.deleteIfExists(inputFile);
61+
62+
String testFileName = String.format("day%02d_input_test.txt", day);
63+
Path testInputFile = Paths.get("src", "test", "resources", folderName, testFileName);
64+
Files.deleteIfExists(testInputFile);
65+
66+
LOGGER.info("All the files related to day {} has been deleted.", day);
67+
68+
}
69+
70+
static String getInput(int year, int day) throws IOException, InterruptedException {
71+
URI uri = URI.create(String.format("https://adventofcode.com/%d/day/%d/input", year, day));
72+
73+
HttpRequest req = HttpRequest.newBuilder()
74+
.uri(uri)
75+
.header("User-Agent", "github.com/albertominetti/")
76+
.GET().build();
77+
78+
try (HttpClient client = HttpClient.newBuilder()
79+
.cookieHandler(CookieHandler.getDefault())
80+
.version(HttpClient.Version.HTTP_2)
81+
.connectTimeout(Duration.ofSeconds(10))
82+
.build()) {
83+
return client.send(req, HttpResponse.BodyHandlers.ofString()).body();
84+
}
85+
}
86+
87+
static void prepareCookie() throws IOException {
88+
CookieManager cookieManager = new CookieManager();
89+
String textCookie = IOUtils.resourceToString("/cookie.txt", UTF_8);
90+
if (textCookie == null) {
91+
throw new IllegalArgumentException("Missing cookie file, please check your cookie.txt file in the resource directory.");
92+
}
93+
Pattern patternForCookie = Pattern.compile("session=([a-f0-9]+)");
94+
Matcher matcher = patternForCookie.matcher(textCookie);
95+
if (matcher.matches()) {
96+
HttpCookie sessionCookie = new HttpCookie("session", matcher.group(1));
97+
sessionCookie.setPath("/");
98+
sessionCookie.setVersion(0);
99+
cookieManager.getCookieStore()
100+
.add(URI.create("https://adventofcode.com"), sessionCookie);
101+
} else {
102+
throw new IllegalArgumentException("Invalid cookie format, please check your cookie.txt file.");
103+
}
104+
105+
CookieHandler.setDefault(cookieManager);
106+
}
107+
108+
109+
static void prepareTestsForDay(int year, int day) throws IOException, InterruptedException {
110+
String basePackageName = String.format("adventofcode%d", year);
111+
String packageName = String.format("day%02d", day);
112+
String testClassName = String.format("Day%02dTest", day);
113+
114+
Path testClassPath = Paths.get("src", "test", "java", "aminetti", basePackageName, packageName, testClassName + ".java");
115+
Path templateClassPath = Paths.get("src", "test", "java", "aminetti", "adventofcode2024", "dayXX", "DayXXTest.java");
116+
117+
if (Files.exists(testClassPath)) {
118+
LOGGER.warn("The test class file {} is already existent.", testClassPath.toAbsolutePath());
119+
return;
120+
}
121+
122+
Files.createDirectories(testClassPath.getParent());
123+
String templateClassContent = Files.readString(templateClassPath);
124+
125+
126+
String className = String.format("Day%02d", day);
127+
String classContent = templateClassContent
128+
.replaceAll("adventofcode[0-9]+", basePackageName)
129+
.replace("DayXX", className)
130+
.replace("DayXXTest", testClassName)
131+
.replaceAll("dayXX", packageName);
132+
Files.writeString(testClassPath, classContent, WRITE, TRUNCATE_EXISTING, CREATE);
133+
134+
LOGGER.info("The test java source file {} has been created.", testClassPath.toAbsolutePath());
135+
136+
}
137+
138+
static void prepareCodeForDay(int year, int day) throws IOException, InterruptedException {
139+
String basePackageName = String.format("adventofcode%d", year);
140+
String packageName = String.format("day%02d", day);
141+
String className = String.format("Day%02d", day);
142+
143+
Path classPath = Paths.get("src", "main", "java", "aminetti", basePackageName, packageName, className + ".java");
144+
Path templateClassPath = Paths.get("src", "main", "java", "aminetti", "adventofcode2024", "dayXX", "DayXX.java");
145+
146+
if (Files.exists(classPath)) {
147+
LOGGER.warn("The class file {} is already existent.", classPath.toAbsolutePath());
148+
return;
149+
}
150+
151+
Files.createDirectories(classPath.getParent());
152+
String templateClassContent = Files.readString(templateClassPath);
153+
String classContent = templateClassContent
154+
.replaceAll("adventofcode[0-9]+", basePackageName)
155+
.replace("DayXX", className)
156+
.replaceAll("dayXX", packageName);
157+
Files.writeString(classPath, classContent, WRITE, TRUNCATE_EXISTING, CREATE);
158+
159+
LOGGER.info("The java source file {} has been created.", classPath.toAbsolutePath());
160+
161+
}
162+
163+
164+
static void downloadDayInput(int year, int day) throws IOException, InterruptedException {
165+
String folderName = String.format("day%02d", day);
166+
String fileName = String.format("day%02d_input.txt", day);
167+
Path path = Paths.get("src", "test", "resources", folderName, fileName);
168+
169+
if (Files.exists(path)) {
170+
LOGGER.warn("The input file {} is already existent.", path.toAbsolutePath());
171+
return;
172+
}
173+
174+
Files.createDirectories(path.getParent());
175+
Path testInput = path.getParent().resolve(String.format("day%02d_input_test.txt", day));
176+
Files.createFile(testInput);
177+
LOGGER.info("The input file {} has been created.", testInput.toAbsolutePath());
178+
179+
String dayInput = getInput(year, day);
180+
Files.writeString(path, dayInput, WRITE, TRUNCATE_EXISTING, CREATE);
181+
LOGGER.info("The input file {} has been created.", path.toAbsolutePath());
182+
}
183+
184+
static int getCurrentDay() {
185+
LocalDate now = LocalDate.now();
186+
if (now.getMonth() != Month.DECEMBER) {
187+
throw new IllegalArgumentException("It is still not December.");
188+
}
189+
190+
return now.getDayOfMonth();
191+
}
192+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package aminetti.adventofcode2024.dayXX;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.util.List;
7+
8+
public class DayXX {
9+
private static final Logger LOGGER = LoggerFactory.getLogger(DayXX.class);
10+
private List<String> input;
11+
12+
public DayXX() {
13+
}
14+
15+
public void parseInput(List<String> input) {
16+
this.input = input;
17+
18+
for (String s : input) {
19+
20+
}
21+
}
22+
23+
public long solvePart1() {
24+
25+
return 0;
26+
}
27+
28+
public long solvePart2() {
29+
30+
return 0;
31+
}
32+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package aminetti.adventofcode2024.dayXX;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.io.IOException;
6+
import java.util.List;
7+
8+
import static java.nio.charset.StandardCharsets.UTF_8;
9+
import static org.apache.commons.io.IOUtils.readLines;
10+
import static org.apache.commons.io.IOUtils.resourceToString;
11+
import static org.hamcrest.MatcherAssert.assertThat;
12+
import static org.hamcrest.Matchers.is;
13+
14+
class DayXXTest {
15+
16+
@Test
17+
void actualInputPart1() throws IOException {
18+
// given
19+
List<String> input = readLines(resourceToString("/dayXX/dayXX_input.txt", UTF_8));
20+
21+
// when
22+
DayXX solver = new DayXX();
23+
solver.parseInput(input);
24+
long l = solver.solvePart1();
25+
26+
// then
27+
assertThat(l, is(0L));
28+
}
29+
30+
@Test
31+
void testInputPart1() throws IOException {
32+
// given
33+
List<String> input = readLines(resourceToString("/dayXX/dayXX_input_test.txt", UTF_8));
34+
35+
// when
36+
DayXX solver = new DayXX();
37+
solver.parseInput(input);
38+
long l = solver.solvePart1();
39+
40+
// then
41+
assertThat(l, is(0L));
42+
}
43+
44+
@Test
45+
void actualInputPart2() throws IOException {
46+
// given
47+
List<String> input = readLines(resourceToString("/dayXX/dayXX_input.txt", UTF_8));
48+
49+
// when
50+
DayXX solver = new DayXX();
51+
solver.parseInput(input);
52+
long l = solver.solvePart2();
53+
54+
// then
55+
assertThat(l, is(0L));
56+
}
57+
58+
@Test
59+
void testInputPart2() throws IOException {
60+
// given
61+
List<String> input = readLines(resourceToString("/dayXX/dayXX_input_test.txt", UTF_8));
62+
63+
// when
64+
DayXX solver = new DayXX();
65+
solver.parseInput(input);
66+
long l = solver.solvePart2();
67+
68+
// then
69+
assertThat(l, is(0L));
70+
}
71+
72+
73+
}

src/test/resources/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)