<commit_before>package server;

import java.io.IOException;
import java.net.BindException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;

import messages.MessageType;
import server.connectivity.Connection;
import server.connectivity.ConnectionWaiter;
import server.player.TrackScheduler;
import utilities.IO;
import utilities.ProcessCommunicator;

/**A server, that includes classes to stream videos from youtube or audio files given
 * by a client 
 * 
 * @author Mellich
 *
 */
public class YTJBServer implements Server {
	
	/**
	 * the standard port will be used, when no other port is given
	 */
	public static final int PORT = 12345;
	
	private long version = 816L;
	
	public String workingDirectory;
	
	/**
	 * the server socket to handle connections to the server
	 */
	private ServerSocket server;
	
	private int port;
	
	/**
	 * the connection waiter of the server
	 */
	private ConnectionWaiter waiter;
	
	/**
	 * the music scheduler of the server
	 */
	private TrackScheduler scheduler;
	
	/**
	 * a list of tracks, that are "wished" by clients to play
	 */
	private LinkedList<MusicTrack> wishList;
	
	/**
	 * a list of tracks, that will be used when the wish list is empty
	 */
	private LinkedList<MusicTrack> gapList;
	
	/**
	 * list of clients connected to the server
	 */
	private ArrayList<Connection> notifiables;
	
	private ArrayList<Connection> player;
	
	private InitFileCommunicator initFile;
	
	private String currentGapList;
	
	private ArrayList<String> gapLists;
	
	private GapListLoader gapListLoader;
	
	private Semaphore playerFinished = new Semaphore(0);
	
	private int maxGapListTracks = 0;
	
	private Thread connectionBroadcast = null;
	
	private VotingController votingController;

	private URLParser[] urlParser;
	
	
	private void notifyParser(){
		for (URLParser p : urlParser){
			p.notifyNewURL();
		}
	}
	
	
	/**
	 * starts the server and makes him ready for work
	 */
	public void startUp(){
			ProcessCommunicator.updateYoutubeDL(workingDirectory);
			currentGapList = initFile.getStartUpGapList();
			searchGapLists();	
			urlParser = new URLParser[Runtime.getRuntime().availableProcessors()];
			for (int i = 0; i < urlParser.length; i++){
				this.urlParser[i] = new URLParser(this,scheduler,i);
				urlParser[i].start();
			}
			gapListLoader = new GapListLoader(this);
			gapListLoader.start();
			waiter.start();
			scheduler.start();
			ProcessCommunicator.startPlayer(getIpAddress(),port,workingDirectory);
			this.connectionBroadcast = new Thread(new ConnectionBroadcast(getIpAddress(),port,this));
			this.connectionBroadcast.start();
			IO.printlnDebug(this, "New server opened on address "+getIpAddress()+" port "+port);
	}
	
	public String getWorkingDir(){
		return workingDirectory;
	}
	
	public long getVote(long macAddress){
		return votingController.getVotedTrackID(macAddress);
	}
	
	public boolean removeVote(long macAddress){
		if (votingController.removeVote(macAddress)){
			this.notifyClients(MessageType.WISHLISTUPDATEDNOTIFY, this.listToArray(wishList));
			return true;
		}
		return false;		
	}
	
	public boolean addVote(long trackID,long macAddress){
		if (votingController.addVote(trackID, macAddress)){
			this.notifyClients(MessageType.WISHLISTUPDATEDNOTIFY, this.listToArray(wishList));
			return true;
		}
		return false;
	}
	
	private synchronized ArrayList<String> listToArray(LinkedList<MusicTrack> list){
		ArrayList<String> result = new ArrayList<String>();
		for (int i = 0; i < list.size(); i++){
			result.add(""+list.get(i).getTrackID());
			result.add(list.get(i).getTitle());
			result.add(""+list.get(i).getVoteCount());
			result.add(""+list.get(i).getParseStatus());
			result.add(""+list.get(i).getShortURL());
		}
		return result;
	}
	
	public int getCurrentClientCount(){
		return notifiables.size();
	}
	
	public int getCurrentPlayerCount(){
		return player.size();
	}
	
	/**adds a MusicTrack to a list
	 * 
	 * @param track the track to be added
	 * @param toWishList if true, track will be added to wish list
	 * @param atFirst if true, track will be added at the beginning of the list and at the and, if the value is false
	 */
	public synchronized void addToList(MusicTrack track,boolean toWishList, boolean atFirst){
		boolean existsParsed = this.existsParsedURL();
		if (toWishList){
			if (atFirst){
				if (!wishList.isEmpty()){
					int i = wishList.size();
					while(wishList.get(i - 1).getVoteCount() == 0){
						i--;
					}
					wishList.add(i, track);
				} else wishList.add(track);
			}
			else wishList.add(track);
			this.notifyClients(MessageType.WISHLISTUPDATEDNOTIFY,this.listToArray(wishList));
		}
		else{
			if (atFirst)
				gapList.addFirst(track);
			else gapList.add(track);
			if (!track.isFromSavedGapList())
				this.setMaxGapListTrackCount(this.getMaxLoadedGapListTracksCount() + 1);
			if (this.getMaxLoadedGapListTracksCount() <= gapList.size())
				this.notifyClients(MessageType.GAPLISTUPDATEDNOTIFY,this.listToArray(gapList));
		}<commit_msg>bug fixes<commit_after>package server;

import java.io.IOException;
import java.net.BindException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;

import messages.MessageType;
import server.connectivity.Connection;
import server.connectivity.ConnectionWaiter;
import server.player.TrackScheduler;
import utilities.IO;
import utilities.ProcessCommunicator;

/**A server, that includes classes to stream videos from youtube or audio files given
 * by a client 
 * 
 * @author Mellich
 *
 */
public class YTJBServer implements Server {
	
	/**
	 * the standard port will be used, when no other port is given
	 */
	public static final int PORT = 12345;
	
	private long version = 816L;
	
	public String workingDirectory;
	
	/**
	 * the server socket to handle connections to the server
	 */
	private ServerSocket server;
	
	private int port;
	
	/**
	 * the connection waiter of the server
	 */
	private ConnectionWaiter waiter;
	
	/**
	 * the music scheduler of the server
	 */
	private TrackScheduler scheduler;
	
	/**
	 * a list of tracks, that are "wished" by clients to play
	 */
	private LinkedList<MusicTrack> wishList;
	
	/**
	 * a list of tracks, that will be used when the wish list is empty
	 */
	private LinkedList<MusicTrack> gapList;
	
	/**
	 * list of clients connected to the server
	 */
	private ArrayList<Connection> notifiables;
	
	private ArrayList<Connection> player;
	
	private InitFileCommunicator initFile;
	
	private String currentGapList;
	
	private ArrayList<String> gapLists;
	
	private GapListLoader gapListLoader;
	
	private Semaphore playerFinished = new Semaphore(0);
	
	private int maxGapListTracks = 0;
	
	private Thread connectionBroadcast = null;
	
	private VotingController votingController;

	private URLParser[] urlParser;
	
	
	private void notifyParser(){
		for (URLParser p : urlParser){
			p.notifyNewURL();
		}
	}
	
	
	/**
	 * starts the server and makes him ready for work
	 */
	public void startUp(){
			ProcessCommunicator.updateYoutubeDL(workingDirectory);
			currentGapList = initFile.getStartUpGapList();
			searchGapLists();	
			urlParser = new URLParser[Runtime.getRuntime().availableProcessors()];
			for (int i = 0; i < urlParser.length; i++){
				this.urlParser[i] = new URLParser(this,scheduler,i);
				urlParser[i].start();
			}
			gapListLoader = new GapListLoader(this);
			gapListLoader.start();
			waiter.start();
			scheduler.start();
			ProcessCommunicator.startPlayer(getIpAddress(),port,workingDirectory);
			this.connectionBroadcast = new Thread(new ConnectionBroadcast(getIpAddress(),port,this));
			this.connectionBroadcast.start();
			IO.printlnDebug(this, "New server opened on address "+getIpAddress()+" port "+port);
	}
	
	public String getWorkingDir(){
		return workingDirectory;
	}
	
	public long getVote(long macAddress){
		return votingController.getVotedTrackID(macAddress);
	}
	
	public boolean removeVote(long macAddress){
		if (votingController.removeVote(macAddress)){
			this.notifyClients(MessageType.WISHLISTUPDATEDNOTIFY, this.listToArray(wishList));
			return true;
		}
		return false;		
	}
	
	public boolean addVote(long trackID,long macAddress){
		if (votingController.addVote(trackID, macAddress)){
			this.notifyClients(MessageType.WISHLISTUPDATEDNOTIFY, this.listToArray(wishList));
			return true;
		}
		return false;
	}
	
	private synchronized ArrayList<String> listToArray(LinkedList<MusicTrack> list){
		ArrayList<String> result = new ArrayList<String>();
		for (int i = 0; i < list.size(); i++){
			result.add(""+list.get(i).getTrackID());
			result.add(list.get(i).getTitle());
			result.add(""+list.get(i).getVoteCount());
			result.add(""+list.get(i).getParseStatus());
			result.add(""+list.get(i).getShortURL());
		}
		return result;
	}
	
	public int getCurrentClientCount(){
		return notifiables.size();
	}
	
	public int getCurrentPlayerCount(){
		return player.size();
	}
	
	/**adds a MusicTrack to a list
	 * 
	 * @param track the track to be added
	 * @param toWishList if true, track will be added to wish list
	 * @param atFirst if true, track will be added at the beginning of the list and at the and, if the value is false
	 */
	public synchronized void addToList(MusicTrack track,boolean toWishList, boolean atFirst){
		boolean existsParsed = this.existsParsedURL();
		if (toWishList){
			if (atFirst){
				if (!wishList.isEmpty()){
					int i = wishList.size();
					while(i > 0 && wishList.get(i - 1).getVoteCount() == 0){
						i--;
					}
					wishList.add(i, track);
				} else wishList.add(track);
			}
			else wishList.add(track);
			this.notifyClients(MessageType.WISHLISTUPDATEDNOTIFY,this.listToArray(wishList));
		}
		else{
			if (atFirst)
				gapList.addFirst(track);
			else gapList.add(track);
			if (!track.isFromSavedGapList())
				this.setMaxGapListTrackCount(this.getMaxLoadedGapListTracksCount() + 1);
			if (this.getMaxLoadedGapListTracksCount() <= gapList.size())
				this.notifyClients(MessageType.GAPLISTUPDATEDNOTIFY,this.listToArray(gapList));
		}
{'fraction_non_alphanumeric': 0.11015077307212139, 'fraction_numerical': 0.0031691155286660906, 'mean_word_length': 4.368041237113402, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 22, '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': '232861', 'n_tokens_mistral': 3621, 'n_tokens_neox': 3149, 'n_words': 831}