use serde::Deserialize;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::Path;
const TIMES_PATH: &str = "external/literature-clock/docs/times/";
#[derive(Debug, Deserialize)]
struct Quote {
quote_first: String,
quote_time_case: String,
quote_last: String,
title: String,
author: String,
sfw: String,
}
fn get_quotes() -> HashMap<String, Vec<Quote>> {
let mut map: HashMap<String, Vec<Quote>> = HashMap::new();
for file in fs::read_dir(TIMES_PATH).unwrap() {
let file = file.unwrap();
let file_name = file.file_name();
let file_name_string = file_name.into_string().unwrap();
let (key, ext) = file_name_string.split_once('.').unwrap();
let key = key.clone().to_string();
if ext == "json" {
let contents = fs::read_to_string(file.path()).unwrap();
let quotes: Vec<Quote> = serde_json::from_str(&contents).unwrap();
map.insert(key, quotes);
}
}
map
}
fn get_next_timestamp(ts: String) -> String {
let mut ts = ts.split('_');
let mut hours = ts.next().unwrap().parse::<u8>().unwrap();
let mut minutes = ts.next().unwrap().parse::<u8>().unwrap();
minutes += 1;
if minutes == 60 {
hours += 1;
minutes = 0;
}
if hours == 24 {
hours = 0;
}
format!("{:02}_{:02}", hours, minutes)
}
fn replace(s: &str) -> String {
s.replace('"', "\\\"")
.replace("<br>", "\\n")
.replace("<br/>", "\\n")
.replace("<br />", "\\n")
.replace("\\n ", "\\n")
}
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let quotes_dest_path = Path::new(&out_dir).join("quotes.rs");
let options_dest_path = Path::new(&out_dir).join("options.rs");
let quotes = get_quotes();
let mut quotes_string = String::new();
for (key, value) in quotes.iter() {
for (index, quote) in value.iter().enumerate() {
quotes_string.push_str(&format!(
"static QUOTE_{}_{}: Minute = Minute{{title: \"{}\", author: \"{}\", start: \"{}\", time: \"{}\", end: \"{}\"}};\n",
key,
index,
replace("e.title),
replace("e.author),
replace("e.quote_first),
replace("e.quote_time_case),
replace("e.quote_last),
));
}
}
fs::write(quotes_dest_path, quotes_string).unwrap();
let mut pre_processed_matches: Vec<(String, String, String)> = Vec::new();
let mut values = quotes.iter().collect::<Vec<_>>();
values.sort_by(|a, b| a.0.cmp(b.0));
for (key, value) in values {
let mut sfw_quotes: Vec<String> = Vec::new();
let mut all_quotes: Vec<String> = Vec::new();
for (index, quote) in value.iter().enumerate() {
all_quotes.push(format!(""E_{}_{}", key, index));
if quote.sfw == "yes" {
sfw_quotes.push(format!(""E_{}_{}", key, index));
}
}
let mut timestamps: Vec<String> = vec![key.to_string()];
let mut timestamp = get_next_timestamp(key.clone());
while !quotes.contains_key(×tamp) {
timestamps.push(timestamp.clone());
timestamp = get_next_timestamp(timestamp);
}
let joined_timestamps = timestamps.join("\" | \"");
if sfw_quotes.len() == all_quotes.len() {
pre_processed_matches.push((joined_timestamps, "_".to_string(), all_quotes.join(", ")));
} else if sfw_quotes.is_empty() {
let (mut previous_joined_timestamps, sfw, varnames) =
pre_processed_matches.pop().unwrap();
if sfw == "true" {
previous_joined_timestamps += &("\" | \"".to_string() + &joined_timestamps);
pre_processed_matches.push((previous_joined_timestamps, sfw, varnames));
} else if sfw == "_" {
pre_processed_matches.push((
previous_joined_timestamps.clone(),
"false".to_string(),
varnames.clone(),
));
previous_joined_timestamps += &("\" | \"".to_string() + &joined_timestamps);
pre_processed_matches.push((
previous_joined_timestamps,
"true".to_string(),
varnames,
));
} else {
panic!("Last preprocessed was nsfw?");
}
pre_processed_matches.push((
joined_timestamps,
"false".to_string(),
all_quotes.join(", "),
));
} else {
pre_processed_matches.push((
joined_timestamps.clone(),
"false".to_string(),
all_quotes.join(", "),
));
pre_processed_matches.push((
joined_timestamps,
"true".to_string(),
sfw_quotes.join(", "),
));
}
}
let mut options_string = String::new();
options_string.push_str("match (time, sfw) {\n");
for (time, sfw, quotes) in pre_processed_matches {
options_string.push_str(&format!(
"(\"{}\", {}) => vec![{}],\n",
time.replace('_', ":"),
sfw,
quotes,
));
}
options_string.push_str("(_, _) => bail!(\"Couldn't match timestamp!\"),\n");
options_string.push('}');
fs::write(options_dest_path, options_string).unwrap();
println!("cargo:rerun-if-changed=external/literature-clock/");
println!("cargo:rerun-if-changed=build.rs");
}