<commit_before>package core;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.tuple.Pair;



public class Marche {
	private boolean ouvert;
	private boolean fini;
	private long debut;
	private Map<Action, Set<Ordre>> liste_achats;
	private Map<Action, Set<Ordre>> liste_ventes;
	private List<Joueur> liste_joueurs;
	private Set<Integer> liste_id_ordres;
	private Map<Action, Set<Echange>> historiques;
	private final Lock mutex = new ReentrantLock();
	private Thread timer = null;

	public Marche() {
		ouvert = false;
		fini = false;
		liste_achats = new HashMap<>();
		liste_ventes = new HashMap<>();
		historiques = new HashMap<>();
		for (Action a : Action.values()) {
			liste_achats.put(a, new TreeSet<Ordre>());
			liste_ventes.put(a, new TreeSet<Ordre>());
			historiques.put(a, new TreeSet<Echange>());
		}
		liste_joueurs = new LinkedList<>();
		liste_id_ordres = new TreeSet<>();
		
		if(Config.getInstance().BANQUE){
			Joueur banque = creer_joueur("banque");
			banque.setSolde_euros(Integer.MAX_VALUE);
			int max_action_en_jeu = Config.getInstance().SOLDE_ACTIONS_INIT*Action.values().length*100;//100 joueurs
			for(Action a : Action.values()){
				banque.getSolde_actions().put(a, Integer.MAX_VALUE);
				achat(banque, a, 0.25f, max_action_en_jeu);
				vend(banque, a, 25.0f, max_action_en_jeu);
			}
		}
	}

	public boolean est_ouvert() {
		return ouvert;
	}

	public void commence() {
		ouvert = true;
		debut = System.currentTimeMillis();

		timer = new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000 * 60 * Config.getInstance().TEMPS_PARTIE);
				} catch (InterruptedException e) {
					//might be interrupted if creator leaves
					//don't print error in this case
				}
				fini = true;
				try {
					Thread.sleep(1000 * 60); // sleep 1 s to be sure fini is taking into account
				} catch (InterruptedException e) {
					//might be interrupted if creator leaves
					//don't print error in this case
				}
				//fermer tous les ordres
				for(Joueur joueur : liste_joueurs){
					List<Integer> ordre_supprimer = new LinkedList<>();
					for(Pair<Integer, Ordre> t : joueur.getOperationsOuvertes()){
						ordre_supprimer.add(t.getLeft());
					}
					for(Integer i : ordre_supprimer){
						annuler(joueur, i);
					}
				}
			}
		};
		timer.start();
	}

	public boolean est_fini() {
		return fini;
	}

	public synchronized Joueur creer_joueur(String nom) {
		Joueur j = new Joueur(nom);
		liste_joueurs.add(j);
		return j;
	}

	public synchronized boolean nom_possible(String nom) {
		for (Joueur j : liste_joueurs)
			if (j.getNom().equalsIgnoreCase(nom))
				return false;
		return true;
	}

	public Set<Ordre> getListeAchats(Action a) {
		return liste_achats.get(a);
	}

	public Set<Ordre> getListeVentes(Action a) {
		return liste_ventes.get(a);
	}

	
	public LinkedList<Echange> getHistoriqueEchanges(Action a,int n) {
		/**
		 * @param a : le nom de l'action
		 * @param n : le numéro de liste à partir duquel il faut envoyer les éléments historiques du serveur au client
		 * @return  : retourne une liste chainée contenant les éléments de 'historiques' voulus
		 */
		
		int tailleH=historiques.get(a).size(); //Pour calculer une seule fois la taille de la liste
		LinkedList<Echange> list = new LinkedList<Echange>();//on instancie la liste chainée que l'on va remplir
		
		//on crée un iterateur parcourant 'historiques' dans le sens décroissant
		final Iterator<Echange> i = ((TreeSet<Echange>) historiques.get(a)).descendingIterator();
		for (int j=0; j<tailleH-n && i.hasNext();j++)
			//on ajoute dans la liste chainée les éléments au sens décroissants de 'historiques'
			//au début de la liste chainée à chaque fois pour que les éléments apparaissent dans le bon sens
			list.addFirst(i.next());
		
		//on retourne la liste chainée
		return list;
	}

	public int achat(Joueur joueur_achat, Action a, float prix_achat, int volume_achat) {
		if (volume_achat <= 0.0)
			return -5;
		if (prix_achat <= 0.0)
			return -6;

		mutex.lock();
		int argent_joueur = joueur_achat.getSolde_euros();
		int argent_engage = (int) (volume_achat * prix_achat);
		if (argent_joueur < argent_engage) {
			mutex.unlock();
			return -7;
		}

		Iterator<Ordre> it = liste_ventes.get(a).iterator();

		while (it.hasNext() && volume_achat > 0) {
			Ordre vente = it.next();
			Joueur joueur_vente = vente.getJoueur();

			if (prix_achat >= vente.prix) {
				Echange e = new Echange(joueur_vente, joueur_achat, vente.prix, Math.min(vente.volume, volume_achat));
				historiques.get(a).add(e);

				// l'achat est complete
				if (volume_achat <= vente.volume) {
					int volume_vendu = volume_achat;

					joueur_vente.setSolde_euros(joueur_vente.getSolde_euros() + (int) (vente.prix * volume_vendu));
					joueur_achat.setSolde_euros(joueur_achat.getSolde_euros() - (int) (vente.prix * volume_vendu));
					joueur_achat.getSolde_actions().put(a, joueur_achat.getSolde_actions().get(a) + volume_vendu);
					vente.setVolume(vente.getVolume() - volume_vendu);
					
					//ordre restant vide
					if(vente.getVolume() == 0){
						Integer id_vente = vente.getId_ordre();
						joueur_vente.retirerOperation(id_vente);
						it.remove();
					}

					//ordre restant vide
					if(vente.getVolume() == 0){
						Integer id_vente = vente.getId_ordre();
						joueur_vente.retirerOperation(id_vente);
						it.remove();
					}
					
					
					mutex.unlock();
					return 0;
				}
				// volume_achat > vente.volume

				int volume_vendu = vente.volume;
<commit_msg>correction #2<commit_after>package core;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.tuple.Pair;



public class Marche {
	private boolean ouvert;
	private boolean fini;
	private long debut;
	private Map<Action, Set<Ordre>> liste_achats;
	private Map<Action, Set<Ordre>> liste_ventes;
	private List<Joueur> liste_joueurs;
	private Set<Integer> liste_id_ordres;
	private Map<Action, Set<Echange>> historiques;
	private final Lock mutex = new ReentrantLock();
	private Thread timer = null;

	public Marche() {
		ouvert = false;
		fini = false;
		liste_achats = new HashMap<>();
		liste_ventes = new HashMap<>();
		historiques = new HashMap<>();
		for (Action a : Action.values()) {
			liste_achats.put(a, new TreeSet<Ordre>());
			liste_ventes.put(a, new TreeSet<Ordre>());
			historiques.put(a, new TreeSet<Echange>());
		}
		liste_joueurs = new LinkedList<>();
		liste_id_ordres = new TreeSet<>();
		
		if(Config.getInstance().BANQUE){
			Joueur banque = creer_joueur("banque");
			banque.setSolde_euros(Integer.MAX_VALUE);
			int max_action_en_jeu = Config.getInstance().SOLDE_ACTIONS_INIT*Action.values().length*100;//100 joueurs
			for(Action a : Action.values()){
				banque.getSolde_actions().put(a, Integer.MAX_VALUE);
				achat(banque, a, 0.25f, max_action_en_jeu);
				vend(banque, a, 25.0f, max_action_en_jeu);
			}
		}
	}

	public boolean est_ouvert() {
		return ouvert;
	}

	public void commence() {
		ouvert = true;
		debut = System.currentTimeMillis();

		timer = new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000 * 60 * Config.getInstance().TEMPS_PARTIE);
				} catch (InterruptedException e) {
					//might be interrupted if creator leaves
					//don't print error in this case
				}
				fini = true;
				try {
					Thread.sleep(1000 * 60); // sleep 1 s to be sure fini is taking into account
				} catch (InterruptedException e) {
					//might be interrupted if creator leaves
					//don't print error in this case
				}
				//fermer tous les ordres
				for(Joueur joueur : liste_joueurs){
					List<Integer> ordre_supprimer = new LinkedList<>();
					for(Pair<Integer, Ordre> t : joueur.getOperationsOuvertes()){
						ordre_supprimer.add(t.getLeft());
					}
					for(Integer i : ordre_supprimer){
						annuler(joueur, i);
					}
				}
			}
		};
		timer.start();
	}

	public boolean est_fini() {
		return fini;
	}

	public synchronized Joueur creer_joueur(String nom) {
		Joueur j = new Joueur(nom);
		liste_joueurs.add(j);
		return j;
	}

	public synchronized boolean nom_possible(String nom) {
		for (Joueur j : liste_joueurs)
			if (j.getNom().equalsIgnoreCase(nom))
				return false;
		return true;
	}

	public Set<Ordre> getListeAchats(Action a) {
		return liste_achats.get(a);
	}

	public Set<Ordre> getListeVentes(Action a) {
		return liste_ventes.get(a);
	}

	/**
	 * @param a : le nom de l'action
	 * @param n : le numéro de liste à partir duquel il faut envoyer les éléments historiques du serveur au client
	 * @return  : retourne une liste chainée contenant les éléments de 'historiques' voulus
	 */
	public LinkedList<Echange> getHistoriqueEchanges(Action a,int n) {
		int tailleH=historiques.get(a).size(); //Pour calculer une seule fois la taille de la liste
		LinkedList<Echange> list = new LinkedList<Echange>();//on instancie la liste chainée que l'on va remplir
		
		//on crée un iterateur parcourant 'historiques' dans le sens décroissant
		final Iterator<Echange> i = ((TreeSet<Echange>) historiques.get(a)).descendingIterator();
		for (int j=0; j<tailleH-n && i.hasNext();j++)
			//on ajoute dans la liste chainée les éléments au sens décroissants de 'historiques'
			//au début de la liste chainée à chaque fois pour que les éléments apparaissent dans le bon sens
			list.addFirst(i.next());
		
		//on retourne la liste chainée
		return list;
	}

	public int achat(Joueur joueur_achat, Action a, float prix_achat, int volume_achat) {
		if (volume_achat <= 0.0)
			return -5;
		if (prix_achat <= 0.0)
			return -6;

		mutex.lock();
		int argent_joueur = joueur_achat.getSolde_euros();
		int argent_engage = (int) (volume_achat * prix_achat);
		if (argent_joueur < argent_engage) {
			mutex.unlock();
			return -7;
		}

		Iterator<Ordre> it = liste_ventes.get(a).iterator();

		while (it.hasNext() && volume_achat > 0) {
			Ordre vente = it.next();
			Joueur joueur_vente = vente.getJoueur();

			if (prix_achat >= vente.prix) {
				Echange e = new Echange(joueur_vente, joueur_achat, vente.prix, Math.min(vente.volume, volume_achat));
				historiques.get(a).add(e);

				// l'achat est complete
				if (volume_achat <= vente.volume) {
					int volume_vendu = volume_achat;

					joueur_vente.setSolde_euros(joueur_vente.getSolde_euros() + (int) (vente.prix * volume_vendu));
					joueur_achat.setSolde_euros(joueur_achat.getSolde_euros() - (int) (vente.prix * volume_vendu));
					joueur_achat.getSolde_actions().put(a, joueur_achat.getSolde_actions().get(a) + volume_vendu);
					vente.setVolume(vente.getVolume() - volume_vendu);
					
					//ordre restant vide
					if(vente.getVolume() == 0){
						Integer id_vente = vente.getId_ordre();
						joueur_vente.retirerOperation(id_vente);
						it.remove();
					}

					mutex.unlock();
					return 0;
				}
				// volume_achat > vente.volume

				int volume_vendu = vente.volume;

{'fraction_non_alphanumeric': 0.12168335969073976, 'fraction_numerical': 0.006677209629239149, 'mean_word_length': 3.6766639276910436, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4209714', 'n_tokens_mistral': 4851, 'n_tokens_neox': 4146, 'n_words': 969}