aboutsummaryrefslogtreecommitdiff
path: root/srchr/src/evaluation.rs
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2022-09-29 22:55:01 +0200
committertslil clingman <tslil@posteo.de>2022-09-29 22:55:01 +0200
commitab985ecb4cb6bcc8a65ff79aa746a1f80fa4b2f4 (patch)
tree876352f82e51723ac1cbadeda272c3adbef00ae5 /srchr/src/evaluation.rs
parent785fa20b4e4a5372857f6f033b9d478685460cea (diff)
Refactor code
Diffstat (limited to 'srchr/src/evaluation.rs')
-rw-r--r--srchr/src/evaluation.rs172
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())
+ }
+}