diff --git a/src/lib.rs b/src/lib.rs index 9900876..3b11bc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,18 +21,56 @@ pub mod wikipedia_infobox_analyzer { } /// Creates an ascii infobox out of the properties - pub fn format_infobox_from_used_properties(name: String, properties: Vec) -> String { + pub fn format_infobox_from_used_properties(name: String, qid: String, properties_template: Vec, properties_item: Vec, ) -> String { let mut ascii_table = AsciiTable::default(); - ascii_table.set_max_width(26); + ascii_table.set_max_width(80); ascii_table .column(0) - .set_header(name) + .set_header("Infobox requires") .set_align(Align::Left); - let data: Vec> = properties.iter().map(|v| vec![format!("P{v}")]).collect(); + ascii_table + .column(1) + .set_header(format!("Wikidata {name} ({qid})")) + .set_align(Align::Left); + + // Display the property columns as a table + let data: Vec> = join_columns(&properties_template, &properties_item) + .iter() + .map(|&m| { + let (v1, v2) = m; + vec![ v1.map_or("".to_owned(), |v| format!("P{v}").to_owned()) + , v2.map_or("".to_owned(), |v| format!("P{v}").to_owned())] + } + ).collect(); ascii_table.format(data) } + /// Properties will be displayed in the right column if they are in the list for that column + /// All items in the left columns will be displayed + /// The remaining items in the right columns not in the left columns will trail in the right column + /// ┌───────┬───────┐ + /// │ 1 │ 1 │ + /// │ 3 │ │ + /// │ │ 2 │ + /// │ │ 4 │ + /// └───────┴───────┘ + /// So for example, [1, 3] and [1, 2, 4] become [1, 2, 3, 4], as shown above + fn join_columns(vec1: &[T], vec2: &[T]) -> Vec<(Option, Option)> { + vec1.iter() + .flat_map(|n1| { + if let Some(&n2) = vec2.iter().find(|&x| x == n1) { + std::iter::once((Some(*n1), Some(n2))) + } else { + std::iter::once((Some(*n1), None)) + } + }) + .chain(vec2.iter() + .filter(|&n2| !vec1.contains(n2)) + .map(|n2| (None, Some(*n2)))) + .collect() + } + /// Fetches the wikidata label for the wiki property pub async fn fetch_name_for_wiki_property(pid: u64) -> String { let query = format!(" @@ -139,16 +177,22 @@ mod tests { assert_eq!( format_infobox_from_used_properties( "Earth".to_string(), - vec![31, 361, 571] + "Q2".to_string(), + vec![18, 170, 571], + vec![18, 31, 138, 170, 361, 571] ), + concat![ - "┌───────┐\n", - "│ Earth │\n", // item identifier: Q2 - "├───────┤\n", - "│ P31 │\n", // property: instance of - "│ P361 │\n", // property: part of - "│ P571 │\n", // property: inception - "└───────┘\n" + "┌──────────────────┬─────────────────────┐\n", + "│ Infobox requires │ Wikidata Earth (Q2) │\n", + "├──────────────────┼─────────────────────┤\n", + "│ P18 │ P18 │\n", // property: image + "│ P170 │ P170 │\n", // property: creator + "│ P571 │ P571 │\n", // property: inception + "│ │ P31 │\n", // property: instance of + "│ │ P138 │\n", // property: inception + "│ │ P361 │\n", // property: part of + "└──────────────────┴─────────────────────┘\n", ] ); } diff --git a/src/main.rs b/src/main.rs index fc0a264..0d9523c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,15 +17,20 @@ fn main() -> Result<(), Box> { // Input to the program let title = args.wikipedia_article_title; let language = args.wikipedia_language_code; - let _template = std::fs::read_to_string(&args.infobox_template_file)?; + let template = std::fs::read_to_string(&args.infobox_template_file)?; let qid = fetch_wiki_item_by_article_title(title.clone(), language.clone()); + let properties_template = extract_used_properties_from_template(template); - let properties = fetch_properties_for_wiki_item(qid); - let table = format_infobox_from_used_properties(title.clone(), properties); + let properties_item = fetch_properties_for_wiki_item(qid); + let table = format_infobox_from_used_properties( + title.clone(), + format!("Q{qid}"), + properties_template, + properties_item, + ); - println!("Qid: {qid}"); - println!("Template file exists"); + // Output of the program println!("{table}"); Ok(())