diff options
Diffstat (limited to 'srchr/src/evaluation.rs')
| -rw-r--r-- | srchr/src/evaluation.rs | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/srchr/src/evaluation.rs b/srchr/src/evaluation.rs new file mode 100644 index 0000000..9faeb88 --- /dev/null +++ b/srchr/src/evaluation.rs @@ -0,0 +1,172 @@ +use crate::config::*; +use crate::corpus::*; +use crate::layout::*; +use crate::output::*; + +use std::fmt; + +pub fn prelayout_fitness(corpus: &Corpus, layout: &Prelayout) -> u32 { + let mut score: u32 = 0; + + for i in 0..6 { + let keys = layout.get_standard_column(i); + let k1 = keys[0]; + let k2 = keys[1]; + let k3 = keys[2]; + + score += corpus.get_bigram_count(k1, k2) + + corpus.get_bigram_count(k1, k3) + + corpus.get_bigram_count(k2, k3); + } + + for i in 0..2 { + let keys = layout.get_index_column(i); + let k1 = keys[0]; + let k2 = keys[1]; + let k3 = keys[2]; + let k4 = keys[3]; + let k5 = keys[4]; + let k6 = keys[5]; + + // We want index usage! + let index_count: u32 = keys.iter().map(|&k| corpus.get_character_count(k)).sum(); + score += index_usage_fitness(corpus.get_index_threshold(), index_count); + + score += corpus.get_bigram_count(k1, k2) + + corpus.get_bigram_count(k1, k3) + + corpus.get_bigram_count(k2, k3) + + corpus.get_bigram_count(k4, k5) + + corpus.get_bigram_count(k4, k6) + + corpus.get_bigram_count(k5, k6) + + corpus.get_bigram_count(k1, k4) + + corpus.get_bigram_count(k1, k5) + + corpus.get_bigram_count(k1, k6) + + corpus.get_bigram_count(k2, k4) + + corpus.get_bigram_count(k2, k5) + + corpus.get_bigram_count(k2, k6) + + corpus.get_bigram_count(k3, k4) + + corpus.get_bigram_count(k3, k5) + + corpus.get_bigram_count(k3, k6); + } + + score +} + +#[derive(Copy, Clone)] +pub struct Evaluation { + keypress: [u32; NUM_KEYS], + total_keypress: u32, + sfb: [u32; 8], +} + +impl Evaluation { + pub fn evaluate_layout(corpus: &Corpus, layout: &Layout) -> Evaluation { + let mut keypress: [u32; NUM_KEYS] = [0; NUM_KEYS]; + let mut sfb: [u32; 8] = [0; 8]; + + for (i, &c) in layout.get_keys().iter().enumerate() { + keypress[i] = corpus.get_character_count(c); + } + + // TODO: We make assumptions about NUM_KEYS here + for i in 0..8 { + let ind = if i < 4 { i } else { i + 2 }; + + let k1 = layout.get_key(ind + 10 * 0); + let k2 = layout.get_key(ind + 10 * 1); + let k3 = layout.get_key(ind + 10 * 2); + + sfb[i] = corpus.get_bigram_count(k1, k2) + + corpus.get_bigram_count(k1, k3) + + corpus.get_bigram_count(k2, k3); + + if i == 3 { + let k4 = layout.get_key(4 + 10 * 0); + let k5 = layout.get_key(4 + 10 * 1); + let k6 = layout.get_key(4 + 10 * 2); + sfb[i] += corpus.get_bigram_count(k4, k5) + + corpus.get_bigram_count(k4, k6) + + corpus.get_bigram_count(k5, k6) + + corpus.get_bigram_count(k1, k4) + + corpus.get_bigram_count(k1, k5) + + corpus.get_bigram_count(k1, k6) + + corpus.get_bigram_count(k2, k4) + + corpus.get_bigram_count(k2, k5) + + corpus.get_bigram_count(k2, k6) + + corpus.get_bigram_count(k3, k4) + + corpus.get_bigram_count(k3, k5) + + corpus.get_bigram_count(k3, k6); + } else if i == 4 { + let k4 = layout.get_key(5 + 10 * 0); + let k5 = layout.get_key(5 + 10 * 1); + let k6 = layout.get_key(5 + 10 * 2); + sfb[i] += corpus.get_bigram_count(k4, k5) + + corpus.get_bigram_count(k5, k6) + + corpus.get_bigram_count(k4, k6) + + corpus.get_bigram_count(k1, k4) + + corpus.get_bigram_count(k1, k5) + + corpus.get_bigram_count(k1, k6) + + corpus.get_bigram_count(k2, k4) + + corpus.get_bigram_count(k2, k5) + + corpus.get_bigram_count(k2, k6) + + corpus.get_bigram_count(k3, k4) + + corpus.get_bigram_count(k3, k5) + + corpus.get_bigram_count(k3, k6); + } + } + + return Evaluation { + keypress, + total_keypress: corpus.get_total_count(), + sfb, + }; + } + + fn output_eval(&self) -> String { + let mut result = String::new(); + let tot = self.total_keypress as f32; + + result += &"Percent per key:\n"; + result += &format_block_output(self.keypress.into_iter().map(|k| 100.0 * k as f32 / tot)); + + let mut finger_usages = [0; 8]; + for (i, &c) in self.keypress.iter().enumerate() { + finger_usages[KEY_TO_FINGER[i]] += c; + } + + result += "\nFinger usage: "; + let mut lh: f32 = 0.0; + let mut rh: f32 = 0.0; + for (i, &u) in finger_usages.iter().enumerate() { + let f = u as f32 / tot * 100.0; + result += &format!("{:>5.2}%{}", f, if i < 7 { ", " } else { "" }); + if i % 10 < 4 { + lh += f; + } else { + rh += f; + } + } + + result += &format!("\nHand usage: {:.2}% vs {:.2}%", lh, rh); + + result += "\nSame finger bigrams: "; + for (i, &u) in self.sfb.iter().enumerate() { + result += &format!( + "{:>6.3}%{}", + u as f32 / tot * 100.0, + if i < 7 { ", " } else { "" } + ); + } + + let sfb = self.sfb.iter().sum::<u32>(); + result += &format!("\nTotal sfb: {:.2}% ({})", sfb as f32 / tot * 100.0, sfb); + + return result; + } +} + +impl fmt::Display for Evaluation { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(&self.output_eval()) + } +} |
