use rand;
use std::sync::{Arc, RwLock};
use core::Pixels;
use scanline::Scanline;
use shape::{Shape, ShapeType};
use state::State;
pub struct Worker {
pub w: usize,
pub h: usize,
pub target: Arc<Pixels>,
pub current: Arc<RwLock<Pixels>>,
pub buffer: Pixels,
pub rng: rand::StdRng,
pub scanlines: Vec<Scanline>,
pub score: f32,
}
unsafe impl Sync for Worker {}
impl Worker {
pub fn new(target: Arc<Pixels>, current: Arc<RwLock<Pixels>>) -> Worker {
let w = target.w;
let h = target.h;
let buffer = Pixels::new(w, h);
let rng = rand::StdRng::new().expect("wtf");
let scanlines = Scanline::buffer(h);
let score = -1.0;
Worker { w, h, target, current, buffer, rng, scanlines, score }
}
pub fn init(&mut self, score: f32) {
self.score = score;
}
pub fn energy(&mut self, shape: &Shape, alpha: u8) -> f32 {
let lines = shape.rasterize(self.w, self.h, &mut self.scanlines);
let current = self.current.read().unwrap();
let color = current.compute_color(self.target.as_ref(), lines, alpha);
self.buffer.copy_lines(¤t, lines);
self.buffer.draw_lines(&color, lines);
Pixels::difference_partial(&self.target, ¤t, &self.buffer, self.score, lines)
}
pub fn best_hill_climb_state(&mut self, t: ShapeType, a: u8, n: u32, m: u8) -> State {
let mut state = self.best_random_state(t, a, n);
self.hill_climb(&mut state, 100);
let mut best_state = state.clone();
let mut best_energy = best_state.energy(self);
for _ in 1..m {
state = self.best_random_state(t, a, n);
self.hill_climb(&mut state, 100);
let energy = state.energy(self);
if energy < best_energy {
best_energy = energy;
best_state.copy_from(&state);
}
}
best_state
}
pub fn hill_climb(&mut self, state: &mut State, max_age: i32) {
let mut undo = state.clone();
let mut best_state = state.clone();
let mut best_energy = best_state.energy(self);
let mut age = 0;
while age < max_age {
state.do_move(self, &mut undo);
let energy = state.energy(self);
if energy > best_energy {
state.copy_from(&undo);
} else {
best_energy = energy;
best_state.copy_from(state);
age -= 1;
}
age += 1;
}
state.copy_from(&best_state);
}
pub fn best_random_state(&mut self, t: ShapeType, a: u8, n: u32) -> State {
let mut best_state = self.random_state(t, a);
let mut best_energy = best_state.energy(self);
for _ in 1..n {
let mut state = self.random_state(t, a);
let energy = state.energy(self);
if energy < best_energy {
best_energy = energy;
best_state = state;
}
}
best_state
}
pub fn random_state(&mut self, t: ShapeType, alpha: u8) -> State {
let shape = Shape::random(t, self.w, self.h, &mut self.rng);
State::new(shape, alpha)
}
}