little-sorry 0.1.0

Library to help with coding regret minimization.
Documentation
use crate::regret_matcher::RegretMatcher;
use lazy_static::*;
use ndarray::prelude::*;
use std::cmp;
use std::mem;

use std::vec::Vec;

#[allow(dead_code)]
#[repr(usize)]
#[derive(Debug)]
enum RPSAction {
    Rock = 0,
    Paper = 1,
    Scissors = 2,
}

lazy_static! {
    static ref ROCK_REWARD: Array1<f64> = array![0.0_f64, 1.0_f64, -1.0_f64];
    static ref PAPER_REWARD: Array1<f64> = array![-1.0_f64, 0.0_f64, 1.0_f64];
    static ref SCISSOR_REWARD: Array1<f64> = array![1.0_f64, -1.0_f64, 0.0_f64];
}
impl RPSAction {
    pub fn to_reward(&self) -> ArrayView1<f64> {
        match self {
            Self::Rock => ROCK_REWARD.view(),
            Self::Paper => PAPER_REWARD.view(),
            Self::Scissors => SCISSOR_REWARD.view(),
        }
    }
}

impl From<usize> for RPSAction {
    fn from(i: usize) -> Self {
        unsafe {
            mem::transmute(cmp::max(
                cmp::min(i, Self::Scissors as usize),
                Self::Rock as usize,
            ))
        }
    }
}

#[derive(Debug, Clone)]
pub struct RPSRunner {
    pub matcher_one: RegretMatcher,
    pub matcher_two: RegretMatcher,
}

impl Default for RPSRunner {
    #[must_use]
    fn default() -> Self {
        Self::new()
    }
}

impl RPSRunner {
    #[must_use]
    pub fn new() -> Self {
        Self {
            matcher_one: RegretMatcher::new(3),
            matcher_two: RegretMatcher::new(3),
        }
    }
    pub fn run_one(&mut self) {
        let a1 = RPSAction::from(self.matcher_one.next_action());
        let a2 = RPSAction::from(self.matcher_two.next_action());
        self.matcher_one.update_regret(a1.to_reward());
        self.matcher_two.update_regret(a2.to_reward())
    }
    #[must_use]
    pub fn best_weight(&self) -> Vec<f64> {
        self.matcher_one.best_weight()
    }
}