<commit_before>#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::thread;
use std::sync::mpsc::{channel, Sender};
use std::path::Path;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::io::SeekFrom;

mod models;

fn init_log() -> io::Result<()> {
    let log_config = b"[Achievements]
LogLevel=1
FilePrinting=true
ConsolePrinting=true
ScreenPrinting=false

[Power]
LogLevel=1
FilePrinting=true
ConsolePrinting=true
ScreenPrinting=false";

    let hs_dir = Path::new(r"C:\Program Files (x86)\Hearthstone\log.config");
    if !hs_dir.exists() {
        let mut handle = File::create(hs_dir)?;
        handle.write_all(log_config)?;
    }

    Ok(())
}

fn tail_log(tx: Sender<models::Play>) -> io::Result<()> {
    let hearthstone_path = Path::new(r"C:\Program Files (x86)\Hearthstone\Logs\Power.log");
    let mut handle = io::BufReader::new(File::open(hearthstone_path)?);
    handle.seek(SeekFrom::End(0))?;

    loop {
        let mut b = String::new();
        match handle.read_line(&mut b) {
            Ok(0) => {
                continue;
            }
            Ok(_) => {
                match parse_log_line(&b) {
                    Some(play) => tx.send(play).unwrap(),
                    _ => (),
                }
            }
            Err(err) => println!("Error!, {}", err),
        }
    }
}

fn parse_log_line(line: &str) -> Option<models::Play> {
    lazy_static! {<commit_msg>Sleep log thread when no new bytes are written<commit_after>#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::thread;
use std::sync::mpsc::{channel, Sender};
use std::path::Path;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::time::Duration;

mod models;

fn init_log() -> io::Result<()> {
    let log_config = b"[Achievements]
LogLevel=1
FilePrinting=true
ConsolePrinting=true
ScreenPrinting=false

[Power]
LogLevel=1
FilePrinting=true
ConsolePrinting=true
ScreenPrinting=false";

    let hs_dir = Path::new(r"C:\Program Files (x86)\Hearthstone\log.config");
    if !hs_dir.exists() {
        let mut handle = File::create(hs_dir)?;
        handle.write_all(log_config)?;
    }

    Ok(())
}

fn tail_log(tx: Sender<models::Play>) -> io::Result<()> {
    let hearthstone_path = Path::new(r"C:\Program Files (x86)\Hearthstone\Logs\Power.log");
    let mut handle = io::BufReader::new(File::open(hearthstone_path)?);
    handle.seek(SeekFrom::End(0))?;

    loop {
        let mut b = String::new();
        match handle.read_line(&mut b) {
            Ok(0) => {
                thread::sleep(Duration::from_millis(250));
            }
            Ok(_) => {
                match parse_log_line(&b) {
                    Some(play) => tx.send(play).unwrap(),
                    _ => (),
                }
            }
            Err(err) => println!("Error!, {}", err),
        }
    }
}

fn parse_log_line(line: &str) -> Option<models::Play> {
    lazy_static! {
{'fraction_non_alphanumeric': 0.16897133220910623, 'fraction_numerical': 0.0064080944350758855, 'mean_word_length': 2.8270967741935484, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1396139', 'n_tokens_mistral': 1045, 'n_tokens_neox': 1019, 'n_words': 188}