Compare commits

..

1 Commits

Author SHA1 Message Date
Matej Janezic 00000260e7
chore(release): bump version 2023-11-17 15:59:04 +01:00
8 changed files with 332 additions and 25 deletions

158
Cargo.lock generated
View File

@ -45,7 +45,7 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]] [[package]]
name = "aoc" name = "aoc"
version = "29.0.0" version = "26.0.0"
dependencies = [ dependencies = [
"dotenvy", "dotenvy",
"elves", "elves",
@ -56,6 +56,7 @@ dependencies = [
"pico-args", "pico-args",
"regex", "regex",
"reqwest", "reqwest",
"tokio",
] ]
[[package]] [[package]]
@ -217,12 +218,6 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.25" version = "0.3.25"
@ -242,12 +237,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-io",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab",
] ]
[[package]] [[package]]
@ -466,6 +458,16 @@ version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.17"
@ -573,7 +575,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.107",
] ]
[[package]] [[package]]
@ -595,6 +597,29 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys 0.42.0",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.2.0" version = "2.2.0"
@ -750,6 +775,12 @@ dependencies = [
"windows-sys 0.36.1", "windows-sys 0.36.1",
] ]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.7.0" version = "2.7.0"
@ -802,6 +833,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.7" version = "0.4.7"
@ -811,6 +851,12 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.7" version = "0.4.7"
@ -842,6 +888,17 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "system-configuration" name = "system-configuration"
version = "0.5.1" version = "0.5.1"
@ -903,11 +960,25 @@ dependencies = [
"libc", "libc",
"mio", "mio",
"num_cpus", "num_cpus",
"parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry",
"socket2 0.5.5", "socket2 0.5.5",
"tokio-macros",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]] [[package]]
name = "tokio-native-tls" name = "tokio-native-tls"
version = "0.3.0" version = "0.3.0"
@ -1045,7 +1116,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.107",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1079,7 +1150,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.107",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1135,6 +1206,21 @@ dependencies = [
"windows_x86_64_msvc 0.36.1", "windows_x86_64_msvc 0.36.1",
] ]
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm 0.42.0",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_x86_64_gnullvm 0.42.0",
"windows_x86_64_msvc 0.42.0",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"
@ -1150,15 +1236,21 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5", "windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5", "windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5", "windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5", "windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm", "windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5", "windows_x86_64_msvc 0.48.5",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.48.5" version = "0.48.5"
@ -1171,6 +1263,12 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.5" version = "0.48.5"
@ -1183,6 +1281,12 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.5" version = "0.48.5"
@ -1195,6 +1299,12 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.5" version = "0.48.5"
@ -1207,12 +1317,24 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.5" version = "0.48.5"
@ -1225,6 +1347,12 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"

View File

@ -2,11 +2,12 @@
name = "aoc" name = "aoc"
description = "template for advent of code" description = "template for advent of code"
readme = "README.md" readme = "README.md"
version = "29.0.0" version = "26.0.0"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
authors = ["Matej Janežič <janezic.mj@gmail.com>"] authors = ["Matej Janežič <janezic.mj@gmail.com>"]
repository = "https://github.com/janezicmatej/aoc-template.git" repository = "https://github.com/janezicmatej/aoc-template.git"
default-run = "aoc"
[dependencies] [dependencies]
dotenvy = "0.15.6" dotenvy = "0.15.6"
@ -17,4 +18,5 @@ itertools = "0.12.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
pico-args = "0.5.0" pico-args = "0.5.0"
regex = "1.10.2" regex = "1.10.2"
reqwest = { version = "0.11.22", features = ["blocking"] } reqwest = "0.11.22"
tokio = { version = "1.34.0", features = ["full"] }

View File

@ -13,12 +13,14 @@
- `examples/`: example files go here; you can push this as test are run in ci - `examples/`: example files go here; you can push this as test are run in ci
- `utils/`: utils files go here - `utils/`: utils files go here
- `lib.rs`: contains framework code - `lib.rs`: contains framework code
- `main.rs`: contains framework code
- `.env.example`: example dotenv file - `.env.example`: example dotenv file
### Cli ### Cli
- `cargo scaffold <day>`: prepare solution files for `day` - `cargo scaffold <day>`: prepare solution files for `day`
- `cargo download <day>`: download input file for `day` - `cargo download <day>`: download input file for `day`
- `cargo solve <day>`: run solution against input for `day` - `cargo solve <day>`: run solution against input for `day`
- `cargo all`: alias for run; runs solutions for all days
### dotenv ### dotenv

View File

@ -1,9 +1,9 @@
use dotenvy::dotenv; use dotenvy::dotenv;
use reqwest::blocking::Client; use reqwest::{header, Client};
use reqwest::header;
use std::{env, fs::OpenOptions, io::Write, process}; use std::{env, fs::OpenOptions, io::Write, process};
fn main() { #[tokio::main]
async fn main() {
let day: u8 = match aoc::parse_args() { let day: u8 = match aoc::parse_args() {
Ok(day) => day, Ok(day) => day,
Err(_) => { Err(_) => {
@ -30,8 +30,10 @@ fn main() {
let res = client let res = client
.get(format!("https://adventofcode.com/{year}/day/{day}/input")) .get(format!("https://adventofcode.com/{year}/day/{day}/input"))
.send() .send()
.await
.unwrap() .unwrap()
.text() .text()
.await
.unwrap(); .unwrap();
let input_path = format!("src/inputs/{day_padded}.txt"); let input_path = format!("src/inputs/{day_padded}.txt");

57
src/bin/download_all.rs Normal file
View File

@ -0,0 +1,57 @@
use dotenvy::dotenv;
use itertools::Itertools;
use reqwest::{header, Client};
use std::{env, fs::OpenOptions, io::Write, process};
#[tokio::main]
async fn main() {
dotenv().ok();
let token = env::var("TOKEN").expect("$TOKEN is not set");
let year = env::var("YEAR")
.expect("$YEAR is not set")
.parse::<u32>()
.expect("$YEAR must be a number");
let mut headers = header::HeaderMap::new();
let mut session_header = header::HeaderValue::from_str(format!("session={token}").as_str())
.expect("Error building cookie header");
session_header.set_sensitive(true);
headers.insert(header::COOKIE, session_header);
let client = Client::builder().default_headers(headers).build().unwrap();
let responses = (1..=25)
.map(|d| {
let endpoint = format!("https://adventofcode.com/{year}/day/{d}/input");
println!("{endpoint}");
client.get(endpoint).send()
})
.collect_vec()
.into_iter()
.map(|x| async { x.await.unwrap().text().await.unwrap() })
.collect_vec();
for (day, res) in (1..=25).zip(responses) {
let input_path = format!("src/inputs/{day:02}.txt");
let mut file = match OpenOptions::new()
.write(true)
.create(true)
.open(&input_path)
{
Ok(file) => file,
Err(e) => {
eprintln!("Failed to create module file: {e}");
process::exit(1);
}
};
match file.write_all(res.await.as_bytes()) {
Ok(_) => {
println!("Downloaded input file \"{}\"", &input_path);
}
Err(e) => {
eprintln!("Failed to write module contents: {e}");
process::exit(1);
}
}
}
}

View File

@ -8,7 +8,7 @@ use std::{
process, process,
}; };
const MODULE_TEMPLATE: &str = r#"pub fn part_one(input: &str) -> Option<u32> { const MODULE_TEMPLATE: &str = r###"pub fn part_one(input: &str) -> Option<u32> {
None None
} }
pub fn part_two(input: &str) -> Option<u32> { pub fn part_two(input: &str) -> Option<u32> {
@ -24,16 +24,16 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn test_part_one() { fn test_part_one() {
let input = aoc::read_file("examples", DAY); let input = aoc::read_file("examples", DAY).trim();
assert_eq!(part_one(&input), None); assert_eq!(part_one(&input), None);
} }
#[test] #[test]
fn test_part_two() { fn test_part_two() {
let input = aoc::read_file("examples", DAY); let input = aoc::read_file("examples", DAY).trim();
assert_eq!(part_two(&input), None); assert_eq!(part_two(&input), None);
} }
} }
"#; "###;
fn safe_create_file(path: &str) -> Result<File, std::io::Error> { fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
OpenOptions::new().write(true).create_new(true).open(path) OpenOptions::new().write(true).create_new(true).open(path)

View File

@ -45,10 +45,83 @@ pub fn read_file(folder: &str, day: u8) -> String {
let filepath = cwd.join("src").join(folder).join(format!("{day:02}.txt")); let filepath = cwd.join("src").join(folder).join(format!("{day:02}.txt"));
let f = fs::read_to_string(filepath); let f = fs::read_to_string(filepath);
f.expect("could not open input file").trim().to_string() f.expect("could not open input file")
}
fn parse_time(val: &str, postfix: &str) -> f64 {
val.split(postfix).next().unwrap().parse().unwrap()
} }
pub fn parse_args() -> Result<u8, pico_args::Error> { pub fn parse_args() -> Result<u8, pico_args::Error> {
let mut args = pico_args::Arguments::from_env(); let mut args = pico_args::Arguments::from_env();
args.free_from_str() args.free_from_str()
} }
pub fn parse_exec_time(output: &str) -> f64 {
output.lines().fold(0_f64, |acc, l| {
if !l.contains("elapsed:") {
acc
} else {
let timing = l.split("(elapsed: ").last().unwrap();
// use `contains` istd. of `ends_with`: string may contain ANSI escape sequences.
// for possible time formats, see: https://github.com/rust-lang/rust/blob/1.64.0/library/core/src/time.rs#L1176-L1200
if timing.contains("ns)") {
acc // range below rounding precision.
} else if timing.contains("µs)") {
acc + parse_time(timing, "µs") / 1000_f64
} else if timing.contains("ms)") {
acc + parse_time(timing, "ms")
} else if timing.contains("s)") {
acc + parse_time(timing, "s") * 1000_f64
} else {
acc
}
}
})
}
/// copied from: https://github.com/rust-lang/rust/blob/1.64.0/library/std/src/macros.rs#L328-L333
#[cfg(test)]
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => {{
let (a, b) = (&$a, &$b);
assert!(
(*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}",
*a,
*b
);
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_exec_time() {
assert_approx_eq!(
parse_exec_time(&format!(
"🎄 Part 1 🎄\n0 (elapsed: 74.13ns){ANSI_RESET}\n🎄 Part 2 🎄\n0 (elapsed: 50.00ns){ANSI_RESET}"
)),
0_f64
);
assert_approx_eq!(
parse_exec_time("🎄 Part 1 🎄\n0 (elapsed: 755µs)\n🎄 Part 2 🎄\n0 (elapsed: 700µs)"),
1.455_f64
);
assert_approx_eq!(
parse_exec_time("🎄 Part 1 🎄\n0 (elapsed: 70µs)\n🎄 Part 2 🎄\n0 (elapsed: 1.45ms)"),
1.52_f64
);
assert_approx_eq!(
parse_exec_time(
"🎄 Part 1 🎄\n0 (elapsed: 10.3s)\n🎄 Part 2 🎄\n0 (elapsed: 100.50ms)"
),
10400.50_f64
);
}
}

43
src/main.rs Normal file
View File

@ -0,0 +1,43 @@
/*
* This file contains template code.
* There is no need to edit this file unless you want to change template functionality.
*/
use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
use std::process::Command;
fn main() {
let total: f64 = (1..=25)
.map(|day| {
let day = format!("{day:02}");
let cmd = Command::new("cargo")
.args(["run", "--release", "--bin", &day])
.output()
.unwrap();
println!("----------");
println!("{ANSI_BOLD}| Day {day} |{ANSI_RESET}");
println!("----------");
let output = String::from_utf8(cmd.stdout).unwrap();
let is_empty = output.is_empty();
println!(
"{}",
if is_empty {
"Not solved."
} else {
output.trim()
}
);
if is_empty {
0_f64
} else {
aoc::parse_exec_time(&output)
}
})
.sum();
println!("{ANSI_BOLD}Total:{ANSI_RESET} {ANSI_ITALIC}{total:.2}ms{ANSI_RESET}");
}