@@ -254,7 +254,7 @@ impl LobbyCommand {
|
|||||||
None => {
|
None => {
|
||||||
interaction
|
interaction
|
||||||
.edit_original_interaction_response(ctx, |response| {
|
.edit_original_interaction_response(ctx, |response| {
|
||||||
response.content(format!("Failed to get players"))
|
response.content("Failed to get players")
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -263,12 +263,12 @@ impl LobbyCommand {
|
|||||||
|
|
||||||
let players = players
|
let players = players
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| Player::new(p))
|
.map(Player::new)
|
||||||
.collect::<Vec<Player>>();
|
.collect::<Vec<Player>>();
|
||||||
let slots = vec![
|
let slots = vec![
|
||||||
Role::Tank,
|
Role::Tank,
|
||||||
Role::DPS,
|
Role::Dps,
|
||||||
Role::DPS,
|
Role::Dps,
|
||||||
Role::Support,
|
Role::Support,
|
||||||
Role::Support,
|
Role::Support,
|
||||||
];
|
];
|
||||||
@@ -307,7 +307,7 @@ impl LobbyCommand {
|
|||||||
.iter()
|
.iter()
|
||||||
.sorted_by(|((a, _), _), ((b, _), _)| i32::from(*a).cmp(&i32::from(*b)))
|
.sorted_by(|((a, _), _), ((b, _), _)| i32::from(*a).cmp(&i32::from(*b)))
|
||||||
.map(|(_, i)| async {
|
.map(|(_, i)| async {
|
||||||
if let Some(user) = players[i.unwrap()].discord_id.to_user(ctx).await.ok() {
|
if let Ok(user) = players[i.unwrap()].discord_id.to_user(ctx).await {
|
||||||
user.name
|
user.name
|
||||||
} else {
|
} else {
|
||||||
players[i.unwrap()]
|
players[i.unwrap()]
|
||||||
@@ -322,7 +322,7 @@ impl LobbyCommand {
|
|||||||
.iter()
|
.iter()
|
||||||
.sorted_by(|((a, _), _), ((b, _), _)| i32::from(*a).cmp(&i32::from(*b)))
|
.sorted_by(|((a, _), _), ((b, _), _)| i32::from(*a).cmp(&i32::from(*b)))
|
||||||
.map(|(_, i)| async {
|
.map(|(_, i)| async {
|
||||||
if let Some(user) = players[i.unwrap()].discord_id.to_user(ctx).await.ok() {
|
if let Ok(user) = players[i.unwrap()].discord_id.to_user(ctx).await {
|
||||||
user.name
|
user.name
|
||||||
} else {
|
} else {
|
||||||
players[i.unwrap()]
|
players[i.unwrap()]
|
||||||
@@ -348,9 +348,10 @@ impl LobbyCommand {
|
|||||||
let team1_rank = team1.average_rating(&players);
|
let team1_rank = team1.average_rating(&players);
|
||||||
let team2_rank = team2.average_rating(&players);
|
let team2_rank = team2.average_rating(&players);
|
||||||
|
|
||||||
image_gen.draw_teams_to_png(
|
image_gen.draw_teams_to_vec(
|
||||||
player_names,
|
player_names,
|
||||||
[team1_rank.value as i32, team2_rank.value as i32],
|
[team1_rank.value as i32, team2_rank.value as i32],
|
||||||
|
image::ImageOutputFormat::Png
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -607,25 +608,13 @@ impl LobbyCommand {
|
|||||||
.players
|
.players
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|((role, _), player)| {
|
.filter_map(|((role, _), player)| player.map(|id| (role, id)))
|
||||||
if player.is_some() {
|
|
||||||
Some((role, player.unwrap()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let team2 = team2
|
let team2 = team2
|
||||||
.players
|
.players
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|((role, _), player)| {
|
.filter_map(|((role, _), player)| player.map(|id| (role, id)))
|
||||||
if player.is_some() {
|
|
||||||
Some((role, player.unwrap()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ impl MixerCommand for PreferenceCommand {
|
|||||||
response
|
response
|
||||||
.kind(InteractionResponseType::ChannelMessageWithSource)
|
.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||||
.interaction_response_data(|message| {
|
.interaction_response_data(|message| {
|
||||||
message.content(format!("User not found")).ephemeral(true)
|
message.content("User not found").ephemeral(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ impl MixerCommand for RatingCommand {
|
|||||||
response
|
response
|
||||||
.kind(InteractionResponseType::ChannelMessageWithSource)
|
.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||||
.interaction_response_data(|message| {
|
.interaction_response_data(|message| {
|
||||||
message.content(format!("User not found")).ephemeral(true)
|
message.content("User not found").ephemeral(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
@@ -126,14 +126,14 @@ impl MixerCommand for RatingCommand {
|
|||||||
.as_u64()
|
.as_u64()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if rating < 1 || rating > 5000 {
|
if !(1..=5000).contains(&rating) {
|
||||||
interaction
|
interaction
|
||||||
.create_interaction_response(ctx, |response| {
|
.create_interaction_response(ctx, |response| {
|
||||||
response
|
response
|
||||||
.kind(InteractionResponseType::ChannelMessageWithSource)
|
.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||||
.interaction_response_data(|message| {
|
.interaction_response_data(|message| {
|
||||||
message
|
message
|
||||||
.content(format!("Rank must be between 1 and 5000"))
|
.content("Rank must be between 1 and 5000")
|
||||||
.ephemeral(true)
|
.ephemeral(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ impl SettingsCommand {
|
|||||||
let roles: HashMap<_, _, RandomState> = HashMap::from_iter(
|
let roles: HashMap<_, _, RandomState> = HashMap::from_iter(
|
||||||
[
|
[
|
||||||
("support", Role::Support),
|
("support", Role::Support),
|
||||||
("damage", Role::DPS),
|
("damage", Role::Dps),
|
||||||
("dps", Role::DPS),
|
("dps", Role::Dps),
|
||||||
("tank", Role::Tank),
|
("tank", Role::Tank),
|
||||||
]
|
]
|
||||||
.into_iter(),
|
.into_iter(),
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ impl MixerCommandHandler {
|
|||||||
interaction.user.id,
|
interaction.user.id,
|
||||||
command.name()
|
command.name()
|
||||||
);
|
);
|
||||||
return command.execute(&ctx, interaction).await;
|
return command.execute(ctx, interaction).await;
|
||||||
} else {
|
} else {
|
||||||
info!(
|
info!(
|
||||||
"User {} ({}) executed unknown command \"{}\"",
|
"User {} ({}) executed unknown command \"{}\"",
|
||||||
|
|||||||
@@ -64,9 +64,7 @@ impl EventHandler for MixerBot {
|
|||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
let db = data.get::<DatabaseContainer>().unwrap().read().await;
|
let db = data.get::<DatabaseContainer>().unwrap().read().await;
|
||||||
|
|
||||||
if let Some(_) =
|
if LobbyQuery::lobby_by_channel_id(db.connection(), guild_id, channel_id).await.is_some() {
|
||||||
LobbyQuery::lobby_by_channel_id(db.connection(), guild_id, channel_id).await
|
|
||||||
{
|
|
||||||
if let Some(member) = new.member {
|
if let Some(member) = new.member {
|
||||||
if member.user.bot {
|
if member.user.bot {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ pub enum Role {
|
|||||||
#[sea_orm(string_value = "tank")]
|
#[sea_orm(string_value = "tank")]
|
||||||
Tank,
|
Tank,
|
||||||
#[sea_orm(string_value = "dps")]
|
#[sea_orm(string_value = "dps")]
|
||||||
DPS,
|
Dps,
|
||||||
#[sea_orm(string_value = "support")]
|
#[sea_orm(string_value = "support")]
|
||||||
Support,
|
Support,
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ impl From<Role> for String {
|
|||||||
fn from(role: Role) -> Self {
|
fn from(role: Role) -> Self {
|
||||||
match role {
|
match role {
|
||||||
Role::Tank => "tank".to_string(),
|
Role::Tank => "tank".to_string(),
|
||||||
Role::DPS => "dps".to_string(),
|
Role::Dps => "dps".to_string(),
|
||||||
Role::Support => "support".to_string(),
|
Role::Support => "support".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ impl TryFrom<&str> for Role {
|
|||||||
fn try_from(role: &str) -> Result<Self, Self::Error> {
|
fn try_from(role: &str) -> Result<Self, Self::Error> {
|
||||||
match role {
|
match role {
|
||||||
"tank" => Ok(Role::Tank),
|
"tank" => Ok(Role::Tank),
|
||||||
"dps" => Ok(Role::DPS),
|
"dps" => Ok(Role::Dps),
|
||||||
"support" => Ok(Role::Support),
|
"support" => Ok(Role::Support),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ impl From<Role> for i32 {
|
|||||||
fn from(role: Role) -> Self {
|
fn from(role: Role) -> Self {
|
||||||
match role {
|
match role {
|
||||||
Role::Tank => 0,
|
Role::Tank => 0,
|
||||||
Role::DPS => 1,
|
Role::Dps => 1,
|
||||||
Role::Support => 2,
|
Role::Support => 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl Query {
|
|||||||
player.tank_rd = Set(rating.rd);
|
player.tank_rd = Set(rating.rd);
|
||||||
player.tank_volatility = Set(rating.volatility);
|
player.tank_volatility = Set(rating.volatility);
|
||||||
}
|
}
|
||||||
Role::DPS => {
|
Role::Dps => {
|
||||||
player.dps_rating = Set(rating.value);
|
player.dps_rating = Set(rating.value);
|
||||||
player.dps_rd = Set(rating.rd);
|
player.dps_rd = Set(rating.rd);
|
||||||
player.dps_volatility = Set(rating.volatility);
|
player.dps_volatility = Set(rating.volatility);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use image::{codecs::png, ImageEncoder};
|
use image::ImageOutputFormat;
|
||||||
use imageproc::drawing::text_size;
|
use imageproc::drawing::text_size;
|
||||||
use rusttype::{Font, Scale};
|
use rusttype::{Font, Scale};
|
||||||
use serenity::prelude::TypeMapKey;
|
use serenity::prelude::TypeMapKey;
|
||||||
use std::{io::BufWriter, sync::Arc};
|
use std::{io::Cursor, sync::Arc};
|
||||||
|
|
||||||
pub struct ImageGenerator<'a> {
|
pub struct ImageGenerator<'a> {
|
||||||
pub player_font: Font<'a>,
|
pub player_font: Font<'a>,
|
||||||
@@ -11,7 +11,7 @@ pub struct ImageGenerator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ImageGenerator<'a> {
|
impl<'a> ImageGenerator<'a> {
|
||||||
pub fn draw_teams_to_png(&self, player_names: Vec<String>, teams_rating: [i32; 2]) -> Vec<u8> {
|
pub fn draw_teams_to_vec(&self, player_names: Vec<String>, teams_rating: [i32; 2], format: ImageOutputFormat) -> Vec<u8> {
|
||||||
let mut image: image::ImageBuffer<image::Rgb<u8>, Vec<u8>> = self.teams_image.clone();
|
let mut image: image::ImageBuffer<image::Rgb<u8>, Vec<u8>> = self.teams_image.clone();
|
||||||
|
|
||||||
let player_text_scale = Scale::uniform(60.0);
|
let player_text_scale = Scale::uniform(60.0);
|
||||||
@@ -47,8 +47,8 @@ impl<'a> ImageGenerator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let rating_text_scale = Scale::uniform(86.5);
|
let rating_text_scale = Scale::uniform(86.5);
|
||||||
for i in 0..2 {
|
for (i, rating) in teams_rating.iter().enumerate() {
|
||||||
let rating = teams_rating[i].to_string();
|
let rating = rating.to_string();
|
||||||
|
|
||||||
let size = text_size(rating_text_scale, &self.player_font, &rating);
|
let size = text_size(rating_text_scale, &self.player_font, &rating);
|
||||||
imageproc::drawing::draw_text_mut(
|
imageproc::drawing::draw_text_mut(
|
||||||
@@ -62,16 +62,11 @@ impl<'a> ImageGenerator<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut buf = BufWriter::new(Vec::new());
|
|
||||||
png::PngEncoder::new(&mut buf)
|
let mut buf = Cursor::new(Vec::new());
|
||||||
.write_image(
|
image.write_to(&mut buf, format).unwrap();
|
||||||
image.as_raw(),
|
|
||||||
image.width(),
|
buf.into_inner()
|
||||||
image.height(),
|
|
||||||
image::ColorType::Rgb8,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
buf.into_inner().unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ fn get_role_entries(
|
|||||||
let (tanks, rest) = entries
|
let (tanks, rest) = entries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.partition::<Vec<_>, _>(|e| e.role == Role::Tank);
|
.partition::<Vec<_>, _>(|e| e.role == Role::Tank);
|
||||||
let (dps, supports) = rest.into_iter().partition(|e| e.role == Role::DPS);
|
let (dps, supports) = rest.into_iter().partition(|e| e.role == Role::Dps);
|
||||||
|
|
||||||
(tanks, dps, supports)
|
(tanks, dps, supports)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_combinations(entries: &[PlayerRoleEntry], count: usize) -> Vec<Vec<&PlayerRoleEntry>> {
|
fn get_combinations(entries: &[PlayerRoleEntry], count: usize) -> Vec<Vec<&PlayerRoleEntry>> {
|
||||||
entries
|
entries
|
||||||
.into_iter()
|
.iter()
|
||||||
.combinations(count)
|
.combinations(count)
|
||||||
.sorted_by(|a, b| {
|
.sorted_by(|a, b| {
|
||||||
let a = a.iter().map(|e| e.priority).sum::<f32>();
|
let a = a.iter().map(|e| e.priority).sum::<f32>();
|
||||||
@@ -55,7 +55,7 @@ pub fn mix_players(players: &[Player], slots: Vec<Role>) -> Option<(Team, Team)>
|
|||||||
|
|
||||||
let tank_count = slots.iter().filter(|r| **r == Role::Tank).count();
|
let tank_count = slots.iter().filter(|r| **r == Role::Tank).count();
|
||||||
let support_count = slots.iter().filter(|r| **r == Role::Support).count();
|
let support_count = slots.iter().filter(|r| **r == Role::Support).count();
|
||||||
let dps_count = slots.iter().filter(|r| **r == Role::DPS).count();
|
let dps_count = slots.iter().filter(|r| **r == Role::Dps).count();
|
||||||
|
|
||||||
let tank_combos = get_combinations(&tanks, tank_count);
|
let tank_combos = get_combinations(&tanks, tank_count);
|
||||||
let dps_combos = get_combinations(&dps, dps_count);
|
let dps_combos = get_combinations(&dps, dps_count);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ impl Player {
|
|||||||
Rating::new(model.tank_rating, model.tank_rd, model.tank_volatility),
|
Rating::new(model.tank_rating, model.tank_rd, model.tank_volatility),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Role::DPS,
|
Role::Dps,
|
||||||
Rating::new(model.dps_rating, model.dps_rd, model.dps_volatility),
|
Rating::new(model.dps_rating, model.dps_rd, model.dps_volatility),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@@ -77,7 +77,7 @@ impl Player {
|
|||||||
|
|
||||||
for (i, role) in self.priority_roles.iter().enumerate() {
|
for (i, role) in self.priority_roles.iter().enumerate() {
|
||||||
if let Some(role) = role {
|
if let Some(role) = role {
|
||||||
priorities.insert(role.clone(), priority_points / (i + 1) as f32);
|
priorities.insert(*role, priority_points / (i + 1) as f32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ impl Team {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn count_role(&self, role: &Role) -> usize {
|
pub fn count_role(&self, role: &Role) -> usize {
|
||||||
self.count_role.get(role).unwrap().clone()
|
*self.count_role.get(role).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_rating(&self, players: &[Player]) -> Rating {
|
pub fn full_rating(&self, players: &[Player]) -> Rating {
|
||||||
@@ -55,7 +55,7 @@ impl Team {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|((role, _), index)| {
|
.map(|((role, _), index)| {
|
||||||
if let Some(index) = index {
|
if let Some(index) = index {
|
||||||
players[*index].ranks.get(role).unwrap().clone()
|
*players[*index].ranks.get(role).unwrap()
|
||||||
} else {
|
} else {
|
||||||
Rating::zero()
|
Rating::zero()
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ impl Team {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn average_rating(&self, players: &[Player]) -> Rating {
|
pub fn average_rating(&self, players: &[Player]) -> Rating {
|
||||||
if self.players.len() == 0 {
|
if self.players.is_empty() {
|
||||||
return Rating::zero();
|
return Rating::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ impl Team {
|
|||||||
.filter(|((r, _), _)| r == role)
|
.filter(|((r, _), _)| r == role)
|
||||||
.map(|((_, _), index)| {
|
.map(|((_, _), index)| {
|
||||||
if let Some(index) = index {
|
if let Some(index) = index {
|
||||||
players[*index].ranks.get(&role).unwrap().clone()
|
*players[*index].ranks.get(role).unwrap()
|
||||||
} else {
|
} else {
|
||||||
Rating::zero()
|
Rating::zero()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user