use super::parse::{parse_beatmap_to_song, parse_beatmap_to_song_with_mapper};
use osynic_osudb::entity::osu::osudb::OsuDB;
use super::storage::marked_save_to;
use super::walker::{walk_file_name_with_extension_first, walk_folder_name};
use crate::error::Result;
use crate::types::{Song, SongWithMapper};
pub fn serialize_song_folder_raw(folder_name: &str) -> Result<(u32, String, String, bool)> {
let parts: Vec<&str> = folder_name.splitn(2, ' ').collect();
let song_id_str = parts[0];
if !song_id_str.chars().all(|c| c.is_digit(10)) {
return Err("Invalid song_id".into());
}
if parts.len() < 2 {
return Err("Invalid folder name format".into());
}
let song_id: u32 = song_id_str.parse()?;
let rest = parts[1];
let parts: Vec<&str> = rest.rsplitn(2, " - ").collect();
if parts.len() < 2 {
return Ok((song_id, "manbo".to_string(), "manbo".to_string(), false));
}
let artist_name = parts[1].to_string();
let song_parts: Vec<&str> = parts[0].rsplitn(2, " [no video]").collect();
let song_name = song_parts[song_parts.len() - 1].to_string();
let no_video = song_parts.len() == 2;
Ok((song_id, artist_name, song_name, no_video))
}
pub fn serialize_song_folder(folder_name: &str) -> Result<Song> {
let (song_id, artist_name, song_name, no_video) = serialize_song_folder_raw(folder_name)?;
Ok(Song {
song_id,
artist_name,
song_name,
no_video,
})
}
pub fn serialize_mapper_raw(folder_name: &str) -> Result<String> {
let parts: Vec<&str> = folder_name.rsplitn(2, '(').collect();
let rest = parts[0];
let rparts: Vec<&str> = rest.split(')').collect();
let mapper_name = rparts[0].to_string();
Ok(mapper_name)
}
pub fn serialize_osu_db(osu_db: &mut OsuDB) -> Result<Vec<Song>> {
let mut songs = Vec::new();
let mut beatmapset_id_set = std::collections::HashSet::new();
for beatmap in osu_db.beatmaps.iter_mut() {
if beatmapset_id_set.contains(&beatmap.beatmapset_id) {
continue;
}
beatmapset_id_set.insert(beatmap.beatmapset_id);
let song = parse_beatmap_to_song(beatmap);
songs.push(song);
}
Ok(songs)
}
pub fn serialize_osu_db_with_mapper(osu_db: &mut OsuDB) -> Result<Vec<SongWithMapper>> {
let mut songs = Vec::new();
let mut beatmapset_id_set = std::collections::HashSet::new();
for beatmap in osu_db.beatmaps.iter_mut() {
if beatmapset_id_set.contains(&beatmap.beatmapset_id) {
continue;
}
beatmapset_id_set.insert(beatmap.beatmapset_id);
let song = parse_beatmap_to_song_with_mapper(beatmap);
songs.push(song);
}
Ok(songs)
}
pub fn serialize_song_folder_with_mapper(songs_dir: &str) -> Result<Vec<SongWithMapper>> {
let mut songs = Vec::new();
for folder_name in walk_folder_name(songs_dir)? {
if let Ok((song_id, artist_name, song_name, no_video)) =
serialize_song_folder_raw(&folder_name)
{
let sub_name = format!("{}/{}", songs_dir, folder_name);
let inner_name = walk_file_name_with_extension_first(&sub_name, ".osu")?;
let mapper_name = serialize_mapper_raw(&inner_name)?;
songs.push(SongWithMapper {
song_id,
artist_name,
song_name,
no_video,
mapper_name,
});
}
}
Ok(songs)
}
pub fn serialize_by_folder_name(songs_dir: &str) -> Result<()> {
let mut songs = Vec::new();
for folder_name in walk_folder_name(songs_dir)? {
if let Ok((song_id, artist_name, song_name, no_video)) =
serialize_song_folder_raw(&folder_name)
{
songs.push(Song {
song_id,
artist_name,
song_name,
no_video,
});
}
}
let json = serde_json::to_string_pretty(&songs)?;
marked_save_to("songs", "songs.json", &json)?;
Ok(())
}
pub fn serialize_by_folder_name_with_mapper(songs_dir: &str, save_path: &str) -> Result<()> {
let mut songs = Vec::new();
for folder_name in walk_folder_name(songs_dir)? {
if let Ok((song_id, artist_name, song_name, no_video)) =
serialize_song_folder_raw(&folder_name)
{
let sub_name = format!("{}/{}", songs_dir, folder_name);
let inner_name = walk_file_name_with_extension_first(&sub_name, ".osu")?;
let mapper_name = serialize_mapper_raw(&inner_name)?;
songs.push(SongWithMapper {
song_id,
artist_name,
song_name,
no_video,
mapper_name,
});
}
}
let json = serde_json::to_string_pretty(&songs)?;
marked_save_to(save_path, "songs_m.json", &json)?;
Ok(())
}
pub fn serialize_by_osu_db(osu_db: &mut OsuDB) -> Result<()> {
let songs = serialize_osu_db(osu_db)?;
let json = serde_json::to_string_pretty(&songs)?;
marked_save_to("songs", "songs_d.json", &json)?;
Ok(())
}
pub fn serialize_by_osu_db_with_mapper(osu_db: &mut OsuDB, save_path: &str) -> Result<()> {
let songs = serialize_osu_db_with_mapper(osu_db)?;
let json = serde_json::to_string_pretty(&songs)?;
marked_save_to(save_path, "songs_dm.json", &json)?;
Ok(())
}
pub fn open_osu_db(osu_db: &str) -> Result<OsuDB> {
Ok(OsuDB::from_file(osu_db)?)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialize_song_folder_raw() {
let folder_name =
"1985060 hitorie - Nichijou to Chikyuu no Gakubuchi (wowaka x Hatsune Miku Edit)";
let result = serialize_song_folder_raw(folder_name).unwrap();
println!("{:?}", result);
}
#[test]
fn test_serialize_song_folder() {
let folder_name =
"1985060 hitorie - Nichijou to Chikyuu no Gakubuchi (wowaka x Hatsune Miku Edit)";
let result = serialize_song_folder(folder_name).unwrap();
println!("{:?}", result);
}
#[test]
fn test_serialize_mapper_raw() {
let folder_name = "hitorie - Nichijou to Chikyuu no Gakubuchi (wowaka x Hatsune Miku Edit) (flake) [take care.].osu";
let result = serialize_mapper_raw(folder_name).unwrap();
println!("{:?}", result);
}
#[test]
fn test_serialize_osu_db() {
let mut osu_db = OsuDB::from_file("osu!.db").unwrap();
let songs = serialize_osu_db(&mut osu_db).unwrap();
println!("{:?}", songs);
}
#[test]
fn test_serialize_osu_db_with_mapper() {
let mut osu_db = OsuDB::from_file("osu!.db").unwrap();
let songs = serialize_osu_db_with_mapper(&mut osu_db).unwrap();
println!("{:?}", songs);
}
}