108 lines
3.2 KiB
Rust
108 lines
3.2 KiB
Rust
use std::{collections::HashMap, str::from_utf8};
|
|
|
|
use actix_web::{get, web, App, HttpResponse, HttpServer};
|
|
use rand::seq::SliceRandom;
|
|
use rust_embed::Embed;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
static ARTICLE: &str = "<article>";
|
|
|
|
#[derive(Embed)]
|
|
#[folder = "dictionaries/"]
|
|
struct Dictionaries;
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
struct NameGenQuery {
|
|
dictionaries: Vec<String>,
|
|
gender: String,
|
|
qty: Option<u8>,
|
|
}
|
|
|
|
#[get("/")]
|
|
async fn index(query: web::Json<NameGenQuery>) -> HttpResponse {
|
|
// Load the dictionaries into memory
|
|
let mut dictionaries = HashMap::new();
|
|
for filename in Dictionaries::iter() {
|
|
if let Some(file) = Dictionaries::get(&filename) {
|
|
let data = from_utf8(file.data.as_ref()).unwrap();
|
|
dictionaries.insert(filename.to_string(), serde_json::from_str::<Vec<String>>(data).unwrap());
|
|
}
|
|
}
|
|
|
|
let qty = query.0.qty.unwrap_or(10).min(50).max(1);
|
|
let gender = match query.0.gender.as_str() {
|
|
"m" => "masculins",
|
|
"f" => "feminins",
|
|
_ => "masculins",
|
|
};
|
|
|
|
// Limit to 10 parts max
|
|
let mut chosen_dicts = query.0.dictionaries;
|
|
chosen_dicts.truncate(10);
|
|
|
|
let mut names = vec![];
|
|
|
|
for _ in 0..qty {
|
|
let mut parts = vec![];
|
|
|
|
for dict in chosen_dicts.iter() {
|
|
let filename = match dict.as_str() {
|
|
"adjectif" | "commun" | "ppasse" | "ppresent" | "prenom" => {
|
|
Some(format!("{dict}s_{gender}.json"))
|
|
}
|
|
"patronyme" => Some(format!("{dict}s.json")),
|
|
"article" => Some(ARTICLE.to_string()),
|
|
"virgule" => Some(",".to_string()),
|
|
_ => None,
|
|
};
|
|
if let Some(filename) = filename {
|
|
if let Some(data) = dictionaries.get(&filename) {
|
|
let item = data.choose(&mut rand::thread_rng()).unwrap();
|
|
parts.push(item.to_string())
|
|
} else {
|
|
parts.push(filename)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Replace the <article> with le/la/l'
|
|
let mut to_replace = vec![];
|
|
for (i, item) in parts.iter().enumerate() {
|
|
if item == ARTICLE {
|
|
// Check the next word
|
|
if let Some(next) = parts.get(i + 1) {
|
|
if next
|
|
.starts_with(|c| vec!['a', 'e', 'i', 'o', 'u', 'é', 'è', 'ê', 'h'].contains(&c))
|
|
{
|
|
to_replace.push((i, "l'"));
|
|
} else {
|
|
to_replace.push((i, (if gender == "masculins" { "le" } else { "la" })))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for item in to_replace.iter() {
|
|
parts[item.0] = item.1.to_string();
|
|
}
|
|
|
|
let joined = parts
|
|
.join(" ")
|
|
// Remove space after "l'"
|
|
.replace("l' ", "l'")
|
|
// Remove space before comma
|
|
.replace(" ,", ",");
|
|
|
|
names.push(joined);
|
|
}
|
|
|
|
HttpResponse::Ok().json(names)
|
|
}
|
|
|
|
#[actix_web::main] // or #[tokio::main]
|
|
async fn main() -> std::io::Result<()> {
|
|
HttpServer::new(|| App::new().service(index))
|
|
.bind(("127.0.0.1", 8080))?
|
|
.run()
|
|
.await
|
|
}
|