v1.2.0: can now weight the random selection of shows
This commit is contained in:
parent
b2b8b19c1b
commit
46b49ffda9
4 changed files with 165 additions and 14 deletions
18
src/main.rs
18
src/main.rs
|
@ -4,7 +4,11 @@ use anyhow::{anyhow, Context};
|
|||
use config::Config;
|
||||
use lazy_static::lazy_static;
|
||||
use log::{debug, error, info};
|
||||
use rand::{distributions::Standard, seq::IteratorRandom, Rng};
|
||||
use rand::{
|
||||
distributions::{Distribution, Standard, WeightedIndex},
|
||||
seq::IteratorRandom,
|
||||
Rng,
|
||||
};
|
||||
use shows::Shows;
|
||||
|
||||
mod config;
|
||||
|
@ -36,13 +40,16 @@ async fn main() -> anyhow::Result<()> {
|
|||
return Err(anyhow!("Shows file is empty!"));
|
||||
}
|
||||
|
||||
let dist = WeightedIndex::new(shows.iter().map(|s| s.weight))
|
||||
.context("Failed to load show weights")?;
|
||||
|
||||
info!("Logging into cohost as {}", conf.cohost_email);
|
||||
let session = eggbug::Session::login(&conf.cohost_email, &conf.cohost_password)
|
||||
.await
|
||||
.context("Failed to login to cohost")?;
|
||||
|
||||
loop {
|
||||
let result = post_random_screencap(&conf, &shows, &session, &mut rng)
|
||||
let result = post_random_screencap(&conf, &shows, &session, &dist, &mut rng)
|
||||
.await
|
||||
.context("Failed to post a random screencap");
|
||||
|
||||
|
@ -65,19 +72,20 @@ async fn post_random_screencap<R: Rng>(
|
|||
conf: &Config,
|
||||
shows: &Shows,
|
||||
session: &eggbug::Session,
|
||||
dist: &WeightedIndex<f32>,
|
||||
rng: &mut R,
|
||||
) -> anyhow::Result<()> {
|
||||
let (title, show) = shows.iter().choose(rng).unwrap();
|
||||
let show = &shows[dist.sample(rng)];
|
||||
let episodes = show.episodes().with_context(|| {
|
||||
format!(
|
||||
"Failed to get episode list for show {} with path {}",
|
||||
title,
|
||||
show.title,
|
||||
show.path.display()
|
||||
)
|
||||
})?;
|
||||
let (num, file) = episodes.iter().choose(rng).unwrap();
|
||||
|
||||
let descriptor = shows::display_show_episode(title, show, *num);
|
||||
let descriptor = shows::display_show_episode(show, *num);
|
||||
|
||||
info!("Selected: {} - {}", descriptor, file.display());
|
||||
|
||||
|
|
|
@ -7,19 +7,32 @@ use std::{
|
|||
use anyhow::{anyhow, Context};
|
||||
use log::{debug, error};
|
||||
use serde::Deserialize;
|
||||
use serde_with::{serde_as, KeyValueMap};
|
||||
|
||||
mod enumeration;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Show {
|
||||
#[serde(rename = "$key$")]
|
||||
pub title: String,
|
||||
pub path: PathBuf,
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub parts: HashMap<u32, String>,
|
||||
#[serde(default = "default_weight")]
|
||||
pub weight: f32,
|
||||
}
|
||||
|
||||
pub type Shows = HashMap<String, Show>;
|
||||
fn default_weight() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
pub type Shows = Vec<Show>;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Deserialize)]
|
||||
struct ShowsWrapper(#[serde_as(as = "KeyValueMap<_>")] Shows);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum EpisodeNumber {
|
||||
|
@ -31,17 +44,20 @@ pub enum EpisodeNumber {
|
|||
type Episodes = HashMap<EpisodeNumber, PathBuf>;
|
||||
|
||||
pub fn load<P: AsRef<Path>>(shows_file: P) -> anyhow::Result<Shows> {
|
||||
serde_yaml::from_reader(fs::File::open(shows_file).context("Failed to open shows file")?)
|
||||
.context("Failed to parse YAML from shows file")
|
||||
Ok(serde_yaml::from_reader::<_, ShowsWrapper>(
|
||||
fs::File::open(shows_file).context("Failed to open shows file")?,
|
||||
)
|
||||
.context("Failed to parse YAML from shows file")?
|
||||
.0)
|
||||
}
|
||||
|
||||
pub fn display_show_episode(title: &str, show: &Show, episode: EpisodeNumber) -> String {
|
||||
pub fn display_show_episode(show: &Show, episode: EpisodeNumber) -> String {
|
||||
match episode {
|
||||
EpisodeNumber::Standalone => title.to_string(),
|
||||
EpisodeNumber::SingleSeason(n) => format!("{} episode {}", title, n),
|
||||
EpisodeNumber::Standalone => show.title.to_string(),
|
||||
EpisodeNumber::SingleSeason(n) => format!("{} episode {}", show.title, n),
|
||||
EpisodeNumber::MultiSeason(season, ep) => format!(
|
||||
"{} {} episode {}",
|
||||
title,
|
||||
show.title,
|
||||
show.parts
|
||||
.get(&season)
|
||||
.unwrap_or(&format!("season {}", season)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue