feat: convert music detail to dxrating
This commit is contained in:
99
sdgb-api/src/title/model/dxrating/conversion/mod.rs
Normal file
99
sdgb-api/src/title/model/dxrating/conversion/mod.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use crate::{
|
||||
helper::query_music,
|
||||
title::model::{
|
||||
dxrating::{DxCalculatedEntries, DxLevelName, DxMusicRecord, DxSheetId},
|
||||
get_user_music_api::UserMusicDetail,
|
||||
get_user_rating_api::{MusicRating, UserRating},
|
||||
},
|
||||
};
|
||||
|
||||
impl DxCalculatedEntries {
|
||||
pub fn from_user_rating_lossy(rating: &UserRating) -> DxCalculatedEntries {
|
||||
let b35 = rating
|
||||
.rating_list
|
||||
.iter()
|
||||
.map(DxMusicRecord::try_from)
|
||||
.flatten()
|
||||
.collect();
|
||||
let b15 = rating
|
||||
.new_rating_list
|
||||
.iter()
|
||||
.map(DxMusicRecord::try_from)
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
DxCalculatedEntries { b35, b15 }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for DxLevelName {
|
||||
type Error = ConversionError;
|
||||
|
||||
fn try_from(level: u32) -> Result<Self, Self::Error> {
|
||||
Self::from_repr(level).ok_or(ConversionError::UnknownDifficulty { level })
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&UserMusicDetail> for DxMusicRecord {
|
||||
type Error = ConversionError;
|
||||
|
||||
fn try_from(
|
||||
&UserMusicDetail {
|
||||
music_id,
|
||||
level,
|
||||
achievement,
|
||||
..
|
||||
}: &UserMusicDetail,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let music_title = query_music(music_id)
|
||||
.map(|info| info.name.clone())
|
||||
.ok_or(ConversionError::MusicNotInDB)?;
|
||||
|
||||
Ok(Self {
|
||||
sheet_id: DxSheetId {
|
||||
music_title,
|
||||
level: DxLevelName::try_from(level)?,
|
||||
dx_version: music_id >= 10000,
|
||||
},
|
||||
achievement_rate: (achievement as f64) / 10000.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&MusicRating> for DxMusicRecord {
|
||||
type Error = ConversionError;
|
||||
|
||||
fn try_from(
|
||||
&MusicRating {
|
||||
music_id,
|
||||
level,
|
||||
achievement,
|
||||
..
|
||||
}: &MusicRating,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let music_title = query_music(music_id)
|
||||
.map(|info| info.name.clone())
|
||||
.ok_or(ConversionError::MusicNotInDB)?;
|
||||
|
||||
Ok(Self {
|
||||
sheet_id: DxSheetId {
|
||||
music_title,
|
||||
level: DxLevelName::try_from(level)?,
|
||||
dx_version: music_id >= 10000,
|
||||
},
|
||||
achievement_rate: (achievement as f64) / 10000.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, snafu::Snafu)]
|
||||
pub enum ConversionError {
|
||||
#[snafu(display("Music was not found in database"))]
|
||||
MusicNotInDB,
|
||||
|
||||
#[snafu(display("Utage difficulty was disallowed"))]
|
||||
UtageDifficulty,
|
||||
|
||||
#[snafu(display("Unknown difficulty: {level}"))]
|
||||
UnknownDifficulty { level: u32 },
|
||||
}
|
||||
95
sdgb-api/src/title/model/dxrating/mod.rs
Normal file
95
sdgb-api/src/title/model/dxrating/mod.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
use serde::Serialize;
|
||||
|
||||
/// Full payload for image generate api
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DxRatingNet {
|
||||
pub calculated_entries: DxCalculatedEntries,
|
||||
|
||||
pub version: DataVersion,
|
||||
/// use `_generic`
|
||||
pub region: &'static str,
|
||||
}
|
||||
|
||||
/// Export/Import format
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DxCalculatedEntries {
|
||||
pub b35: Vec<DxMusicRecord>,
|
||||
pub b15: Vec<DxMusicRecord>,
|
||||
}
|
||||
|
||||
/// full music record
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DxMusicRecord {
|
||||
pub sheet_id: DxSheetId,
|
||||
pub achievement_rate: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct DxSheetId {
|
||||
pub music_title: String,
|
||||
pub dx_version: bool,
|
||||
pub level: DxLevelName,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, strum::IntoStaticStr, strum::FromRepr)]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
#[repr(u32)]
|
||||
pub enum DxLevelName {
|
||||
Basic,
|
||||
Advanced,
|
||||
Expert,
|
||||
Master,
|
||||
ReMaster,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum DataVersion {
|
||||
Buddies,
|
||||
BuddiesPlus,
|
||||
Prism,
|
||||
PrismPlus,
|
||||
}
|
||||
|
||||
impl Serialize for DataVersion {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(match self {
|
||||
DataVersion::Buddies => "BUDDiES",
|
||||
DataVersion::BuddiesPlus => "BUDDiES PLUS",
|
||||
DataVersion::Prism => "PRiSM",
|
||||
DataVersion::PrismPlus => "PRiSM PLUS",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for DxSheetId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for DxSheetId {
|
||||
fn to_string(&self) -> String {
|
||||
let mut output = self.music_title.clone();
|
||||
|
||||
if self.dx_version {
|
||||
output += "__dxrt__dx__dxrt__"
|
||||
} else {
|
||||
output += "__dxrt__std__dxrt__"
|
||||
}
|
||||
|
||||
output += self.level.into();
|
||||
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
mod conversion;
|
||||
Reference in New Issue
Block a user