use std::time::{SystemTime, UNIX_EPOCH};
use super::database_structs::{Command, Database, DeletedCommands};
fn get_score(command: &Command) -> i32 {
let now = SystemTime::now();
let current_time: i64 = now.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64;
let time_difference: i64 = current_time - command.last_access_time;
let mult: f64;
if time_difference <= 3600 {
mult=4.0;
}
else if time_difference <= 86400 {
mult=2.0;
}
else if time_difference <= 604800 {
mult=0.5;
}
else {
mult=0.25;
}
let length = command.length as f64;
let frequency = command.frequency as f64;
(mult * length.powf(3.0 / 5.0) * frequency) as i32
}
impl Database {
pub fn add_command(&mut self, command_str: String, deleted_commands: &DeletedCommands) {
if !deleted_commands.deleted_commands.contains(&command_str) {
if let Some(existing_command) = self.reverse_command_map.get(&command_str) {
let mut updated_command = existing_command.clone();
self.total_score -= updated_command.score as i64;
self.total_num_commands -= 1;
updated_command.add();
self.command_list.remove(existing_command);
self.reverse_command_map.remove(&command_str);
self.command_list.insert(updated_command.clone());
self.reverse_command_map.insert(command_str.clone(), updated_command);
self.total_num_commands += 1;
self.total_score += self.reverse_command_map.get(&command_str).unwrap().score as i64;
} else {
let new_command: Command = Command::new(command_str.clone());
if new_command.length <= 5 && new_command.number_of_words == 1 {
return; }
self.command_list.insert(new_command.clone());
self.reverse_command_map.insert(command_str.clone(), new_command);
self.total_num_commands += 1;
self.total_score += self.reverse_command_map.get(&command_str).unwrap().score as i64;
}
let threshold: i64 = 70000; if self.total_score > threshold {
self.score_reset();
}
}
}
pub fn add_command_with_existing(&mut self, command: Command) {
if self.reverse_command_map.contains_key(&command.command_text) {
if let Some(existing_command) = self.reverse_command_map.get(&command.command_text) {
let mut updated_command = existing_command.clone();
self.total_score -= updated_command.score as i64;
self.total_num_commands -= 1;
updated_command.frequency += command.frequency;
updated_command.score = get_score(&updated_command);
self.command_list.remove(existing_command);
self.reverse_command_map.remove(&command.command_text);
self.command_list.insert(updated_command.clone());
self.reverse_command_map.insert(command.command_text.clone(), updated_command);
self.total_num_commands += 1;
self.total_score += self.reverse_command_map.get(&command.command_text).unwrap().score as i64;
}
} else {
if command.length <= 5 && command.number_of_words == 1 {
return; }
let score = command.score;
self.command_list.insert(command.clone());
self.reverse_command_map.insert(command.command_text.clone(), command);
self.total_num_commands += 1;
self.total_score += score as i64;
}
let threshold: i64 = 70000; if self.total_score > threshold {
self.score_reset();
}
}
pub fn remove_command(&mut self, command_str: &String, deleted_commands: &mut DeletedCommands) {
if !deleted_commands.deleted_commands.contains(command_str) {
deleted_commands
.deleted_commands
.insert(command_str.clone());
let command_to_remove = self.reverse_command_map.get(command_str);
if let Some(cmd) = command_to_remove {
self.command_list.remove(cmd);
self.total_num_commands -= 1;
self.total_score -= cmd.score as i64;
self.reverse_command_map.remove(command_str);
}
}
}
pub fn update_db(&mut self) {
let keys: Vec<String> = self.reverse_command_map.keys().cloned().collect();
for key in keys {
if let Some(command) = self.reverse_command_map.get_mut(&key) {
self.total_score -= command.score as i64;
command.update();
self.total_score += command.score as i64;
self.command_list.remove(command);
self.command_list.insert(command.clone());
}
}
let threshold: i64 = 70000; if self.total_score > threshold {
self.score_reset();
}
}
pub fn get_top_commands(&mut self, n: Option<usize>) -> Vec<&Command> {
let n = n.unwrap_or(5);
self.command_list.iter().take(n).collect()
}
pub fn score_reset(&mut self){
let mut to_remove = Vec::new();
let mut num:i32 =0;
let mut sc:i64=0;
for (key, value) in self.reverse_command_map.iter_mut() {
value.frequency = (value.frequency as f32 * 0.5).round() as i32; self.total_score -= value.score as i64;
value.score = get_score(&value);
sc+= value.score as i64;
if value.frequency < 1 {
self.total_num_commands-=1;
to_remove.push(key.clone());
}
else {num+=1;}
}
self.total_score = sc;
self.total_num_commands = num;
for key in &to_remove {
self.reverse_command_map.remove(key);
}
let old_set = std::mem::take(&mut self.command_list);
for mut cmd in old_set {
cmd.frequency = (cmd.frequency as f32 * 0.5).round() as i32; cmd.score=get_score(&cmd);
if cmd.frequency>0 {self.command_list.insert(cmd);}
}
}
}
impl Command {
pub fn new(command_text: String) -> Self {
let length: i16 = command_text.split_whitespace().map(|s| s.len()).sum::<usize>() as i16;
let number_of_words: i8 = command_text.split_whitespace().count() as i8;
let frequency: i32 = 1;
let now = SystemTime::now();
let last_access_time: i64 = now.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64;
let temp_command = Command {
last_access_time,
frequency,
length,
score: 0, command_text: command_text.clone(),
number_of_words,
};
let score = get_score(&temp_command);
Command {
last_access_time,
frequency,
length,
score,
command_text,
number_of_words,
}
}
pub fn add(&mut self) {
let now = SystemTime::now();
self.last_access_time = now.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64; self.frequency += 1;
self.score = get_score(self);
}
pub fn update (&mut self) {
self.score = get_score(self);
}
}