import gleam/float import gleam/int import gleam/io import gleam/list import gleam/result import gleam/string import gleam/time/duration import gleam/time/timestamp.{type Timestamp} import gleeunit import kicad_sexpr/decode.{type Decoder, type NextFn} import kicad_sexpr/parse import kicad_sexpr/token import simplifile pub fn main() -> Nil { io.println("\nTesting Footprints") let assert Ok(footprint_files) = simplifile.get_files("/usr/share/kicad/footprints") let footprint_files = footprint_files |> list.filter(string.ends_with(_, ".kicad_mod")) // |> list.drop(0) // |> list.take(1000) // |> list.sample(1000) // let footprint_files = ["test_files/test3.kicad_mod"] test_read_parse_decode(footprint_files, token.footprint_file, True) io.println("\nTesting Symbol Libraries") let assert Ok(symbol_libraries) = simplifile.get_files("/usr/share/kicad/symbols") let symbol_libraries = symbol_libraries |> list.filter(string.ends_with(_, ".kicad_sym")) // |> list.drop(0) // |> list.take(20) // |> list.sample(20) // let symbol_libraries = ["test_files/test3.kicad_mod"] test_read_parse_decode(symbol_libraries, token.symbol_library, True) gleeunit.main() } fn time_taken_string(start_time: Timestamp, end_time: Timestamp) -> String { let #(s, us) = timestamp.difference(start_time, end_time) |> duration.to_seconds_and_nanoseconds int.to_string(int.absolute_value(s)) <> "." <> int.to_string(us / 1_000_000) <> "s" } fn print_stats( title: String, successes: Int, total: Int, num_len: Int, start_time: Timestamp, end_time: Timestamp, ) -> Nil { io.println( title <> { int.to_string(successes) |> string.pad_start(num_len, "0") } <> "/" <> { int.to_string(total) |> string.pad_start(num_len, "0") } <> " (" <> { int.to_float(100 * successes) /. int.to_float(total) |> float.to_precision(1) |> float.to_string |> string.pad_start(5, "0") |> string.append("%") } <> ") in " <> time_taken_string(start_time, end_time), ) } fn test_read_parse_decode( file_names: List(String), decoder: fn(NextFn(a, a)) -> Decoder(a), print_errors: Bool, ) -> Nil { let num_file_names = list.length(file_names) let num_file_names_str = int.to_string(num_file_names) let num_len = string.length(num_file_names_str) io.println("Total Files: " <> num_file_names_str) let time_before_read = timestamp.system_time() let #(successfully_read, failed_to_read) = file_names |> list.map(fn(file_name) { simplifile.read_bits(file_name) |> result.map(fn(res) { #(file_name, res) }) |> result.map_error(fn(res) { #(file_name, res) }) }) |> result.partition let time_after_read = timestamp.system_time() let num_successfully_read = list.length(successfully_read) print_stats( "Files Read: ", num_successfully_read, num_file_names, num_len, time_before_read, time_after_read, ) case print_errors { True -> list.each(failed_to_read, fn(data) { let #(file_name, error) = data io.println("Failed to read file: " <> file_name) echo error }) False -> Nil } let time_before_parse = timestamp.system_time() let #(successfully_parsed, failed_to_parse) = successfully_read |> list.map(fn(data) { let #(file_name, file_contents) = data parse.run(file_contents) |> result.map(fn(res) { #(file_name, file_contents, res) }) |> result.map_error(fn(res) { #(file_name, file_contents, res) }) }) |> result.partition let time_after_parse = timestamp.system_time() let num_successfully_parsed = list.length(successfully_parsed) print_stats( "Files Parsed: ", num_successfully_parsed, num_successfully_read, num_len, time_before_parse, time_after_parse, ) case print_errors { True -> list.each(failed_to_parse, fn(data) { let #(file_name, _file_contents, error) = data io.println("Failed to parse file: " <> file_name) echo error }) False -> Nil } let time_before_decode = timestamp.system_time() let #(successfully_decoded, failed_to_decode) = successfully_parsed |> list.map(fn(data) { let #(file_name, file_contents, sexpr) = data decode.run(decoder, sexpr) |> result.map(fn(res) { #(file_name, file_contents, sexpr, res) }) |> result.map_error(fn(res) { #(file_name, file_contents, sexpr, res) }) }) |> result.partition let time_after_decode = timestamp.system_time() let num_successfully_decoded = list.length(successfully_decoded) print_stats( "Files Decoded: ", num_successfully_decoded, num_successfully_parsed, num_len, time_before_decode, time_after_decode, ) case print_errors { True -> list.each(failed_to_decode, fn(data) { let #(file_name, _file_contents, _sexpr, error) = data io.println("Failed to decode file: " <> file_name) echo error }) False -> Nil } io.println( "Total Time: " <> time_taken_string(time_before_read, time_after_decode), ) }