aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/build/packages/adglent/src/priv
diff options
context:
space:
mode:
authorHJ <thechairman@thechairman.info>2024-02-03 15:09:54 -0500
committerHJ <thechairman@thechairman.info>2024-02-03 15:09:54 -0500
commit96a3c5c179d8d3fff24eb2953e45f8dd15e2714c (patch)
tree0a67bc0cfeabe51740bb049c61f16f1ac3bdd4ff /aoc2023/build/packages/adglent/src/priv
parent547fe03cf43105f46160e2dd9afff21637eaaf47 (diff)
downloadgleam_aoc-96a3c5c179d8d3fff24eb2953e45f8dd15e2714c.tar.gz
gleam_aoc-96a3c5c179d8d3fff24eb2953e45f8dd15e2714c.zip
cleanup
Diffstat (limited to 'aoc2023/build/packages/adglent/src/priv')
-rw-r--r--aoc2023/build/packages/adglent/src/priv/aoc_client.gleam37
-rw-r--r--aoc2023/build/packages/adglent/src/priv/errors.gleam54
-rw-r--r--aoc2023/build/packages/adglent/src/priv/prompt.gleam38
-rw-r--r--aoc2023/build/packages/adglent/src/priv/template.gleam18
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/solution.gleam27
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam7
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam41
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam41
-rw-r--r--aoc2023/build/packages/adglent/src/priv/toml.gleam52
9 files changed, 315 insertions, 0 deletions
diff --git a/aoc2023/build/packages/adglent/src/priv/aoc_client.gleam b/aoc2023/build/packages/adglent/src/priv/aoc_client.gleam
new file mode 100644
index 0000000..e18bafa
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/aoc_client.gleam
@@ -0,0 +1,37 @@
+import gleam/result.{try}
+import gleam/httpc
+import gleam/http/request
+import gleam/int
+import gleam/string
+
+pub fn get_input(
+ year: String,
+ day: String,
+ session: String,
+) -> Result(String, String) {
+ let url = "https://adventofcode.com/" <> year <> "/day/" <> day <> "/input"
+ use request <- try(
+ request.to(url)
+ |> result.map_error(fn(error) {
+ "Could not create request for \"" <> url <> "\": " <> string.inspect(
+ error,
+ )
+ }),
+ )
+
+ // Send the HTTP request to the server
+ use response <- try(
+ request
+ |> request.prepend_header("Accept", "application/json")
+ |> request.prepend_header("Cookie", "session=" <> session <> ";")
+ |> httpc.send
+ |> result.map_error(fn(error) {
+ "Error when requesting \"" <> url <> "\": " <> string.inspect(error)
+ }),
+ )
+
+ case response.status {
+ status if status >= 200 && status < 300 -> Ok(response.body)
+ status -> Error(int.to_string(status) <> " - " <> response.body)
+ }
+}
diff --git a/aoc2023/build/packages/adglent/src/priv/errors.gleam b/aoc2023/build/packages/adglent/src/priv/errors.gleam
new file mode 100644
index 0000000..14c35ca
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/errors.gleam
@@ -0,0 +1,54 @@
+import gleam/result
+import gleam/string
+import gleam/io
+
+pub fn map_messages(
+ result: Result(a, b),
+ success_message: String,
+ error_message: String,
+) -> Result(String, String) {
+ result
+ |> result.map_error(fn(error) {
+ "Error - " <> error_message <> ": " <> string.inspect(error)
+ })
+ |> result.replace(success_message)
+}
+
+pub fn map_error(
+ result: Result(a, b),
+ error_message: String,
+) -> Result(a, String) {
+ result
+ |> result.map_error(fn(error) {
+ error_message <> ": " <> string.inspect(error)
+ })
+}
+
+pub fn print_result(result: Result(String, String)) {
+ result
+ |> result.unwrap_both
+ |> io.println
+ result
+}
+
+pub fn print_error(result: Result(a, String)) {
+ result
+ |> result.map_error(fn(err) {
+ io.println(err)
+ err
+ })
+}
+
+pub fn assert_ok(result: Result(a, String)) {
+ let assert Ok(value) =
+ result
+ |> result.map_error(fn(err) {
+ halt(1)
+ err
+ })
+ value
+}
+
+@target(erlang)
+@external(erlang, "erlang", "halt")
+fn halt(a: Int) -> Nil
diff --git a/aoc2023/build/packages/adglent/src/priv/prompt.gleam b/aoc2023/build/packages/adglent/src/priv/prompt.gleam
new file mode 100644
index 0000000..6cee35a
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/prompt.gleam
@@ -0,0 +1,38 @@
+import gleam/result
+import gleam/string
+
+pub fn confirm(message: String, auto_accept: Bool) -> Bool {
+ auto_accept || case
+ get_line(message <> "? (Y/N): ")
+ |> result.unwrap("n")
+ |> string.trim()
+ {
+ "Y" | "y" -> True
+ _ -> False
+ }
+}
+
+pub fn value(message: String, default: String, auto_accept: Bool) -> String {
+ case get_value_of_default(message, default, auto_accept) {
+ "" -> default
+ value -> value
+ }
+}
+
+fn get_value_of_default(message: String, default: String, auto_accept: Bool) {
+ case auto_accept {
+ True -> default
+ False ->
+ get_line(message <> "? (" <> default <> "): ")
+ |> result.unwrap("")
+ |> string.trim()
+ }
+}
+
+pub type GetLineError {
+ Eof
+ NoData
+}
+
+@external(erlang, "adglent_ffi", "get_line")
+pub fn get_line(prompt prompt: String) -> Result(String, GetLineError)
diff --git a/aoc2023/build/packages/adglent/src/priv/template.gleam b/aoc2023/build/packages/adglent/src/priv/template.gleam
new file mode 100644
index 0000000..e946888
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/template.gleam
@@ -0,0 +1,18 @@
+import gleam/list
+import gleam/string
+
+pub fn render(
+ template: String,
+ substitutions: List(#(String, String)),
+) -> String {
+ substitutions
+ |> list.fold(
+ template,
+ fn(template, substitution) {
+ let #(name, value) = substitution
+ template
+ |> string.replace("{{ " <> name <> " }}", value)
+ },
+ )
+ |> string.trim <> "\n"
+}
diff --git a/aoc2023/build/packages/adglent/src/priv/templates/solution.gleam b/aoc2023/build/packages/adglent/src/priv/templates/solution.gleam
new file mode 100644
index 0000000..96085c3
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/templates/solution.gleam
@@ -0,0 +1,27 @@
+pub const template = "
+import adglent.{First, Second}
+import gleam/io
+
+pub fn part1(input: String) {
+ todo as \"Implement solution to part 1\"
+}
+
+pub fn part2(input: String) {
+ todo as \"Implement solution to part 2\"
+}
+
+pub fn main() {
+ let assert Ok(part) = adglent.get_part()
+ let assert Ok(input) = adglent.get_input(\"{{ day }}\")
+ case part {
+ First ->
+ part1(input)
+ |> adglent.inspect
+ |> io.println
+ Second ->
+ part2(input)
+ |> adglent.inspect
+ |> io.println
+ }
+}
+"
diff --git a/aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam b/aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam
new file mode 100644
index 0000000..27548d3
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam
@@ -0,0 +1,7 @@
+pub const template = "
+import showtime
+
+pub fn main() {
+ showtime.main()
+}
+"
diff --git a/aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam b/aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam
new file mode 100644
index 0000000..a1d56f6
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam
@@ -0,0 +1,41 @@
+pub const template = "
+import gleam/list
+import gleeunit/should
+import adglent.{type Example, Example}
+import day{{ day }}/solve
+
+type Problem1AnswerType =
+ String
+
+type Problem2AnswerType =
+ String
+
+/// Add examples for part 1 here:
+/// ```gleam
+///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")]
+/// ```
+const part1_examples: List(Example(Problem1AnswerType)) = []
+
+/// Add examples for part 2 here:
+/// ```gleam
+///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")]
+/// ```
+const part2_examples: List(Example(Problem2AnswerType)) = []
+
+pub fn part1_test() {
+ part1_examples
+ |> should.not_equal([])
+ use example <- list.map(part1_examples)
+ solve.part1(example.input)
+ |> should.equal(example.answer)
+}
+
+pub fn part2_test() {
+ part2_examples
+ |> should.not_equal([])
+ use example <- list.map(part2_examples)
+ solve.part2(example.input)
+ |> should.equal(example.answer)
+}
+
+"
diff --git a/aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam b/aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam
new file mode 100644
index 0000000..699feb2
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam
@@ -0,0 +1,41 @@
+pub const template = "
+import gleam/list
+import showtime/tests/should
+import adglent.{type Example, Example}
+import day{{ day }}/solve
+
+type Problem1AnswerType =
+ String
+
+type Problem2AnswerType =
+ String
+
+/// Add examples for part 1 here:
+/// ```gleam
+///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")]
+/// ```
+const part1_examples: List(Example(Problem1AnswerType)) = []
+
+/// Add examples for part 2 here:
+/// ```gleam
+///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")]
+/// ```
+const part2_examples: List(Example(Problem2AnswerType)) = []
+
+pub fn part1_test() {
+ part1_examples
+ |> should.not_equal([])
+ use example <- list.map(part1_examples)
+ solve.part1(example.input)
+ |> should.equal(example.answer)
+}
+
+pub fn part2_test() {
+ part2_examples
+ |> should.not_equal([])
+ use example <- list.map(part2_examples)
+ solve.part2(example.input)
+ |> should.equal(example.answer)
+}
+
+"
diff --git a/aoc2023/build/packages/adglent/src/priv/toml.gleam b/aoc2023/build/packages/adglent/src/priv/toml.gleam
new file mode 100644
index 0000000..7042833
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/priv/toml.gleam
@@ -0,0 +1,52 @@
+import tom
+import gleam/result
+
+pub type TomError {
+ TomParseError(error: tom.ParseError)
+ TomGetError(error: tom.GetError)
+}
+
+pub fn get_string(
+ toml_content: String,
+ key_path: List(String),
+) -> Result(String, TomError) {
+ use toml <- result.try(
+ tom.parse(toml_content <> "\n")
+ |> result.map_error(TomParseError),
+ )
+ use value <- result.try(
+ tom.get_string(toml, key_path)
+ |> result.map_error(TomGetError),
+ )
+ Ok(value)
+}
+
+pub fn get_bool(
+ toml_content: String,
+ key_path: List(String),
+) -> Result(Bool, TomError) {
+ use toml <- result.try(
+ tom.parse(toml_content <> "\n")
+ |> result.map_error(TomParseError),
+ )
+ use value <- result.try(
+ tom.get_bool(toml, key_path)
+ |> result.map_error(TomGetError),
+ )
+ Ok(value)
+}
+
+pub fn get_int(
+ toml_content: String,
+ key_path: List(String),
+) -> Result(Int, TomError) {
+ use toml <- result.try(
+ tom.parse(toml_content <> "\n")
+ |> result.map_error(TomParseError),
+ )
+ use value <- result.try(
+ tom.get_int(toml, key_path)
+ |> result.map_error(TomGetError),
+ )
+ Ok(value)
+}