Impl from_preferences
With creates a Preference instance from a list of pronoun weights. Signed-off-by: Ben Aaron Goldberg <ben@benaaron.dev>
This commit is contained in:
parent
87583fc383
commit
29addcaf9a
|
@ -65,6 +65,13 @@ pub trait Preference {
|
|||
/// [1]: https://fem.mint.lgbt/Emi/PronounsToday/raw/branch/main/doc/User-Preference-String-Spec.txt
|
||||
fn as_prefstring_bytes(&self) -> Vec<u8>;
|
||||
|
||||
/// Create a Preference instance from a list of pronoun preferences
|
||||
///
|
||||
/// This should produce an instance of Preference using the provided preferences.
|
||||
/// `prefs` is a list of pronoun preferences. Each entry is the weight of the pronoun
|
||||
/// at that index in the pronoun list in the settings.
|
||||
fn from_preferences(prefs: &[u8]) -> Self where Self: Sized;
|
||||
|
||||
/// Parse a base64 prefstring
|
||||
///
|
||||
/// This is the primary method of creating a `Preference` object from a prefstring. The
|
||||
|
@ -128,4 +135,8 @@ impl Preference for UserPreferences {
|
|||
UserPreferences::V0(pref) => pref,
|
||||
}.as_prefstring_bytes()
|
||||
}
|
||||
|
||||
fn from_preferences(prefs: &[u8]) -> Self where Self: Sized {
|
||||
UserPreferences::V0(UserPreferencesV0::from_preferences(prefs))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use std::{
|
|||
/// See the [prefstring specification][1] for more information about how this is interpretted.
|
||||
///
|
||||
/// [1]: https://fem.mint.lgbt/Emi/PronounsToday/raw/branch/main/doc/User-Preference-String-Spec.txt
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct UserPreferencesV0 {
|
||||
pub default_weight: u8,
|
||||
pub default_enabled: bool,
|
||||
|
@ -129,6 +130,91 @@ impl Preference for UserPreferencesV0 {
|
|||
.chain(self.commands.iter().map(|cmd| cmd.into()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn from_preferences(prefs: &[u8]) -> Self where Self: Sized {
|
||||
if prefs.is_empty() {
|
||||
return Self::default();
|
||||
}
|
||||
let mut weight_counts = vec![0u8; *prefs.iter().max().unwrap() as usize + 1];
|
||||
let mut num_zeros = 0;
|
||||
for w in prefs {
|
||||
if *w == 0 {
|
||||
num_zeros += 1;
|
||||
} else {
|
||||
weight_counts[*w as usize] += 1;
|
||||
}
|
||||
}
|
||||
let default_weight = weight_counts
|
||||
.iter()
|
||||
.enumerate()
|
||||
.max_by(|(_, v1), (_, v2)| v1.cmp(v2))
|
||||
.map(|(w, _)| w as u8)
|
||||
.unwrap();
|
||||
let default_enabled = num_zeros < prefs.len() / 2;
|
||||
let mut commands = Vec::new();
|
||||
if default_enabled {
|
||||
let mut last_default = -1;
|
||||
for (i, w) in prefs.iter().enumerate() {
|
||||
let i = i as isize;
|
||||
if *w == default_weight {
|
||||
continue;
|
||||
} else {
|
||||
if i - last_default > 1 {
|
||||
let toggle_enabled = *w == 0;
|
||||
let distance = if toggle_enabled {
|
||||
(i - last_default) as u8 - 1
|
||||
} else {
|
||||
(i - last_default) as u8 - 2
|
||||
};
|
||||
eprintln!("{} {} {} {}", toggle_enabled, distance, i, last_default);
|
||||
commands.push(Command::Move {
|
||||
toggle_enabled,
|
||||
distance
|
||||
});
|
||||
if !toggle_enabled {
|
||||
commands.push(Command::SetWeight(*w));
|
||||
}
|
||||
} else {
|
||||
commands.push(Command::SetWeight(*w));
|
||||
}
|
||||
last_default = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut last_enabled = -1;
|
||||
for (i, w) in prefs.iter().enumerate() {
|
||||
let i = i as isize;
|
||||
if *w == 0 {
|
||||
continue;
|
||||
} else {
|
||||
if i - last_enabled > 1 {
|
||||
let toggle_enabled = *w == default_weight;
|
||||
let distance = if toggle_enabled {
|
||||
(i - last_enabled) as u8 - 1
|
||||
} else {
|
||||
(i - last_enabled) as u8 - 2
|
||||
};
|
||||
eprintln!("{} {} {} {}", toggle_enabled, distance, i, last_enabled);
|
||||
commands.push(Command::Move {
|
||||
toggle_enabled,
|
||||
distance
|
||||
});
|
||||
if !toggle_enabled {
|
||||
commands.push(Command::SetWeight(*w));
|
||||
}
|
||||
} else {
|
||||
commands.push(Command::SetWeight(*w));
|
||||
}
|
||||
last_enabled = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self {
|
||||
default_weight,
|
||||
default_enabled,
|
||||
commands,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Default to all pronouns on with equal weight
|
||||
|
@ -392,4 +478,132 @@ mod tests {
|
|||
|
||||
check_table(table, expected_table);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_prefs_most_disabled1() {
|
||||
let pref_vals = vec![0,1,2,0,0];
|
||||
let expected_prefs = UserPreferencesV0 {
|
||||
default_enabled: false,
|
||||
default_weight: 2,
|
||||
commands: vec![
|
||||
Command::Move {
|
||||
toggle_enabled: false,
|
||||
distance: 0,
|
||||
},
|
||||
Command::SetWeight(1),
|
||||
Command::SetWeight(2),
|
||||
],
|
||||
};
|
||||
let prefs = UserPreferencesV0::from_preferences(&pref_vals);
|
||||
assert_eq!(prefs, expected_prefs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_prefs_most_disabled2() {
|
||||
let pref_vals = vec![0,1,1,0,0,0,2];
|
||||
let expected_prefs = UserPreferencesV0 {
|
||||
default_enabled: false,
|
||||
default_weight: 1,
|
||||
commands: vec![
|
||||
Command::Move {
|
||||
toggle_enabled: true,
|
||||
distance: 1,
|
||||
},
|
||||
Command::SetWeight(1),
|
||||
Command::Move {
|
||||
toggle_enabled: false,
|
||||
distance: 2,
|
||||
},
|
||||
Command::SetWeight(2),
|
||||
],
|
||||
};
|
||||
let prefs = UserPreferencesV0::from_preferences(&pref_vals);
|
||||
assert_eq!(prefs, expected_prefs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_prefs_most_disabled3() {
|
||||
let pref_vals = vec![0,0,0,0,1,0,0,0,2];
|
||||
let expected_prefs = UserPreferencesV0 {
|
||||
default_enabled: false,
|
||||
default_weight: 2,
|
||||
commands: vec![
|
||||
Command::Move {
|
||||
toggle_enabled: false,
|
||||
distance: 3,
|
||||
},
|
||||
Command::SetWeight(1),
|
||||
Command::Move {
|
||||
toggle_enabled: true,
|
||||
distance: 3,
|
||||
},
|
||||
],
|
||||
};
|
||||
let prefs = UserPreferencesV0::from_preferences(&pref_vals);
|
||||
assert_eq!(prefs, expected_prefs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_prefs_most_enabled1() {
|
||||
let pref_vals = vec![0,1,2,1,1];
|
||||
let expected_prefs = UserPreferencesV0 {
|
||||
default_enabled: true,
|
||||
default_weight: 1,
|
||||
commands: vec![
|
||||
Command::SetWeight(0),
|
||||
Command::Move {
|
||||
toggle_enabled: false,
|
||||
distance: 0,
|
||||
},
|
||||
Command::SetWeight(2),
|
||||
],
|
||||
};
|
||||
let prefs = UserPreferencesV0::from_preferences(&pref_vals);
|
||||
assert_eq!(prefs, expected_prefs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_prefs_most_enabled2() {
|
||||
let pref_vals = vec![1,0,0,1,1,1,2];
|
||||
let expected_prefs = UserPreferencesV0 {
|
||||
default_enabled: true,
|
||||
default_weight: 1,
|
||||
commands: vec![
|
||||
Command::Move {
|
||||
toggle_enabled: true,
|
||||
distance: 1,
|
||||
},
|
||||
Command::SetWeight(0),
|
||||
Command::Move {
|
||||
toggle_enabled: false,
|
||||
distance: 2,
|
||||
},
|
||||
Command::SetWeight(2),
|
||||
],
|
||||
};
|
||||
let prefs = UserPreferencesV0::from_preferences(&pref_vals);
|
||||
assert_eq!(prefs, expected_prefs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_prefs_most_enabled3() {
|
||||
let pref_vals = vec![1,1,1,1,0,1,1,1,2];
|
||||
let expected_prefs = UserPreferencesV0 {
|
||||
default_enabled: true,
|
||||
default_weight: 1,
|
||||
commands: vec![
|
||||
Command::Move {
|
||||
toggle_enabled: true,
|
||||
distance: 4,
|
||||
},
|
||||
Command::Move {
|
||||
toggle_enabled: false,
|
||||
distance: 2,
|
||||
},
|
||||
Command::SetWeight(2),
|
||||
],
|
||||
};
|
||||
let prefs = UserPreferencesV0::from_preferences(&pref_vals);
|
||||
assert_eq!(prefs, expected_prefs);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue