Nicely format imports
This commit is contained in:
parent
0e0043d2c1
commit
50f8db4e2e
|
@ -1,17 +1,15 @@
|
|||
// {{{ Imports
|
||||
use anyhow::anyhow;
|
||||
use image::RgbaImage;
|
||||
|
||||
use crate::{
|
||||
assets::get_data_dir,
|
||||
context::{Error, UserContext},
|
||||
user::User,
|
||||
};
|
||||
use crate::assets::get_data_dir;
|
||||
use crate::context::{Error, UserContext};
|
||||
use crate::user::User;
|
||||
|
||||
use super::{
|
||||
chart::{Difficulty, Level},
|
||||
play::get_best_plays,
|
||||
score::{Grade, ScoringSystem},
|
||||
};
|
||||
use super::chart::{Difficulty, Level};
|
||||
use super::play::get_best_plays;
|
||||
use super::score::{Grade, ScoringSystem};
|
||||
// }}}
|
||||
|
||||
// {{{ Goal
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// {{{ Imports
|
||||
use std::{fmt::Display, num::NonZeroU16, path::PathBuf};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use image::{ImageBuffer, Rgb};
|
||||
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ValueRef};
|
||||
|
||||
use crate::{
|
||||
bitmap::Color,
|
||||
context::{DbConnection, Error},
|
||||
};
|
||||
use crate::bitmap::Color;
|
||||
use crate::context::{DbConnection, Error};
|
||||
// }}}
|
||||
|
||||
// {{{ Difficuly
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// {{{ Imports
|
||||
use std::fs;
|
||||
|
||||
use anyhow::Context;
|
||||
|
@ -6,11 +7,10 @@ use num::Integer;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::serde_as;
|
||||
|
||||
use crate::{
|
||||
arcaea::chart::{Difficulty, Jacket, SongCache},
|
||||
assets::{get_asset_dir, should_skip_jacket_art},
|
||||
context::Error,
|
||||
};
|
||||
use crate::arcaea::chart::{Difficulty, Jacket, SongCache};
|
||||
use crate::assets::{get_asset_dir, should_skip_jacket_art};
|
||||
use crate::context::Error;
|
||||
// }}}
|
||||
|
||||
/// How many sub-segments to split each side into
|
||||
pub const SPLIT_FACTOR: u32 = 8;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// {{{ Imports
|
||||
use std::array;
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
|
@ -17,6 +18,7 @@ use crate::user::User;
|
|||
|
||||
use super::rating::{rating_as_fixed, rating_as_float};
|
||||
use super::score::{Score, ScoringSystem};
|
||||
// }}}
|
||||
|
||||
// {{{ Create play
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// {{{ Imports
|
||||
use std::fmt::{Display, Write};
|
||||
|
||||
use num::{Rational32, Rational64};
|
||||
|
||||
use crate::context::Error;
|
||||
|
||||
use super::{
|
||||
chart::Chart,
|
||||
rating::{rating_as_float, rating_from_fixed, Rating},
|
||||
};
|
||||
use super::chart::Chart;
|
||||
use super::rating::{rating_as_float, rating_from_fixed, Rating};
|
||||
// }}}
|
||||
|
||||
// {{{ Scoring system
|
||||
#[derive(Debug, Clone, Copy, poise::ChoiceParameter)]
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
use std::{
|
||||
cell::RefCell,
|
||||
env::var,
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
sync::{LazyLock, OnceLock},
|
||||
thread::LocalKey,
|
||||
};
|
||||
// {{{ Imports
|
||||
use std::cell::RefCell;
|
||||
use std::env::var;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{LazyLock, OnceLock};
|
||||
use std::thread::LocalKey;
|
||||
|
||||
use freetype::{Face, Library};
|
||||
use image::{DynamicImage, RgbaImage};
|
||||
|
||||
use crate::{arcaea::chart::Difficulty, timed};
|
||||
use crate::arcaea::chart::Difficulty;
|
||||
use crate::timed;
|
||||
// }}}
|
||||
|
||||
// {{{ Path helpers
|
||||
#[inline]
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
//!
|
||||
//! There's still stuff to be implemented here, like a cache for glyphs and
|
||||
//! whatnot, but this does run pretty stably for the b30 renderer.
|
||||
|
||||
// {{{ Imports
|
||||
use anyhow::anyhow;
|
||||
use freetype::{
|
||||
bitmap::PixelMode,
|
||||
face::{KerningMode, LoadFlag},
|
||||
ffi::{FT_Set_Var_Design_Coordinates, FT_GLYPH_BBOX_PIXELS},
|
||||
Bitmap, BitmapGlyph, Face, Glyph, StrokerLineCap, StrokerLineJoin,
|
||||
};
|
||||
use freetype::bitmap::PixelMode;
|
||||
use freetype::face::{KerningMode, LoadFlag};
|
||||
use freetype::ffi::{FT_Set_Var_Design_Coordinates, FT_GLYPH_BBOX_PIXELS};
|
||||
use freetype::{Bitmap, BitmapGlyph, Face, Glyph, StrokerLineCap, StrokerLineJoin};
|
||||
use image::{GenericImage, RgbImage, RgbaImage};
|
||||
use num::traits::Euclid;
|
||||
|
||||
use crate::{assets::FREETYPE_LIB, context::Error};
|
||||
use crate::assets::FREETYPE_LIB;
|
||||
use crate::context::Error;
|
||||
// }}}
|
||||
|
||||
// {{{ Color
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// {{{ Imports
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{
|
||||
cli::context::CliContext,
|
||||
commands::score::magic_impl,
|
||||
context::{Error, UserContext},
|
||||
};
|
||||
use crate::cli::context::CliContext;
|
||||
use crate::commands::score::magic_impl;
|
||||
use crate::context::{Error, UserContext};
|
||||
// }}}
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub struct Args {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// {{{ Imports
|
||||
use std::num::NonZeroU64;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
@ -7,7 +8,13 @@ use poise::serenity_prelude::{CreateAttachment, CreateMessage};
|
|||
use crate::assets::get_var;
|
||||
use crate::context::Error;
|
||||
use crate::{commands::discord::MessageContext, context::UserContext};
|
||||
// }}}
|
||||
|
||||
/// Similar in scope to [crate::commands::discord::mock::MockContext],
|
||||
/// except replies and messages are printed to the standard output.
|
||||
///
|
||||
/// Attachments are ignored, and [CreateMessage] values are printed
|
||||
/// as TOML.
|
||||
pub struct CliContext {
|
||||
pub user_id: u64,
|
||||
pub data: UserContext,
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
use std::{
|
||||
fs,
|
||||
io::{stdout, Write},
|
||||
};
|
||||
// {{{ Imports
|
||||
use std::fs;
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
use anyhow::{anyhow, bail, Context};
|
||||
use image::imageops::FilterType;
|
||||
|
||||
use crate::{
|
||||
arcaea::{
|
||||
chart::{Difficulty, SongCache},
|
||||
jacket::{ImageVec, BITMAP_IMAGE_SIZE},
|
||||
},
|
||||
assets::{get_asset_dir, get_data_dir},
|
||||
context::{connect_db, Error},
|
||||
recognition::fuzzy_song_name::guess_chart_name,
|
||||
};
|
||||
use crate::arcaea::chart::{Difficulty, SongCache};
|
||||
use crate::arcaea::jacket::{ImageVec, BITMAP_IMAGE_SIZE};
|
||||
use crate::assets::{get_asset_dir, get_data_dir};
|
||||
use crate::context::{connect_db, Error};
|
||||
use crate::recognition::fuzzy_song_name::guess_chart_name;
|
||||
// }}}
|
||||
|
||||
/// Hacky function which clears the current line of the standard output.
|
||||
#[inline]
|
||||
fn clear_line() {
|
||||
print!("\r \r");
|
||||
|
|
|
@ -1,32 +1,27 @@
|
|||
// {{{ Imports
|
||||
use anyhow::anyhow;
|
||||
use poise::serenity_prelude::{CreateAttachment, CreateEmbed, CreateMessage};
|
||||
|
||||
use crate::{
|
||||
arcaea::{chart::Side, play::Play},
|
||||
context::{Context, Error},
|
||||
get_user,
|
||||
recognition::fuzzy_song_name::guess_song_and_chart,
|
||||
};
|
||||
use crate::arcaea::{chart::Side, play::Play};
|
||||
use crate::context::{Context, Error};
|
||||
use crate::get_user;
|
||||
use crate::recognition::fuzzy_song_name::guess_song_and_chart;
|
||||
use std::io::Cursor;
|
||||
|
||||
use chrono::DateTime;
|
||||
use image::{ImageBuffer, Rgb};
|
||||
use plotters::{
|
||||
backend::{BitMapBackend, PixelFormat, RGBPixel},
|
||||
chart::{ChartBuilder, LabelAreaPosition},
|
||||
drawing::IntoDrawingArea,
|
||||
element::Circle,
|
||||
series::LineSeries,
|
||||
style::{IntoFont, TextStyle, BLUE, WHITE},
|
||||
};
|
||||
use plotters::backend::{BitMapBackend, PixelFormat, RGBPixel};
|
||||
use plotters::chart::{ChartBuilder, LabelAreaPosition};
|
||||
use plotters::drawing::IntoDrawingArea;
|
||||
use plotters::element::Circle;
|
||||
use plotters::series::LineSeries;
|
||||
use plotters::style::{IntoFont, TextStyle, BLUE, WHITE};
|
||||
use poise::CreateReply;
|
||||
|
||||
use crate::{
|
||||
arcaea::score::{Score, ScoringSystem},
|
||||
user::discord_id_to_discord_user,
|
||||
};
|
||||
use crate::arcaea::score::{Score, ScoringSystem};
|
||||
|
||||
use super::discord::MessageContext;
|
||||
// }}}
|
||||
|
||||
// {{{ Top command
|
||||
/// Chart-related stats
|
||||
|
@ -134,7 +129,7 @@ mod info_tests {
|
|||
}
|
||||
}
|
||||
// }}}
|
||||
|
||||
// {{{ Discord wrapper
|
||||
/// Show a chart given it's name
|
||||
#[poise::command(prefix_command, slash_command, user_cooldown = 1)]
|
||||
async fn info(
|
||||
|
@ -148,6 +143,7 @@ async fn info(
|
|||
Ok(())
|
||||
}
|
||||
// }}}
|
||||
// }}}
|
||||
// {{{ Best score
|
||||
/// Show the best score on a given chart
|
||||
#[poise::command(prefix_command, slash_command, user_cooldown = 1)]
|
||||
|
@ -193,7 +189,7 @@ async fn best(
|
|||
song,
|
||||
chart,
|
||||
0,
|
||||
Some(&discord_id_to_discord_user(&ctx, &user.discord_id).await?),
|
||||
Some(&ctx.fetch_user(&user.discord_id).await?),
|
||||
)?;
|
||||
|
||||
ctx.channel_id()
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use std::{num::NonZeroU64, str::FromStr};
|
||||
// {{{ Imports
|
||||
use std::num::NonZeroU64;
|
||||
use std::str::FromStr;
|
||||
|
||||
use poise::serenity_prelude::{futures::future::join_all, CreateAttachment, CreateMessage};
|
||||
use poise::serenity_prelude::futures::future::join_all;
|
||||
use poise::serenity_prelude::{CreateAttachment, CreateMessage};
|
||||
|
||||
use crate::{
|
||||
arcaea::play::Play,
|
||||
context::{Error, UserContext},
|
||||
timed,
|
||||
};
|
||||
use crate::arcaea::play::Play;
|
||||
use crate::context::{Error, UserContext};
|
||||
use crate::timed;
|
||||
// }}}
|
||||
|
||||
// {{{ Trait
|
||||
pub trait MessageContext {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// {{{ Imports
|
||||
use crate::arcaea::play::{CreatePlay, Play};
|
||||
use crate::arcaea::score::Score;
|
||||
use crate::context::{Context, Error};
|
||||
|
@ -10,6 +11,7 @@ use poise::serenity_prelude as serenity;
|
|||
use poise::serenity_prelude::CreateMessage;
|
||||
|
||||
use super::discord::MessageContext;
|
||||
// }}}
|
||||
|
||||
// {{{ Score
|
||||
/// Score management
|
||||
|
|
|
@ -1,34 +1,28 @@
|
|||
// {{{ Imports
|
||||
use std::io::Cursor;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use image::{DynamicImage, ImageBuffer};
|
||||
use poise::{
|
||||
serenity_prelude::{CreateAttachment, CreateEmbed},
|
||||
CreateReply,
|
||||
};
|
||||
use poise::serenity_prelude::{CreateAttachment, CreateEmbed};
|
||||
use poise::CreateReply;
|
||||
|
||||
use crate::{
|
||||
arcaea::{
|
||||
achievement::GoalStats,
|
||||
chart::Level,
|
||||
jacket::BITMAP_IMAGE_SIZE,
|
||||
play::{compute_b30_ptt, get_best_plays},
|
||||
rating::rating_as_float,
|
||||
score::ScoringSystem,
|
||||
},
|
||||
assert_is_pookie,
|
||||
assets::{
|
||||
get_difficulty_background, with_font, B30_BACKGROUND, COUNT_BACKGROUND, EXO_FONT,
|
||||
GRADE_BACKGROUND, NAME_BACKGROUND, PTT_EMBLEM, SCORE_BACKGROUND, STATUS_BACKGROUND,
|
||||
TOP_BACKGROUND,
|
||||
},
|
||||
bitmap::{Align, BitmapCanvas, Color, LayoutDrawer, LayoutManager, Rect},
|
||||
context::{Context, Error},
|
||||
get_user,
|
||||
logs::debug_image_log,
|
||||
reply_errors, timed,
|
||||
user::User,
|
||||
use crate::arcaea::achievement::GoalStats;
|
||||
use crate::arcaea::chart::Level;
|
||||
use crate::arcaea::jacket::BITMAP_IMAGE_SIZE;
|
||||
use crate::arcaea::play::{compute_b30_ptt, get_best_plays};
|
||||
use crate::arcaea::rating::rating_as_float;
|
||||
use crate::arcaea::score::ScoringSystem;
|
||||
use crate::assets::{
|
||||
get_difficulty_background, with_font, B30_BACKGROUND, COUNT_BACKGROUND, EXO_FONT,
|
||||
GRADE_BACKGROUND, NAME_BACKGROUND, PTT_EMBLEM, SCORE_BACKGROUND, STATUS_BACKGROUND,
|
||||
TOP_BACKGROUND,
|
||||
};
|
||||
use crate::bitmap::{Align, BitmapCanvas, Color, LayoutDrawer, LayoutManager, Rect};
|
||||
use crate::context::{Context, Error};
|
||||
use crate::logs::debug_image_log;
|
||||
use crate::user::User;
|
||||
use crate::{assert_is_pookie, get_user, reply_errors, timed};
|
||||
// }}}
|
||||
|
||||
// {{{ Stats
|
||||
/// Stats display
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// {{{ Imports
|
||||
use include_dir::{include_dir, Dir};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
|
@ -6,34 +7,19 @@ use std::fs;
|
|||
use std::path::Path;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use crate::{
|
||||
arcaea::{chart::SongCache, jacket::JacketCache},
|
||||
assets::{get_data_dir, EXO_FONT, GEOSANS_FONT, KAZESAWA_BOLD_FONT, KAZESAWA_FONT},
|
||||
recognition::{hyperglass::CharMeasurements, ui::UIMeasurements},
|
||||
timed,
|
||||
};
|
||||
use crate::arcaea::{chart::SongCache, jacket::JacketCache};
|
||||
use crate::assets::{get_data_dir, EXO_FONT, GEOSANS_FONT, KAZESAWA_BOLD_FONT, KAZESAWA_FONT};
|
||||
use crate::recognition::{hyperglass::CharMeasurements, ui::UIMeasurements};
|
||||
use crate::timed;
|
||||
// }}}
|
||||
|
||||
// Types used by all command functions
|
||||
// {{{ Common types
|
||||
pub type Error = anyhow::Error;
|
||||
pub type Context<'a> = poise::Context<'a, UserContext, Error>;
|
||||
|
||||
// }}}
|
||||
// {{{ DB connection
|
||||
pub type DbConnection = r2d2::Pool<SqliteConnectionManager>;
|
||||
|
||||
// Custom user data passed to all command functions
|
||||
#[derive(Clone)]
|
||||
pub struct UserContext {
|
||||
pub db: DbConnection,
|
||||
pub song_cache: SongCache,
|
||||
pub jacket_cache: JacketCache,
|
||||
pub ui_measurements: UIMeasurements,
|
||||
|
||||
pub geosans_measurements: CharMeasurements,
|
||||
pub exo_measurements: CharMeasurements,
|
||||
// TODO: do we really need both after I've fixed the bug in the ocr code?
|
||||
pub kazesawa_measurements: CharMeasurements,
|
||||
pub kazesawa_bold_measurements: CharMeasurements,
|
||||
}
|
||||
|
||||
pub fn connect_db(data_dir: &Path) -> DbConnection {
|
||||
fs::create_dir_all(data_dir).expect("Could not create $SHIMMERING_DATA_DIR");
|
||||
|
||||
|
@ -52,6 +38,22 @@ pub fn connect_db(data_dir: &Path) -> DbConnection {
|
|||
|
||||
Pool::new(SqliteConnectionManager::file(&db_path)).expect("Could not open sqlite database.")
|
||||
}
|
||||
// }}}
|
||||
// {{{ UserContext
|
||||
/// Custom user data passed to all command functions
|
||||
#[derive(Clone)]
|
||||
pub struct UserContext {
|
||||
pub db: DbConnection,
|
||||
pub song_cache: SongCache,
|
||||
pub jacket_cache: JacketCache,
|
||||
pub ui_measurements: UIMeasurements,
|
||||
|
||||
pub geosans_measurements: CharMeasurements,
|
||||
pub exo_measurements: CharMeasurements,
|
||||
// TODO: do we really need both after I've fixed the bug in the ocr code?
|
||||
pub kazesawa_measurements: CharMeasurements,
|
||||
pub kazesawa_bold_measurements: CharMeasurements,
|
||||
}
|
||||
|
||||
impl UserContext {
|
||||
#[inline]
|
||||
|
@ -89,7 +91,8 @@ impl UserContext {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ Testing helpers
|
||||
#[cfg(test)]
|
||||
pub mod testing {
|
||||
use super::*;
|
||||
|
@ -137,3 +140,4 @@ pub mod testing {
|
|||
}};
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
|
|
@ -21,20 +21,18 @@
|
|||
//! aforementioned precomputed vectors are generated using almost the exact
|
||||
//! procedure described in steps 1-6, except the images are generated at
|
||||
//! startup using my very own bitmap rendering module (`crate::bitmap`).
|
||||
// {{{ Imports
|
||||
use anyhow::{anyhow, bail};
|
||||
use freetype::Face;
|
||||
use image::{DynamicImage, ImageBuffer, Luma};
|
||||
use imageproc::{
|
||||
contrast::{threshold, ThresholdType},
|
||||
region_labelling::{connected_components, Connectivity},
|
||||
};
|
||||
use imageproc::contrast::{threshold, ThresholdType};
|
||||
use imageproc::region_labelling::{connected_components, Connectivity};
|
||||
use num::traits::Euclid;
|
||||
|
||||
use crate::{
|
||||
bitmap::{Align, BitmapCanvas, Color, TextStyle},
|
||||
context::Error,
|
||||
logs::{debug_image_buffer_log, debug_image_log},
|
||||
};
|
||||
use crate::bitmap::{Align, BitmapCanvas, Color, TextStyle};
|
||||
use crate::context::Error;
|
||||
use crate::logs::{debug_image_buffer_log, debug_image_log};
|
||||
// }}}
|
||||
|
||||
// {{{ ConponentVec
|
||||
/// How many sub-segments to split each side into
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// {{{ Imports
|
||||
use std::fmt::Display;
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
|
@ -20,6 +21,7 @@ use crate::recognition::ui::{
|
|||
ScoreScreenRect, SongSelectRect, UIMeasurementRect, UIMeasurementRect::*,
|
||||
};
|
||||
use crate::transform::rotate;
|
||||
// }}}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ScoreKind {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
// {{{ Imports
|
||||
use std::fs;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use image::GenericImage;
|
||||
|
||||
use crate::{assets::get_config_dir, bitmap::Rect, context::Error};
|
||||
use crate::assets::get_config_dir;
|
||||
use crate::bitmap::Rect;
|
||||
use crate::context::Error;
|
||||
// }}}
|
||||
|
||||
// {{{ Rects
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
20
src/user.rs
20
src/user.rs
|
@ -1,13 +1,8 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use poise::serenity_prelude::UserId;
|
||||
use rusqlite::Row;
|
||||
|
||||
use crate::{
|
||||
commands::discord::MessageContext,
|
||||
context::{Context, Error, UserContext},
|
||||
};
|
||||
use crate::commands::discord::MessageContext;
|
||||
use crate::context::{Error, UserContext};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct User {
|
||||
|
@ -75,14 +70,3 @@ impl User {
|
|||
Ok(user)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn discord_id_to_discord_user(
|
||||
&ctx: &Context<'_>,
|
||||
discord_id: &str,
|
||||
) -> Result<poise::serenity_prelude::User, Error> {
|
||||
UserId::from_str(discord_id)?
|
||||
.to_user(ctx.http())
|
||||
.await
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue