i question my life decisions
This commit is contained in:
@@ -12,6 +12,7 @@ use serenity::model::id::{ChannelId, RoleId, UserId};
|
|||||||
use serenity::model::Permissions;
|
use serenity::model::Permissions;
|
||||||
use crate::bot::commands::MixerCommand;
|
use crate::bot::commands::MixerCommand;
|
||||||
use crate::database::DatabaseContainer;
|
use crate::database::DatabaseContainer;
|
||||||
|
use crate::mixer::mixer::Mixer;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LobbyCommand;
|
pub struct LobbyCommand;
|
||||||
@@ -149,9 +150,19 @@ impl LobbyCommand {
|
|||||||
let members = main_channel.members(ctx.cache().unwrap()).await?;
|
let members = main_channel.members(ctx.cache().unwrap()).await?;
|
||||||
let users = members.iter().map(|m| m.user.id).collect::<Vec<UserId>>();
|
let users = members.iter().map(|m| m.user.id).collect::<Vec<UserId>>();
|
||||||
let players = db.get_players(users).await;
|
let players = db.get_players(users).await;
|
||||||
|
let players = db.get_players((0..10).map(|id| UserId(id)).collect()).await;
|
||||||
|
|
||||||
println!("{:?}", players);
|
println!("{:?}", players);
|
||||||
|
|
||||||
|
let mixer = Mixer::new(players);
|
||||||
|
if let Some((mut team1, mut team2)) = mixer.select_teams() {
|
||||||
|
team1.sort_by(|a, b| a.role.cmp(&b.role));
|
||||||
|
team2.sort_by(|a, b| a.role.cmp(&b.role));
|
||||||
|
let team1: Vec<_> = team1.iter().map(|p| p.player.bn_name.clone()).collect();
|
||||||
|
let team2: Vec<_> = team2.iter().map(|p| p.player.bn_name.clone()).collect();
|
||||||
|
println!("{:?}\n{:?}", team1, team2);
|
||||||
|
}
|
||||||
|
|
||||||
interaction.create_interaction_response(ctx.http(), |response| {
|
interaction.create_interaction_response(ctx.http(), |response| {
|
||||||
response.kind(InteractionResponseType::ChannelMessageWithSource)
|
response.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||||
.interaction_response_data(|message| {
|
.interaction_response_data(|message| {
|
||||||
|
|||||||
@@ -29,15 +29,32 @@ impl Mixer {
|
|||||||
let mut team1 = Vec::new();
|
let mut team1 = Vec::new();
|
||||||
let mut team2 = Vec::new();
|
let mut team2 = Vec::new();
|
||||||
|
|
||||||
for i in 0..10 {
|
'outer: for i in 0..10 {
|
||||||
let priorities = self.get_players_priority(&players, &team1, &team2);
|
let priorities = self.get_players_priority(&players, &team1, &team2);
|
||||||
|
// let priorities = Self::priorities_to_array(priorities, &players);
|
||||||
|
|
||||||
if let Some(player) = self.get_highest_priority_player(&players, &priorities) {
|
if let Some(player) = self.get_highest_priority_player(&players, &priorities) {
|
||||||
if i % 2 == 0 {
|
if Self::full_team_rank(&team1) > Self::full_team_rank(&team2) {
|
||||||
team1.push(player.clone());
|
if Self::has_slot_for(&team2, player.role) {
|
||||||
|
team2.push(player.clone());
|
||||||
|
}
|
||||||
|
else if Self::has_slot_for(&team1, player.role) {
|
||||||
|
team1.push(player.clone());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
team2.push(player.clone());
|
if Self::has_slot_for(&team1, player.role) {
|
||||||
|
team1.push(player.clone());
|
||||||
|
}
|
||||||
|
else if Self::has_slot_for(&team2, player.role) {
|
||||||
|
team2.push(player.clone());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
players.retain(|p| p.id != player.player.id);
|
players.retain(|p| p.id != player.player.id);
|
||||||
@@ -72,6 +89,10 @@ impl Mixer {
|
|||||||
let selected_players = team1.iter().filter(|player| player.role == role)
|
let selected_players = team1.iter().filter(|player| player.role == role)
|
||||||
.chain(team2.iter().filter(|player| player.role == role)).clone().collect::<Vec<&MixedPlayer>>();
|
.chain(team2.iter().filter(|player| player.role == role)).clone().collect::<Vec<&MixedPlayer>>();
|
||||||
|
|
||||||
|
if selected_players.len() <= 0 {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
selected_players.iter().map(|player| {
|
selected_players.iter().map(|player| {
|
||||||
match player.role {
|
match player.role {
|
||||||
Role::Tank => player.player.tank,
|
Role::Tank => player.player.tank,
|
||||||
@@ -82,15 +103,47 @@ impl Mixer {
|
|||||||
}).sum::<f32>() / selected_players.len() as f32
|
}).sum::<f32>() / selected_players.len() as f32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn full_team_rank(team: &Vec<MixedPlayer>) -> f32 {
|
||||||
|
if team.len() <= 0 {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
team.iter().map(|p| {
|
||||||
|
match p.role {
|
||||||
|
Role::Tank => p.player.tank,
|
||||||
|
Role::Dps => p.player.dps,
|
||||||
|
Role::Support => p.player.support,
|
||||||
|
_ => 0.0
|
||||||
|
}
|
||||||
|
}).sum::<f32>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_slot_for(team: &Vec<MixedPlayer>, role: Role) -> bool {
|
||||||
|
let team_role_count = team.iter().filter(|p| p.role == role).count();
|
||||||
|
|
||||||
|
match role {
|
||||||
|
Role::Tank => team_role_count < 1,
|
||||||
|
Role::Dps | Role::Support => team_role_count < 2,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn calculate_priorities(players: &Vec<Model>, team1: &Vec<MixedPlayer>, team2: &Vec<MixedPlayer>, expected: Role, priorities: &mut HashMap<(Role, i32), f32>) -> bool {
|
fn calculate_priorities(players: &Vec<Model>, team1: &Vec<MixedPlayer>, team2: &Vec<MixedPlayer>, expected: Role, priorities: &mut HashMap<(Role, i32), f32>) -> bool {
|
||||||
let group_coefficients = vec![10.0, 50.0, 100.0, 150.0, 125.0];
|
let group_coefficients = vec![1.0, 5.0, 7.5, 10.0, 6.0];
|
||||||
|
|
||||||
let team1_roles = team1.iter().map(|player| player.role).collect::<Vec<Role>>();
|
let team1_roles = team1.iter().map(|player| player.role).collect::<Vec<Role>>();
|
||||||
let team2_roles = team2.iter().map(|player| player.role).collect::<Vec<Role>>();
|
let team2_roles = team2.iter().map(|player| player.role).collect::<Vec<Role>>();
|
||||||
|
|
||||||
let team1_role_count = team1_roles.iter().filter(|role| **role == expected).count();
|
let team1_role_count = team1_roles.iter().filter(|role| **role == expected).count();
|
||||||
let team2_role_count = team2_roles.iter().filter(|role| **role == expected).count();
|
let team2_role_count = team2_roles.iter().filter(|role| **role == expected).count();
|
||||||
let prioritize_role = team1_role_count == 0 || team2_role_count == 0;
|
|
||||||
|
let max_role_players = match expected {
|
||||||
|
Role::Tank => 2,
|
||||||
|
Role::Dps | Role::Support => 4,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
|
let prioritize_role = (team1_role_count + team2_role_count) < max_role_players;
|
||||||
|
|
||||||
if !prioritize_role {
|
if !prioritize_role {
|
||||||
return false;
|
return false;
|
||||||
@@ -102,7 +155,7 @@ impl Mixer {
|
|||||||
).cloned().collect::<Vec<Player>>();
|
).cloned().collect::<Vec<Player>>();
|
||||||
|
|
||||||
let primary = players.iter().filter(|player|
|
let primary = players.iter().filter(|player|
|
||||||
player.primary_role == expected && (player.secondary_role != Role::None || player.tertiary_role == Role::None)
|
player.primary_role == expected && (player.secondary_role != Role::None || player.tertiary_role != Role::None)
|
||||||
).cloned().collect::<Vec<Player>>();
|
).cloned().collect::<Vec<Player>>();
|
||||||
|
|
||||||
let secondary = players.iter().filter(|player|
|
let secondary = players.iter().filter(|player|
|
||||||
@@ -118,7 +171,7 @@ impl Mixer {
|
|||||||
).cloned().collect::<Vec<Player>>();
|
).cloned().collect::<Vec<Player>>();
|
||||||
|
|
||||||
|
|
||||||
let average_tank_skill = Self::average_rank(team1, team2, expected);
|
let average_role_rank = Self::average_rank(team1, team2, expected);
|
||||||
|
|
||||||
for player in otp {
|
for player in otp {
|
||||||
let rank = match expected {
|
let rank = match expected {
|
||||||
@@ -127,7 +180,7 @@ impl Mixer {
|
|||||||
Role::Support => player.support,
|
Role::Support => player.support,
|
||||||
_ => 0.0
|
_ => 0.0
|
||||||
};
|
};
|
||||||
let skill_difference = (rank - average_tank_skill).abs();
|
let skill_difference = Self::calculate_rank_difference(average_role_rank, rank);
|
||||||
|
|
||||||
priorities.insert((expected, player.id), rank / group_coefficients[0] / (skill_difference + 1.0));
|
priorities.insert((expected, player.id), rank / group_coefficients[0] / (skill_difference + 1.0));
|
||||||
}
|
}
|
||||||
@@ -139,7 +192,7 @@ impl Mixer {
|
|||||||
Role::Support => player.support,
|
Role::Support => player.support,
|
||||||
_ => 0.0
|
_ => 0.0
|
||||||
};
|
};
|
||||||
let skill_difference = (rank - average_tank_skill).abs();
|
let skill_difference = Self::calculate_rank_difference(average_role_rank, rank);
|
||||||
|
|
||||||
priorities.insert((expected, player.id), rank / group_coefficients[1] / (skill_difference + 1.0));
|
priorities.insert((expected, player.id), rank / group_coefficients[1] / (skill_difference + 1.0));
|
||||||
}
|
}
|
||||||
@@ -151,7 +204,7 @@ impl Mixer {
|
|||||||
Role::Support => player.support,
|
Role::Support => player.support,
|
||||||
_ => 0.0
|
_ => 0.0
|
||||||
};
|
};
|
||||||
let skill_difference = (rank - average_tank_skill).abs();
|
let skill_difference = Self::calculate_rank_difference(average_role_rank, rank);
|
||||||
|
|
||||||
priorities.insert((expected, player.id), rank / group_coefficients[2] / (skill_difference + 1.0));
|
priorities.insert((expected, player.id), rank / group_coefficients[2] / (skill_difference + 1.0));
|
||||||
}
|
}
|
||||||
@@ -163,7 +216,7 @@ impl Mixer {
|
|||||||
Role::Support => player.support,
|
Role::Support => player.support,
|
||||||
_ => 0.0
|
_ => 0.0
|
||||||
};
|
};
|
||||||
let skill_difference = (rank - average_tank_skill).abs();
|
let skill_difference = Self::calculate_rank_difference(average_role_rank, rank);
|
||||||
|
|
||||||
priorities.insert((expected, player.id), rank / group_coefficients[3] / (skill_difference + 1.0));
|
priorities.insert((expected, player.id), rank / group_coefficients[3] / (skill_difference + 1.0));
|
||||||
}
|
}
|
||||||
@@ -175,7 +228,7 @@ impl Mixer {
|
|||||||
Role::Support => player.support,
|
Role::Support => player.support,
|
||||||
_ => 0.0
|
_ => 0.0
|
||||||
};
|
};
|
||||||
let skill_difference = (rank - average_tank_skill).abs();
|
let skill_difference = Self::calculate_rank_difference(average_role_rank, rank);
|
||||||
|
|
||||||
priorities.insert((expected, player.id), rank / group_coefficients[4] / (skill_difference + 1.0));
|
priorities.insert((expected, player.id), rank / group_coefficients[4] / (skill_difference + 1.0));
|
||||||
}
|
}
|
||||||
@@ -183,7 +236,14 @@ impl Mixer {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_highest_priority_player(&self, players: &Vec<Model>, priorities: &HashMap<(Role, i32), f32>) -> Option<MixedPlayer> {
|
fn calculate_rank_difference(average_rank: f32, rank: f32) -> f32 {
|
||||||
|
match average_rank {
|
||||||
|
0.0 => 0.0,
|
||||||
|
_ => (rank - average_rank).abs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_highest_priority_player(&self, players: &Vec<Player>, priorities: &HashMap<(Role, i32), f32>) -> Option<MixedPlayer> {
|
||||||
let mut highest_priority = 0.0;
|
let mut highest_priority = 0.0;
|
||||||
let mut highest_priority_player = None;
|
let mut highest_priority_player = None;
|
||||||
|
|
||||||
@@ -203,4 +263,23 @@ impl Mixer {
|
|||||||
|
|
||||||
highest_priority_player
|
highest_priority_player
|
||||||
}
|
}
|
||||||
|
fn priorities_to_array(priorities: HashMap<(Role, i32), f32>, players: &Vec<Player>) -> Vec<MixedPlayer> {
|
||||||
|
let mut sorted: Vec<MixedPlayer> = vec![];
|
||||||
|
for role in vec![Role::Tank, Role::Dps, Role::Support] {
|
||||||
|
for player in players {
|
||||||
|
if let Some(priority) = priorities.get(&(role, player.id)) {
|
||||||
|
sorted.push(MixedPlayer {
|
||||||
|
role,
|
||||||
|
player: player.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sorted.sort_by(|p1, p2| priorities.get(&(p2.role, p2.player.id)).unwrap()
|
||||||
|
.total_cmp(priorities.get(&(p1.role, p1.player.id)).unwrap())
|
||||||
|
);
|
||||||
|
|
||||||
|
sorted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Ord, PartialOrd, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub enum Role {
|
pub enum Role {
|
||||||
Tank,
|
Tank,
|
||||||
Dps,
|
Dps,
|
||||||
@@ -9,6 +9,7 @@ pub enum Role {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl PartialEq<i32> for Role {
|
impl PartialEq<i32> for Role {
|
||||||
fn eq(&self, other: &i32) -> bool {
|
fn eq(&self, other: &i32) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
Reference in New Issue
Block a user