add CLI flags, update README accordingly, add mode 'expand'

This commit is contained in:
mtgmonkey 2025-06-27 04:24:57 -04:00
parent 34fd92cccc
commit 5a29918cd9
8 changed files with 258 additions and 63 deletions

127
Cargo.lock generated
View file

@ -17,6 +17,56 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "anstream"
version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -83,6 +133,52 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "clap"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.9.4"
@ -294,6 +390,12 @@ version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "http" name = "http"
version = "1.3.1" version = "1.3.1"
@ -545,6 +647,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.15" version = "1.0.15"
@ -659,6 +767,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.73" version = "0.10.73"
@ -850,6 +964,7 @@ dependencies = [
name = "rust_elaborator" name = "rust_elaborator"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"csv", "csv",
"fuzzy-matcher", "fuzzy-matcher",
"reqwest", "reqwest",
@ -1059,6 +1174,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.6.1" version = "2.6.1"
@ -1330,6 +1451,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"

View file

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
clap = { version = "4.5.40", features = ["derive"] }
csv = "1.3.1" csv = "1.3.1"
fuzzy-matcher = { version = "0.3.7", features = ["compact"] } fuzzy-matcher = { version = "0.3.7", features = ["compact"] }
reqwest = { version = "0.12.20", features = ["json"] } reqwest = { version = "0.12.20", features = ["json"] }

View file

@ -45,3 +45,9 @@ Uno,
where `title` can be anything. where `title` can be anything.
Capitalization does not matter. Capitalization does not matter.
Additional columns will not be present in `out.csv`. Additional columns will not be present in `out.csv`.
If you have an existing `out.csv`, you can add new rows and avoid recalling the rows that are already filled in with the flag `--mode expand`.
`cat out.csv | nix run . -- --mode expand`
This will only check rows that have a) a blank second column or b) NOT_FOUND in the second column.

28
flake.lock generated
View file

@ -2,7 +2,9 @@
"nodes": { "nodes": {
"naersk": { "naersk": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs" "nixpkgs": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1745925850, "lastModified": 1745925850,
@ -20,27 +22,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1750215678, "lastModified": 1750776420,
"narHash": "sha256-Rc/ytpamXRf6z8UA2SGa4aaWxUXRbX2MAWIu2C8M+ok=", "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "5395fb3ab3f97b9b7abca147249fa2e8ed27b192", "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1750134718,
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -52,7 +38,7 @@
"root": { "root": {
"inputs": { "inputs": {
"naersk": "naersk", "naersk": "naersk",
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs"
} }
} }
}, },

View file

@ -1,7 +1,10 @@
{ {
inputs = { inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable"; nixpkgs.url = "nixpkgs/nixos-unstable";
naersk.url = github:nix-community/naersk; naersk = {
url = "github:nix-community/naersk";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = { outputs = {
nixpkgs, nixpkgs,
@ -11,7 +14,11 @@
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
in { in {
packages.${system}.default = pkgs.callPackage ./package.nix {naersk = pkgs.callPackage naersk {};}; packages.${system} = {
default = pkgs.callPackage ./package.nix {
naersk = pkgs.callPackage naersk {};
};
};
# nixosModules.${system}.default = ./module.nix; # nixosModules.${system}.default = ./module.nix;
}; };
} }

View file

@ -1,7 +1,6 @@
{ {
openssl, openssl,
pkg-config, pkg-config,
stdenv,
naersk, naersk,
... ...
}: }:
@ -10,11 +9,6 @@ naersk.buildPackage {
src = ./.; src = ./.;
buildInputs = [openssl]; buildInputs = [openssl];
nativeBuildInputs = [pkg-config]; nativeBuildInputs = [pkg-config];
# configurePhase = '''';
# buildPhase = '''';
# installPhase = ''
# install -Dm775 ./target/release/rust_elaborator $out/bin/rust_elaborator
# '';
meta = { meta = {
mainProgram = "rust_elaborator"; mainProgram = "rust_elaborator";
homepage = "https://mtgmonkey.net"; homepage = "https://mtgmonkey.net";

View file

@ -1,7 +1,13 @@
use reqwest::Error; use clap::Parser;
use reqwest::header::USER_AGENT;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
#[arg(short, long, default_value_t = ("elaborate".to_string()))]
pub mode: String,
}
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct Id_search_results { pub struct Id_search_results {
pub boardgame: Boardgame, pub boardgame: Boardgame,

View file

@ -1,3 +1,4 @@
use clap::Parser;
use reqwest::header::USER_AGENT; use reqwest::header::USER_AGENT;
use rust_elaborator::*; use rust_elaborator::*;
use std::io; use std::io;
@ -6,7 +7,12 @@ use std::io::prelude::*;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), reqwest::Error> { async fn main() -> Result<(), reqwest::Error> {
println!("Welcome to rust_elaborator!"); println!("Welcome to rust_elaborator!");
write_csv().await; let args = Args::parse();
match args.mode.as_str() {
"elaborate" => make_out_from_in().await,
"expand" => make_out_from_out().await,
_ => panic!(),
};
Ok(()) Ok(())
} }
@ -130,31 +136,7 @@ fn find_best_boardgame(
) )
} }
fn find_best_match(name: String, mut names: Vec<&String>) -> (String, i32) { async fn make_out_from_in() -> Result<(), Box<dyn std::error::Error>> {
use fuzzy_matcher::FuzzyMatcher;
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default();
names.sort_unstable_by(|a, b| {
matcher
.fuzzy_match(a, &name)
.cmp(&matcher.fuzzy_match(b, &name))
});
(
names[0].to_string(),
matcher.fuzzy_match(&names[0], &name).unwrap(),
)
}
fn read_csv() -> Result<(), Box<dyn std::error::Error>> {
let mut reader = csv::Reader::from_reader(io::stdin());
for result in reader.records() {
let record = result.unwrap();
let game = &record[0];
println!("Game: {}", game);
}
Ok(())
}
async fn write_csv() -> Result<(), Box<dyn std::error::Error>> {
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
let mut out = File::create("out.csv").unwrap(); let mut out = File::create("out.csv").unwrap();
@ -179,32 +161,32 @@ async fn write_csv() -> Result<(), Box<dyn std::error::Error>> {
let boardgame = get_boardgame_from_name(&client, game.to_string()).await; let boardgame = get_boardgame_from_name(&client, game.to_string()).await;
match boardgame { match boardgame {
Some(boardgame) => { Some(boardgame) => {
let minplayers = if (boardgame.minplayers != 0) { let minplayers = if boardgame.minplayers != 0 {
boardgame.minplayers.to_string() boardgame.minplayers.to_string()
} else { } else {
"".to_string() "".to_string()
}; };
let maxplayers = if (boardgame.maxplayers != 0) { let maxplayers = if boardgame.maxplayers != 0 {
boardgame.maxplayers.to_string() boardgame.maxplayers.to_string()
} else { } else {
"".to_string() "".to_string()
}; };
let playingtime = if (boardgame.playingtime != 0) { let playingtime = if boardgame.playingtime != 0 {
boardgame.playingtime.to_string() boardgame.playingtime.to_string()
} else { } else {
"".to_string() "".to_string()
}; };
let minplaytime = if (boardgame.minplaytime != 0) { let minplaytime = if boardgame.minplaytime != 0 {
boardgame.minplaytime.to_string() boardgame.minplaytime.to_string()
} else { } else {
"".to_string() "".to_string()
}; };
let maxplaytime = if (boardgame.maxplaytime != 0) { let maxplaytime = if boardgame.maxplaytime != 0 {
boardgame.maxplaytime.to_string() boardgame.maxplaytime.to_string()
} else { } else {
"".to_string() "".to_string()
}; };
let age = if (boardgame.age != 0) { let age = if boardgame.age != 0 {
boardgame.age.to_string() boardgame.age.to_string()
} else { } else {
"".to_string() "".to_string()
@ -233,3 +215,89 @@ async fn write_csv() -> Result<(), Box<dyn std::error::Error>> {
} }
Ok(()) Ok(())
} }
async fn make_out_from_out() -> Result<(), Box<dyn std::error::Error>> {
use std::fs::File;
let mut out = File::create("out.csv").unwrap();
let mut writer = csv::Writer::from_writer(out);
let mut reader = csv::Reader::from_reader(io::stdin());
writer
.write_record(&[
"title",
"foundtitle",
"minplayers",
"maxplayers",
"playingtime",
"minplaytime",
"maxplaytime",
"age",
])
.unwrap();
let client = reqwest::Client::new();
for result in reader.records() {
let record = result.unwrap();
let title = &record[0];
let foundtitle = &record[1];
if foundtitle == "" || foundtitle == "NOT_FOUND" {
let boardgame = get_boardgame_from_name(&client, title.to_string()).await;
match boardgame {
Some(boardgame) => {
let minplayers = if boardgame.minplayers != 0 {
boardgame.minplayers.to_string()
} else {
"".to_string()
};
let maxplayers = if boardgame.maxplayers != 0 {
boardgame.maxplayers.to_string()
} else {
"".to_string()
};
let playingtime = if boardgame.playingtime != 0 {
boardgame.playingtime.to_string()
} else {
"".to_string()
};
let minplaytime = if boardgame.minplaytime != 0 {
boardgame.minplaytime.to_string()
} else {
"".to_string()
};
let maxplaytime = if boardgame.maxplaytime != 0 {
boardgame.maxplaytime.to_string()
} else {
"".to_string()
};
let age = if boardgame.age != 0 {
boardgame.age.to_string()
} else {
"".to_string()
};
writer
.write_record(&[
title,
get_name_from_name(&client, title.to_string())
.await
.unwrap()
.as_str(),
minplayers.as_str(),
maxplayers.as_str(),
playingtime.as_str(),
minplaytime.as_str(),
maxplaytime.as_str(),
age.as_str(),
])
.unwrap()
}
None => writer
.write_record(&[title, "NOT_FOUND", "", "", "", "", "", ""])
.unwrap(),
};
} else {
writer.write_record(&[
&record[0], &record[1], &record[2], &record[3], &record[4], &record[5], &record[6],
&record[7],
]);
};
}
Ok(())
}