i question my life decisions

This commit is contained in:
Suiranoil
2023-04-04 15:51:21 +03:00
parent 6ceddceca4
commit 89cc771834
3 changed files with 106 additions and 15 deletions

View File

@@ -12,6 +12,7 @@ use serenity::model::id::{ChannelId, RoleId, UserId};
use serenity::model::Permissions;
use crate::bot::commands::MixerCommand;
use crate::database::DatabaseContainer;
use crate::mixer::mixer::Mixer;
#[derive(Clone)]
pub struct LobbyCommand;
@@ -149,9 +150,19 @@ impl LobbyCommand {
let members = main_channel.members(ctx.cache().unwrap()).await?;
let users = members.iter().map(|m| m.user.id).collect::<Vec<UserId>>();
let players = db.get_players(users).await;
let players = db.get_players((0..10).map(|id| UserId(id)).collect()).await;
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| {
response.kind(InteractionResponseType::ChannelMessageWithSource)
.interaction_response_data(|message| {

View File

@@ -29,16 +29,33 @@ impl Mixer {
let mut team1 = 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::priorities_to_array(priorities, &players);
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) {
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 {
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);
}
@@ -72,6 +89,10 @@ impl Mixer {
let selected_players = team1.iter().filter(|player| player.role == role)
.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| {
match player.role {
Role::Tank => player.player.tank,
@@ -82,15 +103,47 @@ impl Mixer {
}).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 {
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 team2_roles = team2.iter().map(|player| player.role).collect::<Vec<Role>>();
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 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 {
return false;
@@ -102,7 +155,7 @@ impl Mixer {
).cloned().collect::<Vec<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>>();
let secondary = players.iter().filter(|player|
@@ -118,7 +171,7 @@ impl Mixer {
).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 {
let rank = match expected {
@@ -127,7 +180,7 @@ impl Mixer {
Role::Support => player.support,
_ => 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));
}
@@ -139,7 +192,7 @@ impl Mixer {
Role::Support => player.support,
_ => 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));
}
@@ -151,7 +204,7 @@ impl Mixer {
Role::Support => player.support,
_ => 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));
}
@@ -163,7 +216,7 @@ impl Mixer {
Role::Support => player.support,
_ => 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));
}
@@ -175,7 +228,7 @@ impl Mixer {
Role::Support => player.support,
_ => 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));
}
@@ -183,7 +236,14 @@ impl Mixer {
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_player = None;
@@ -203,4 +263,23 @@ impl Mixer {
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
}
}

View File

@@ -1,7 +1,7 @@
use std::hash::{Hash, Hasher};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[derive(Debug, Ord, PartialOrd, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Role {
Tank,
Dps,
@@ -9,6 +9,7 @@ pub enum Role {
None
}
impl PartialEq<i32> for Role {
fn eq(&self, other: &i32) -> bool {
match self {