//! The algorithms powering pronouns.today - Random pronouns generated daily //! //! This library contains all of the functionality for selecting a random pronoun based off of a //! user's preferences, including parsing various preference string (prefstring) versions, //! generating a weighted table based off of user preferences, and selecting a pronoun set based //! off of that weighted table. //! //! ## Basic Usage //! //! ``` //! use pronouns_today::InstanceSettings; //! //! let instance_settings = InstanceSettings::default(); // Or load from a config file //! //! // When you receive a request //! let user_name = Some("Emi"); //! let user_prefstr = Some("acaqqbykawbag"); //! let pronouns = instance_settings.select_pronouns(user_name, user_prefstr); //! //! println!("Your pronouns are: {}", pronouns); //! ``` //! //! ## Advanced Usage //! //! The `InstanceSettings::select_pronouns()` method is really just a shorthand for the //! more complex process going on behind the scenes. In reality, there are several steps //! used to select the pronouns. Each step can be modified or run individually for //! greater control. //! //! 1. Configure the [`InstanceSettings`] from a config or default //! 2. Parse the user's prefstring with [`UserPreferences::from_prefstring()`][up] //! 3. Produce a weighted table from the preferences using //! [`UserPreferences::into_weighted_table()`][up] //! 4. Roll a pronoun set from the weighted table with one of the methods in the //! [`WeightedTable`] struct. //! 5. Render the [`Pronoun`]s with one of the provided methods, or use the forms //! individually. //! //! [up]: UserPreferences pub mod user_preferences; pub mod util; mod weighted_table; use std::fmt; use serde::{Serialize, Deserialize, self}; pub use weighted_table::WeightedTable; pub use user_preferences::UserPreferences; /// Runtime-constant setting that apply to an entire pronouns.today instance /// /// These are values specified by the instance operator through the pronouns.today config file. /// /// This is also the struct that is used to perform the majority of operations pertaining parsing /// user preference strings (prefstrings). Utility methods are also provided for parsing a /// prefstring and then selecting a pronoun with it all at once. #[derive(Clone, Serialize, Deserialize, Debug)] pub struct InstanceSettings { /// A list of pronouns recognized by the instance pub pronoun_list: Vec, } impl InstanceSettings { /// Parse a prefstring and then immediately select pronouns from it. /// /// This is shorthand for /// /// ``` /// # use pronouns_today::InstanceSettings; /// # let settings = InstanceSettings::default(); /// # let name = String::from("Sashanora"); /// # let prefstring = String::from("todo"); /// let pronouns = settings.parse_prefstring(Some(&prefstring)).select_pronouns(Some(&name)); /// # assert_eq!(pronouns, settings.select_pronouns(Some(&name), Some(&prefstring))); /// ``` pub fn select_pronouns(&self, name: Option>, pref_string: Option>) -> &str { todo!() } } impl Default for InstanceSettings { fn default() -> Self { let pronouns: Vec = vec![ ["she", "her", "her", "hers", "herself" ].into(), ["he", "him", "his", "his", "himself" ].into(), ["they", "them", "their", "theirs", "themself" ].into(), ["it", "it", "its", "its", "itself" ].into(), ["xe", "xem", "xyr", "xyrs", "xemself" ].into(), ["ze", "zem", "zyr", "zyrs", "zemself" ].into(), ["fae", "faer", "faer", "faers", "faerself" ].into(), ["ne", "nem", "nir", "nirs", "nirself" ].into(), ["e", "em", "eir", "eirs", "eirself" ].into(), ["vey", "vem", "ver", "vers", "verself" ].into(), ]; InstanceSettings { pronoun_list: pronouns } } } /// A standard five-form pronoun set /// /// All pronouns are configured as five-form pronoun set. This is necessary in order to display /// example sentances to the user. However, typically only two or three forms of the pronoun are /// used to display the pronoun. For example, she/her/her/hers/herself would typically be written /// she/her or she/her/hers. /// /// Methods are provided to quickly generate these shorter forms, as well as example sentences. #[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug)] #[serde(from = "[String; 5]", into = "[String; 5]")] pub struct Pronoun { /// The pronoun's form when used as a subject /// /// For "she", this is "she", as in /// /// > *She* went to the park. pub subject_pronoun: String, /// The pronoun's form when used as an object /// /// For "she", this is "her", as in /// /// > I went with *her* pub object_pronoun: String, /// The pronoun's form when used as a possesive determiner /// /// For "she", this is "her", as in /// /// > I have *her* frisbee pub possesive_determiner: String, /// The pronoun's form when used as a possesive pronoun /// /// For "she", this is "hers", as in /// /// > At least I think it is *hers*. pub possesive_pronoun: String, /// The pronoun's form when used reflexively /// /// For "she", this is "herself", as in /// /// > She did it herself pub reflexive_pronoun: String, } impl Pronoun { pub fn render_threeform(&self) -> String { format!("{}/{}/{}", self.subject_pronoun, self.object_pronoun, self.possesive_pronoun) } } impl fmt::Display for Pronoun { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(&self.render_threeform()) } } impl From<[String; 5]> for Pronoun { fn from(five_form: [String; 5]) -> Self { let mut five_form = IntoIterator::into_iter(five_form); // If anyone knows a better way of deconstructing this, *please* let me know, or PR Pronoun { subject_pronoun: five_form.next().unwrap(), object_pronoun: five_form.next().unwrap(), possesive_determiner: five_form.next().unwrap(), possesive_pronoun: five_form.next().unwrap(), reflexive_pronoun: five_form.next().unwrap(), } } } impl From<[&str; 5]> for Pronoun { fn from(five_form: [&str; 5]) -> Self { (&five_form).into() } } impl From<&[&str; 5]> for Pronoun { fn from(five_form: &[&str; 5]) -> Self { Pronoun { subject_pronoun: five_form[0].to_string(), object_pronoun: five_form[1].to_string(), possesive_determiner: five_form[2].to_string(), possesive_pronoun: five_form[3].to_string(), reflexive_pronoun: five_form[4].to_string(), } } } impl From for [String; 5] { fn from(pronoun: Pronoun) -> Self { [ pronoun.subject_pronoun, pronoun.object_pronoun, pronoun.possesive_determiner, pronoun.possesive_pronoun, pronoun.reflexive_pronoun, ] } }