123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- use r2d2_sqlite::SqliteConnectionManager;
- use r2d2::Pool;
- #[macro_use]
- use rusqlite::params;
- use std::sync::Arc;
- use std::fs::File;
- use std::io::{self, BufRead};
- use rand::thread_rng;
- use rand::seq::SliceRandom;
- use rand::distributions::{Distribution, WeightedIndex};
- pub fn create_array_source(filename: &str) -> Arc<dyn DataSource<String>> {
- let file = File::open(filename).unwrap();
- let lines = io::BufReader::new(file).lines();
- let mut questions: Vec<String> = Vec::new();
- for line in lines {
- if let Ok(l) = line {
- questions.push(l);
- }
- }
- Arc::new(ArraySource::create(questions))
- }
- pub trait DataSource<T> {
- fn get_ith(&self, i: usize) -> Option<T>;
- fn len(&self) -> usize;
- }
- pub struct ArraySource<T> {
- words: Vec<T>
- }
- impl<T: Clone> DataSource<T> for ArraySource<T> {
- fn get_ith(&self, i: usize) -> Option<T> {
- self.words.get(i).cloned()
- }
- fn len(&self) -> usize {
- self.words.len()
- }
- }
- impl<T> ArraySource<T> {
- pub fn create(words: Vec<T>) -> Self {
- ArraySource {
- words
- }
- }
- }
- pub struct SqliteSource {
- pool: Pool<SqliteConnectionManager>
- }
- impl DataSource<String> for SqliteSource {
- fn get_ith(& self, i: usize) -> Option<String> {
- match self.pool.get() {
- Ok(p) => {
- let r: rusqlite::Result<String> = p.query_row(
- "SELECT question
- FROM questions
- WHERE id=?1;",
- params![i as i32],
- |row| row.get(0));
- r.ok()
- },
- Err(_) => None
- }
- }
- fn len(&self) -> usize {
- match self.pool.get() {
- Ok(p) => {
- let r: rusqlite::Result<i32> = p.query_row(
- "SELECT COUNT(*)
- FROM questions;",
- rusqlite::NO_PARAMS,
- |row| row.get(0));
- r.unwrap_or(0) as usize
- },
- Err(_) => 0
- }
- }
- }
- impl SqliteSource {
- pub fn open(db_name: &str) -> Result<Self, r2d2::Error> {
- Ok(SqliteSource {
- pool: Pool::new(SqliteConnectionManager::file(db_name))?
- })
- }
- }
- pub struct Shuffler<T> {
- source: Arc<dyn DataSource<T>>,
- permutation: Vec<usize>,
- index: usize
- }
- impl<T> Shuffler<T> {
- pub fn create(source: Arc<dyn DataSource<T>>) -> Self {
- let mut permutation = (0..source.len()).collect::<Vec<_>>();
- permutation.shuffle(&mut thread_rng());
- Self {
- source,
- permutation,
- index: 0
- }
- }
- pub fn get(&mut self) -> T {
- let old_index = self.index;
- self.index += 1;
- if self.index >= self.permutation.len() {
- self.index = 0;
- }
- self.source.get_ith(self.permutation[old_index]).unwrap()
- }
- }
- pub struct LetterDistribution {
- consonants: Vec<char>,
- consonant_weights: WeightedIndex<f32>,
- vowels: Vec<char>,
- vowel_weights: WeightedIndex<f32>,
- }
- impl LetterDistribution {
- pub fn create() -> Self {
- Self {
- consonants: vec![
- 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'
- ],
- consonant_weights: WeightedIndex::new(vec![
- 4.5f32,
- 5.5f32,
- 6.5f32,
- 3.5f32,
- 5.0f32,
- 7.5f32,
- 1.0f32,
- 3.0f32,
- 5.0f32,
- 5.0f32,
- 13.0f32,
- 2.5f32,
- 1.0f32,
- 9.0f32,
- 8.5f32,
- 8.5f32,
- 2.5f32,
- 3.0f32,
- 1.0f32,
- 1.0f32,
- 3.5f32,
- ]).unwrap(),
- vowels: vec!['A', 'E', 'I', 'O', 'U', 'Ä', 'Ö', 'Ü'],
- vowel_weights: WeightedIndex::new(vec![
- 17.0f32,
- 32.0f32,
- 22.0f32,
- 10.0f32,
- 13.0f32,
- 2.0f32,
- 2.0f32,
- 2.0f32,
- ]).unwrap()
- }
- }
- pub fn get(&self, vowels: usize, consonants: usize) -> Vec<char> {
- let mut result: Vec<char> = Vec::new();
- let rng = &mut thread_rng();
- for _i in 0..vowels {
- result.push(self.vowels[self.vowel_weights.sample(rng)]);
- }
- for _i in 0..consonants {
- result.push(self.consonants[self.consonant_weights.sample(rng)]);
- }
- return result;
- }
- }
|