use chrono::{TimeZone, Utc};
use uuid::uuid;
use crate::{
game::{
AdvancedMatchInfo, BastionType, MatchCategory, MatchCompletion, MatchEloUpdate,
MatchOutcome, MatchRank, MatchSeedInfo, MatchTimelineEvent, MatchType, OverworldType,
},
types::Time,
user::{SupporterTier, UserProfile},
};
#[test]
fn match_info() {
const JSON: &str = r#"{"id":1524115,"type":2,"seed":{"id":null,"overworld":"VILLAGE","nether":"HOUSING","variations":[]},"category":"ANY","gameMode":"default","players":[{"uuid":"79635c3dbf634a228bf44544cc7c0d27","nickname":"LaysarOwO","roleType":0,"eloRate":1146,"eloRank":1048,"country":null},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","nickname":"Frigbob","roleType":0,"eloRate":1470,"eloRank":211,"country":null}],"spectators":[],"result":{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":620128},"forfeited":false,"decayed":false,"rank":{"season":1000,"allTime":null},"changes":[{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","change":19,"eloRate":1282},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","change":-19,"eloRate":1245}],"completions":[{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":620128}],"timelines":[{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":610048,"type":"projectelo.timeline.dragon_death"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":535511,"type":"end.root"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":535393,"type":"story.enter_the_end"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":494792,"type":"story.follow_ender_eye"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":454844,"type":"story.follow_ender_eye"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":419050,"type":"projectelo.timeline.blind_travel"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":358761,"type":"projectelo.timeline.blind_travel"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":354196,"type":"nether.obtain_blaze_rod"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":331692,"type":"nether.obtain_blaze_rod"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":320335,"type":"nether.find_fortress"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":311082,"type":"adventure.root"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":310966,"type":"adventure.kill_a_mob"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":310597,"type":"nether.find_fortress"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":290740,"type":"husbandry.root"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":282496,"type":"adventure.kill_a_mob"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":282404,"type":"adventure.root"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":266018,"type":"nether.loot_bastion"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":255043,"type":"story.form_obsidian"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":235241,"type":"nether.obtain_crying_obsidian"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":230341,"type":"nether.obtain_crying_obsidian"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":223692,"type":"story.form_obsidian"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":170186,"type":"nether.distract_piglin"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":162694,"type":"nether.loot_bastion"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":161055,"type":"nether.find_bastion"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":157338,"type":"nether.find_bastion"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":153691,"type":"husbandry.root"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":132943,"type":"story.enter_the_nether"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":132837,"type":"nether.root"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":120786,"type":"story.lava_bucket"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":118642,"type":"nether.root"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":118522,"type":"story.enter_the_nether"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":106937,"type":"story.lava_bucket"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":37230,"type":"story.root"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":33038,"type":"story.mine_stone"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":31439,"type":"story.root"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":29794,"type":"story.obtain_armor"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":29794,"type":"story.iron_tools"},{"uuid":"79635c3dbf634a228bf44544cc7c0d27","time":29684,"type":"story.smelt_iron"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":24938,"type":"story.mine_stone"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":23237,"type":"story.iron_tools"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":22337,"type":"story.obtain_armor"},{"uuid":"7d3a6bb9f62645ae80cf40840ca84c50","time":21037,"type":"story.smelt_iron"}],"season":7,"date":1735326765,"seedType":"VILLAGE","bastionType":"HOUSING","tag":null,"replayExist":false}"#;
let full_info: AdvancedMatchInfo = serde_json::from_str(JSON).unwrap();
let info = &full_info.info;
assert_eq!(info.id, 1524115);
assert_eq!(info.kind, MatchType::Ranked);
assert_eq!(info.season, 7);
assert_eq!(info.category, Some(MatchCategory::Any));
assert_eq!(info.date, Utc.timestamp_opt(1735326765, 0).unwrap());
let mut players = info.players().to_vec();
players.sort_by_key(|l| l.uuid);
assert_eq!(
players,
[
UserProfile::new(
"79635c3dbf634a228bf44544cc7c0d27",
"LaysarOwO",
SupporterTier::None,
Some(1146),
Some(1048),
None,
),
UserProfile::new(
"7d3a6bb9f62645ae80cf40840ca84c50",
"Frigbob",
SupporterTier::None,
Some(1470),
Some(211),
None,
),
]
);
let frigidbob = uuid!("7d3a6bb9f62645ae80cf40840ca84c50");
let laysar = uuid!("79635c3dbf634a228bf44544cc7c0d27");
assert_eq!(info.spectators(), []);
assert_eq!(
info.seed,
Some(MatchSeedInfo {
id: None,
overworld: Some(OverworldType::Village),
bastion: Some(BastionType::Housing),
variations: [].into(),
end_towers: None,
})
);
assert_eq!(info.overworld_type(), Some(OverworldType::Village));
assert_eq!(info.bastion_type(), Some(BastionType::Housing));
assert_eq!(
info.result,
MatchOutcome {
winner_uuid: Some(frigidbob),
time: Time(620128),
}
);
assert!(!info.forfeited);
assert!(!info.decayed);
assert_eq!(
info.rank,
MatchRank {
season: Some(1000),
all_time: None,
}
);
assert_eq!(
info.elo_updates(),
[
MatchEloUpdate {
player_uuid: frigidbob,
change: Some(19),
elo: Some(1282),
},
MatchEloUpdate {
player_uuid: laysar,
change: Some(-19),
elo: Some(1245),
}
],
);
assert_eq!(
full_info.completions(),
[MatchCompletion {
player_uuid: frigidbob,
time: Time(620128),
}]
);
assert_eq!(
full_info.timeline_events(),
[
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(610048),
id: "projectelo.timeline.dragon_death".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(535511),
id: "end.root".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(535393),
id: "story.enter_the_end".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(494792),
id: "story.follow_ender_eye".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(454844),
id: "story.follow_ender_eye".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(419050),
id: "projectelo.timeline.blind_travel".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(358761),
id: "projectelo.timeline.blind_travel".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(354196),
id: "nether.obtain_blaze_rod".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(331692),
id: "nether.obtain_blaze_rod".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(320335),
id: "nether.find_fortress".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(311082),
id: "adventure.root".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(310966),
id: "adventure.kill_a_mob".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(310597),
id: "nether.find_fortress".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(290740),
id: "husbandry.root".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(282496),
id: "adventure.kill_a_mob".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(282404),
id: "adventure.root".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(266018),
id: "nether.loot_bastion".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(255043),
id: "story.form_obsidian".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(235241),
id: "nether.obtain_crying_obsidian".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(230341),
id: "nether.obtain_crying_obsidian".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(223692),
id: "story.form_obsidian".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(170186),
id: "nether.distract_piglin".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(162694),
id: "nether.loot_bastion".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(161055),
id: "nether.find_bastion".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(157338),
id: "nether.find_bastion".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(153691),
id: "husbandry.root".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(132943),
id: "story.enter_the_nether".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(132837),
id: "nether.root".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(120786),
id: "story.lava_bucket".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(118642),
id: "nether.root".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(118522),
id: "story.enter_the_nether".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(106937),
id: "story.lava_bucket".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(37230),
id: "story.root".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(33038),
id: "story.mine_stone".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(31439),
id: "story.root".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(29794),
id: "story.obtain_armor".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(29794),
id: "story.iron_tools".into(),
},
MatchTimelineEvent {
player_uuid: laysar,
time: Time(29684),
id: "story.smelt_iron".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(24938),
id: "story.mine_stone".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(23237),
id: "story.iron_tools".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(22337),
id: "story.obtain_armor".into(),
},
MatchTimelineEvent {
player_uuid: frigidbob,
time: Time(21037),
id: "story.smelt_iron".into(),
}
]
);
assert!(!full_info.replay_exists);
#[cfg(feature = "serialize")]
{
let re_deserialized: AdvancedMatchInfo =
serde_json::from_str(&serde_json::to_string(&full_info).unwrap()).unwrap();
assert_eq!(full_info, re_deserialized)
}
}
#[test]
fn match_category() {
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ANY""#).unwrap(),
MatchCategory::Any
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""CUSTOM""#).unwrap(),
MatchCategory::Custom
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""HIGH""#).unwrap(),
MatchCategory::High
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""KILL_ALL_BOSSES""#).unwrap(),
MatchCategory::KillAllBosses
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""KILL_WITHER""#).unwrap(),
MatchCategory::KillWither
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""KILL_ELDER_GUARDIAN""#).unwrap(),
MatchCategory::KillElderGuardian
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ALL_ADVANCEMENTS""#).unwrap(),
MatchCategory::AllAdvancements
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""HALF""#).unwrap(),
MatchCategory::Half
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""POGLOOT_QUATER""#).unwrap(),
MatchCategory::PoglootQuater
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""HOW_DID_WE_GET_HERE""#).unwrap(),
MatchCategory::HowDidWeGetHere
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""HERO_OF_VILLAGE""#).unwrap(),
MatchCategory::HeroOfVillage
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ARBALISTIC""#).unwrap(),
MatchCategory::Arbalistic
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""COVER_ME_IN_DEBRIS""#).unwrap(),
MatchCategory::CoverMeInDebris
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ENTER_NETHER""#).unwrap(),
MatchCategory::EnterNether
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ENTER_END""#).unwrap(),
MatchCategory::EnterEnd
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ALL_SWORDS""#).unwrap(),
MatchCategory::AllSwords
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ALL_MINERALS""#).unwrap(),
MatchCategory::AllMinerals
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""FULL_IA_15_LVL""#).unwrap(),
MatchCategory::FullIa15Lvl
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ALL_WORKSTATIONS""#).unwrap(),
MatchCategory::AllWorkstations
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""FULL_INV""#).unwrap(),
MatchCategory::FullInv
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""STACK_OF_LIME_WOOL""#).unwrap(),
MatchCategory::StackOfLimeWool
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ALL_PORTALS""#).unwrap(),
MatchCategory::AllPortals
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""ALL_BLOCKS""#).unwrap(),
MatchCategory::AllBlocks
);
assert_eq!(
serde_json::from_str::<MatchCategory>(r#""MINE_A_CHUNK""#).unwrap(),
MatchCategory::MineAChunk
);
}
#[test]
fn match_type() {
assert_eq!(
serde_json::from_str::<MatchType>("1").unwrap(),
MatchType::Causal
);
assert_eq!(
serde_json::from_str::<MatchType>("2").unwrap(),
MatchType::Ranked
);
assert_eq!(
serde_json::from_str::<MatchType>("3").unwrap(),
MatchType::Private
);
assert_eq!(
serde_json::from_str::<MatchType>("4").unwrap(),
MatchType::Event
);
assert!(serde_json::from_str::<MatchType>("0").is_err());
assert!(serde_json::from_str::<MatchType>("99").is_err());
}
#[test]
fn overworld_type() {
assert_eq!(
serde_json::from_str::<OverworldType>(r#""VILLAGE""#).unwrap(),
OverworldType::Village
);
assert_eq!(
serde_json::from_str::<OverworldType>(r#""BURIED_TREASURE""#).unwrap(),
OverworldType::BuriedTreasure
);
assert_eq!(
serde_json::from_str::<OverworldType>(r#""SHIPWRECK""#).unwrap(),
OverworldType::Shipwreck
);
assert_eq!(
serde_json::from_str::<OverworldType>(r#""DESERT_TEMPLE""#).unwrap(),
OverworldType::DesertTemple
);
assert_eq!(
serde_json::from_str::<OverworldType>(r#""RUINED_PORTAL""#).unwrap(),
OverworldType::RuinedPortal
);
assert!(serde_json::from_str::<OverworldType>(r#""DOESN'T EXIST""#).is_err());
}
#[test]
fn bastion_type() {
assert_eq!(
serde_json::from_str::<BastionType>(r#""HOUSING""#).unwrap(),
BastionType::Housing
);
assert_eq!(
serde_json::from_str::<BastionType>(r#""TREASURE""#).unwrap(),
BastionType::Treasure
);
assert_eq!(
serde_json::from_str::<BastionType>(r#""BRIDGE""#).unwrap(),
BastionType::Bridge
);
assert_eq!(
serde_json::from_str::<BastionType>(r#""STABLES""#).unwrap(),
BastionType::Stables
);
assert!(serde_json::from_str::<BastionType>(r#""DOESN'T EXIST""#).is_err());
#[cfg(feature = "serialize")]
{
assert_eq!(
serde_json::to_string(&BastionType::Housing).unwrap(),
r#""HOUSING""#
);
assert_eq!(
serde_json::to_string(&BastionType::Treasure).unwrap(),
r#""TREASURE""#
);
assert_eq!(
serde_json::to_string(&BastionType::Bridge).unwrap(),
r#""BRIDGE""#
);
assert_eq!(
serde_json::to_string(&BastionType::Stables).unwrap(),
r#""STABLES""#
);
}
}