use crate::config::*; use crate::corpus::*; use crate::layout::*; use crate::output::*; use std::fmt; pub fn prelayout_fitness(corpus: &Corpus, layout: &Prelayout) -> f32 { let mut score: f32 = 0.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_perc(k1, k2) + corpus.get_bigram_perc(k1, k3) + corpus.get_bigram_perc(k2, k3); score += (corpus.get_skipgram_perc(k1, k2) + corpus.get_skipgram_perc(k1, k3) + corpus.get_skipgram_perc(k2, k3)) * STANDARD_DSFB_WEIGHT; } 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]; let index_percs = keys.iter().map(|&k| corpus.get_character_count(k)).sum(); score += index_usage_fitness(corpus.get_total_count(), index_percs); score += corpus.get_bigram_perc(k1, k2) + corpus.get_bigram_perc(k1, k3) + corpus.get_bigram_perc(k2, k3) + corpus.get_bigram_perc(k4, k5) + corpus.get_bigram_perc(k4, k6) + corpus.get_bigram_perc(k5, k6) + corpus.get_bigram_perc(k1, k4) + corpus.get_bigram_perc(k1, k5) + corpus.get_bigram_perc(k1, k6) + corpus.get_bigram_perc(k2, k4) + corpus.get_bigram_perc(k2, k5) + corpus.get_bigram_perc(k2, k6) + corpus.get_bigram_perc(k3, k4) + corpus.get_bigram_perc(k3, k5) + corpus.get_bigram_perc(k3, k6); } score } pub struct Evaluation { keypress: [u32; NUM_KEYS], total_keypress: u32, total_bigrams: u32, sfb: [f32; 8], dsfb: [f32; 8], } impl Evaluation { pub fn evaluate_layout(corpus: &Corpus, layout: &Layout) -> Evaluation { let mut keypress: [u32; NUM_KEYS] = [0; NUM_KEYS]; let mut sfb: [f32; 8] = [0.0; 8]; let mut dsfb: [f32; 8] = [0.0; 8]; for (i, &c) in layout.get_keys().iter().enumerate() { keypress[i] = corpus.get_character_count(c as u8); } 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_perc(k1, k2) + corpus.get_bigram_perc(k1, k3) + corpus.get_bigram_perc(k2, k3); dsfb[i] = corpus.get_skipgram_perc(k1, k2) + corpus.get_skipgram_perc(k1, k3) + corpus.get_skipgram_perc(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_perc(k4, k5) + corpus.get_bigram_perc(k4, k6) + corpus.get_bigram_perc(k5, k6) + corpus.get_bigram_perc(k1, k4) + corpus.get_bigram_perc(k1, k5) + corpus.get_bigram_perc(k1, k6) + corpus.get_bigram_perc(k2, k4) + corpus.get_bigram_perc(k2, k5) + corpus.get_bigram_perc(k2, k6) + corpus.get_bigram_perc(k3, k4) + corpus.get_bigram_perc(k3, k5) + corpus.get_bigram_perc(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_perc(k4, k5) + corpus.get_bigram_perc(k5, k6) + corpus.get_bigram_perc(k4, k6) + corpus.get_bigram_perc(k1, k4) + corpus.get_bigram_perc(k1, k5) + corpus.get_bigram_perc(k1, k6) + corpus.get_bigram_perc(k2, k4) + corpus.get_bigram_perc(k2, k5) + corpus.get_bigram_perc(k2, k6) + corpus.get_bigram_perc(k3, k4) + corpus.get_bigram_perc(k3, k5) + corpus.get_bigram_perc(k3, k6); } } return Evaluation { keypress, total_keypress: corpus.get_total_count(), total_bigrams: corpus.get_total_bigrams(), sfb, dsfb, }; } fn output_eval(&self) -> String { let mut result = String::new(); let tot = self.total_keypress as f32; let big = self.total_bigrams as f32; let tig = self.total_bigrams 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 += "\nSFB distribution : "; for (i, &u) in self.sfb.iter().enumerate() { result += &format!("{:>6.3}%{}", u * 100.0, if i < 7 { ", " } else { "" }); } result += "\nDSFB distribution: "; for (i, &u) in self.dsfb.iter().enumerate() { result += &format!("{:>6.3}%{}", u * 100.0, if i < 7 { ", " } else { "" }); } let sfb = self.sfb.iter().sum::(); let dsfb = self.dsfb.iter().sum::(); result += &format!("\nTotal sfb: {:.3}% ({:.0})", sfb * 100.0, sfb * big); result += &format!("\nTotal dsfb: {:.3}% ({:.0})", dsfb * 100.0, dsfb * tig); return result; } } impl fmt::Display for Evaluation { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(&self.output_eval()) } }