-
Notifications
You must be signed in to change notification settings - Fork 11
Enhance CLI output formatting and logging #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,11 @@ | |
| #include <charconv> | ||
| #include <algorithm> | ||
| #include <random> | ||
| #include <atomic> | ||
|
|
||
| #include <fstream> | ||
| #include <sstream> | ||
| #include <iomanip> | ||
|
|
||
| #ifdef NO_GPU | ||
| constexpr bool no_gpu = true; | ||
|
|
@@ -82,6 +87,7 @@ struct Args { | |
| std::optional<HostService> server; | ||
| std::optional<std::string> output_file; | ||
| std::optional<int64_t> start_seed; | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment here |
||
| std::optional<int32_t> min_size; | ||
|
|
||
| bool parse(int argc, const char **const argv) { | ||
|
|
@@ -130,6 +136,7 @@ struct Args { | |
| output_file = argv[i++]; | ||
| } else if (std::strcmp("--start", arg) == 0) { | ||
| if (!parse_argument_int(argc, argv, i, start_seed, [](int64_t start_seed){ return true; }, arg)) return false; | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
| } else if (std::strcmp("--size", arg) == 0) { | ||
| if (!parse_argument_int(argc, argv, i, min_size, [](int32_t min_size){ return min_size >= 0; }, arg)) return false; | ||
| } else { | ||
|
|
@@ -171,6 +178,101 @@ uint64_t random_start_seed() { | |
| return ((uint64_t)device() << 32) + (uint64_t)device(); | ||
| } | ||
|
|
||
| namespace { | ||
|
|
||
|
|
||
| struct SearchResult { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have a struct for this, I don't see why we need another. |
||
| int64_t seed = 0; | ||
| int32_t x = 0; | ||
| int32_t z = 0; | ||
| int32_t size = 0; | ||
| }; | ||
|
|
||
| std::string join_devices(const std::vector<int> &devices) { | ||
| if (devices.empty()) { | ||
| return "(none)"; | ||
| } | ||
|
|
||
| std::string result; | ||
| for (size_t i = 0; i < devices.size(); ++i) { | ||
| if (i != 0) { | ||
| result += ", "; | ||
| } | ||
| result += std::to_string(devices[i]); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| std::string platform_name(bool large_biomes) { | ||
| return large_biomes ? "java_1_21_5_lb" : "java_1_21_5"; | ||
| } | ||
|
|
||
| std::string make_chunkbase_url(int64_t seed, int32_t x, int32_t z, bool large_biomes) { | ||
| return "https://www.chunkbase.com/apps/seed-map#seed=" + std::to_string(seed) + | ||
| "&platform=" + platform_name(large_biomes) + | ||
| "&dimension=overworld&x=" + std::to_string(x) + | ||
| "&z=" + std::to_string(z) + | ||
| "&zoom=0.125"; | ||
| } | ||
|
|
||
| std::string make_mcseedmap_url(int64_t seed, int32_t x, int32_t z, bool large_biomes) { | ||
| const std::string base = large_biomes | ||
| ? "https://mcseedmap.net/1.21.5-Java/lb/" | ||
| : "https://mcseedmap.net/1.21.5-Java/"; | ||
| return base + std::to_string(seed) + | ||
| "#x=" + std::to_string(x) + | ||
| "&z=" + std::to_string(z) + | ||
| "&l=-3"; | ||
| } | ||
|
|
||
| std::string current_finding_tag() { | ||
| if (unbound) { | ||
| return large_biomes ? "ULB" : "USB"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't useful, and it's wrong because what if you're running with |
||
| } | ||
| return large_biomes ? "LB" : "SB"; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| void write_result_line(std::FILE *file, const SearchResult &result) { | ||
| const std::string tag = current_finding_tag(); | ||
| std::fprintf(file, "%s %" PRIi64 " %" PRIi32 " %" PRIi32 " %" PRIi32 "\n", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment about the tag being wrong. |
||
| tag.c_str(), result.seed, result.x, result.z, result.size); | ||
| } | ||
|
|
||
| void print_result_card(const SearchResult &r, bool large_biomes, size_t rank = 0) { | ||
| if (rank != 0) { | ||
| std::printf("%2zu) ", rank); | ||
| } else { | ||
| std::printf("Found: "); | ||
| } | ||
| std::printf("seed=%" PRIi64 " x=%" PRIi32 " z=%" PRIi32 " size=%" PRIi32 "\n", | ||
| r.seed, r.x, r.z, r.size); | ||
| std::printf(" Chunkbase : %s\n", make_chunkbase_url(r.seed, r.x, r.z, large_biomes).c_str()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how I feel about baking in chunkbase/mcseedmap links for this. Maybe it should be a compiler option though if you did want to still have it. |
||
| std::printf(" mcseedmap : %s\n", make_mcseedmap_url(r.seed, r.x, r.z, large_biomes).c_str()); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| void print_banner(const Args &args, int threads, int32_t min_size, const std::string &output_path, uint64_t start_seed) { | ||
| std::printf("============================================================\n"); | ||
| std::printf("Minecraft Mushroom Island Search\n"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably say COMMISSION with a version number instead of the generic "Minecraft Mushroom Island Search" nobody refers to this program as. |
||
| std::printf("============================================================\n"); | ||
| std::printf("large_biomes : %s\n", large_biomes ? "true" : "false"); | ||
| std::printf("unbound : %s\n", unbound ? "true" : "false"); | ||
| std::printf("print interval : %d\n", PRINT_INTERVAL); | ||
| std::printf("GPU devices : %s\n", join_devices(args.devices).c_str()); | ||
| std::printf("finding type : %s\n", current_finding_tag().c_str()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems redundant if you're also displaying whether it's large biomes and unbound. |
||
| std::printf("CPU threads : %d\n", threads); | ||
| std::printf("min size : %" PRIi32 "\n", min_size); | ||
| std::printf("output file : %s\n", output_path.c_str()); | ||
| std::printf("start seed : %" PRIu64 "\n", start_seed); | ||
|
|
||
| std::printf("============================================================\n\n"); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| int main_inner(int argc, char **argv) { | ||
| Args args{}; | ||
| if (!args.parse(argc, const_cast<const char **const>(argv))) { | ||
|
|
@@ -179,10 +281,6 @@ int main_inner(int argc, char **argv) { | |
| } | ||
|
|
||
| const int threads = args.threads.value_or(args.client ? 0 : 1); | ||
| int32_t min_size = args.min_size.value_or(10'000'000 * (large_biomes ? 16 : 1)); | ||
| if (threads != 0) { | ||
| std::printf("min_size = %" PRIi32 "\n", min_size); | ||
| } | ||
|
|
||
| if (no_gpu && args.devices.size() != 0) { | ||
| std::fprintf(stderr, "The program was compiled without gpu support\n"); | ||
|
|
@@ -197,26 +295,30 @@ int main_inner(int argc, char **argv) { | |
| return 1; | ||
| } | ||
|
|
||
| std::printf("Hello! large_biomes = %s\nunbound: %s\nprint interval: %d\n", large_biomes ? "true" : "false", unbound ? "true" : "false", PRINT_INTERVAL); | ||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary formatting change (2 new lines) |
||
| int32_t min_size = args.min_size.value_or(6'000'000 * (large_biomes ? 16 : 1)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you change the default from 10M (160M LB) to 6M (96M LB)? |
||
| const std::string output_file_path = args.output_file ? args.output_file.value() : "output.txt"; | ||
| const uint64_t start_seed = args.start_seed.value_or(random_start_seed()); | ||
|
|
||
| std::FILE *output_file = nullptr; | ||
| if (threads != 0) { | ||
| const char *output_file_path = args.output_file ? args.output_file.value().c_str() : "output.txt"; | ||
| output_file = std::fopen(output_file_path, "a"); | ||
| output_file = std::fopen(output_file_path.c_str(), "a"); | ||
| if (output_file == nullptr) { | ||
| std::fprintf(stderr, "Could not open %s\n", output_file_path); | ||
| std::fprintf(stderr, "Could not open %s\n", output_file_path.c_str()); | ||
| return 1; | ||
| } | ||
| std::setvbuf(output_file, nullptr, _IOLBF, BUFSIZ); | ||
| std::fprintf(output_file, "\n"); | ||
| std::fflush(output_file); | ||
| } | ||
|
|
||
| print_banner(args, threads, min_size, output_file_path, start_seed); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary formatting change (new line) |
||
| GpuOutputs gpu_outputs; | ||
| CpuOutputs cpu_outputs; | ||
|
|
||
| #ifndef NO_GPU | ||
| uint64_t start_seed = args.start_seed.value_or(random_start_seed()); | ||
| std::printf("Starting from %" PRIi64 "\n", start_seed); | ||
| SeedIterator seed_range(start_seed); | ||
|
|
||
| std::vector<std::unique_ptr<GpuThread>> gpu_threads; | ||
|
|
@@ -244,26 +346,32 @@ int main_inner(int argc, char **argv) { | |
| } | ||
| #endif | ||
|
|
||
| for (size_t i = 0;; i++) { | ||
| for (size_t i = 0;; ++i) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why flip this? |
||
| if (threads != 0) { | ||
| std::lock_guard lock(cpu_outputs.mutex); | ||
| while (!cpu_outputs.queue.empty()) { | ||
| auto output = cpu_outputs.queue.front(); | ||
| cpu_outputs.queue.pop(); | ||
| std::printf("%" PRIi64 " at %" PRIi32 " %" PRIi32 " with %" PRIi32 "\n", output.seed, output.x, output.z, output.score); | ||
| std::fprintf(output_file, "%" PRIi64 " %" PRIi32 " %" PRIi32 " %" PRIi32 "\n", output.seed, output.x, output.z, output.score); | ||
| std::fflush(output_file); | ||
| print_result_card(SearchResult{static_cast<int64_t>(output.seed), output.x, output.z, output.score}, large_biomes); | ||
| if (output_file != nullptr) { | ||
| write_result_line(output_file, SearchResult{static_cast<int64_t>(output.seed), output.x, output.z, output.score}); | ||
| std::fflush(output_file); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (args.devices.size() == 0 && i % 10 == 0) { | ||
| std::lock_guard lock(gpu_outputs.mutex); | ||
| std::printf("gpu_outputs.queue.size() = %zu\n", gpu_outputs.queue.size()); | ||
| std::printf("[status] queued GPU outputs: %zu\n", gpu_outputs.queue.size()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why change this? |
||
| } | ||
|
|
||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary formatting change |
||
| std::this_thread::sleep_for(std::chrono::seconds(1)); | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary formatting change |
||
| #ifndef NO_GPU | ||
| for (auto &thread : gpu_threads) { | ||
| (*thread).stop(); | ||
|
|
@@ -302,10 +410,25 @@ int main_inner(int argc, char **argv) { | |
| } | ||
| #endif | ||
|
|
||
| if (threads != 0) { | ||
| std::lock_guard lock(cpu_outputs.mutex); | ||
| while (!cpu_outputs.queue.empty()) { | ||
| auto output = cpu_outputs.queue.front(); | ||
| cpu_outputs.queue.pop(); | ||
| print_result_card(SearchResult{static_cast<int64_t>(output.seed), output.x, output.z, output.score}, large_biomes); | ||
| if (output_file != nullptr) { | ||
| write_result_line(output_file, SearchResult{static_cast<int64_t>(output.seed), output.x, output.z, output.score}); | ||
| std::fflush(output_file); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't need this line added |
||
| if (output_file != nullptr) { | ||
| std::fflush(output_file); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might be the most "Correct" thing to do but since we're already closing the file anyway in the next line, I'm not sure it's necessary. |
||
| std::fclose(output_file); | ||
| } | ||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't need this line added |
||
| return 0; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't see why we need the extra newline