package cnam.nsy208.sudoku.bluetooth;
import cnam.nsy208.sudoku.main.Sudoku;
import cnam.nsy208.sudoku.model.CheckTimeOut;
import javax.bluetooth.*;
import javax.microedition.io.*;
import java.io.*;
import java.util.Vector;
/**
*
* @author Martial
*/
public class SudokuServer extends Thread implements BtInterface {
private Vector _client ;
private StreamConnectionNotifier _notifierServ ;
private StreamConnection _connServ ;
private LocalDevice _localDeviceServ ;
private OutputStream _outputServ ;
private InputStream _inputServ = null;
private boolean _isInitServ ;
private char[] _gridcharServ ;
private boolean _stopServ ;
private boolean _endlog ;
private Sudoku _controler ;
private int _number ;
private int _score ;
private CheckTimeOut _checkTimeOut;
private static String _serverUrlServ = "btspp://localhost:" + Sudoku.RFCOMM_UUID + ";name=SudokuServer;authorize=true";
/**
* Inialise les variables
* @param c : controlleur
* @param grid : grille
*/
public SudokuServer( Sudoku c , char[] grid ) {
_client = new Vector();
_controler = c ;
_number = 0 ;
_score = 100 ;
_isInitServ = false;
_endlog = false ;
_gridcharServ = grid ;
_checkTimeOut = new CheckTimeOut(this);
start();
}
/**
* Arrete le serveur
*/
public void stopServer() {
_stopServ = true ;
}
/**
* Démarre le serveur Sudoku
*/
public void run() {
String msg ;
String id ;
String data ;
String num ;
String strScore ;
_stopServ = false ;
_endlog = false ;
_number = 0 ;
if (!_isInitServ) {
// Initialization is done in the thread to avoid dead lock 'isInit' ensures it is done once only
try {
_connServ = null;
_localDeviceServ = LocalDevice.getLocalDevice();
_localDeviceServ.setDiscoverable(DiscoveryAgent.GIAC);
_notifierServ = (StreamConnectionNotifier) Connector.open( _serverUrlServ );
} catch (BluetoothStateException e) {
System.err.println("BluetoothStateException: " + e.getMessage());
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
}
_isInitServ = true;
System.out.println("Starting Echo Server");
}
try {
System.out.println("\n\nServer Running...");
while( !_stopServ ) {
// Pauses thread until Transmission occurs
_connServ = _notifierServ.acceptAndOpen();
_outputServ = _connServ.openOutputStream();
_inputServ = _connServ.openInputStream();
// Read Data Transmission
msg = readDataServ() ;
System.out.println("Received Message from Client: " + msg );
id = getId( msg ) ;
data = getData( msg ) ;
System.out.println( "id : " + id + " data : " + data ) ;
// INSCRIPTION
if( (id.compareTo( "I" ) == 0) ) {
if( _endlog == false ) {
System.out.println("Phase INSCRIPTION");
// Ajout d'un joueur dans la liste
_number+=10 ;
_controler.addPlayer( _number , data , 360000 ) ;
msg = new String( Integer.toString( _number ) );
while( msg.length() < 3 ) {
msg = "0" + msg ;
}
msg = "J" + msg ;
writeDataServ( msg ) ;
// DEMANDE DE GRILLE
msg = readDataServ() ;
id = getId( msg ) ;
data = getData( msg ) ;
System.out.println( "id : " + id + " data : " + data ) ;
if( id.compareTo( "D" ) == 0 ) {
System.out.println("Phase DEMANDE DE GRILLE");
data = new String( _gridcharServ );
msg = new String( "G" + data );
writeDataServ( msg );
}
_client.addElement( new BtClient( new UUID( _number ) , this ) ) ;
} else {
msg = new String( "A" );
writeDataServ( msg ) ;
}
}
// SOLUTION TROUVEE
if( id.compareTo( "R" ) == 0 ) {
System.out.println("Phase SOLUTION TROUVEE");
// Récupération du numero du joueur
num = data.substring( 0 , 3 );
while( num.substring( 0 , 1).compareTo( "0" ) == 0 ) {
num = num.substring( 1 , num.length() ) ;
}
// Récupération du score
if( data.length() > 3 ) {
strScore = new String( data.substring( 3 , data.length() ) ) ;
} else {
strScore = new String( "" ) ;
}
((BtClient)_client.elementAt((Integer.parseInt( num )/10)-1)).setActive(0);
_score = Integer.parseInt( strScore ) ;
_controler.setPlayerScore( Integer.parseInt( num ) , _score );
_controler.displayRanking() ;
}
_outputServ.close();
_inputServ.close() ;
}
} catch (Exception ex) {
System.err.println("Bluetooth Server Running Error: " + ex);
}
}
/**
* Lit des données sur la connexion BT serveur
* @return Les données lues
*/
public String readDataServ() {
byte[] data = null;
try {
// Probably want to throw an exception if length is not greater then 0
int length = _inputServ.read();
data = new byte[length];
length = 0;
// Assemble data
while (length != data.length) {
int ch = _inputServ.read(data, length, data.length - length);
if (ch == -1) {
throw new IOException("Can't read data");
}
length += ch;
}
} catch (IOException e) {
System.err.println(e);
}
return new String(data);
}
/**
* Ecrit des données sur la connexion BT serveur
* @param msg : Données à écrire
*/
public void writeDataServ( String msg ) {
try {
_outputServ.write(msg.length()); // length is 1 byte
_outputServ.write(msg.getBytes());
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* Retourne l'Identifiant de trame
* @param msg : Message à identifier
* @return Identifiant
*/
public String getId( String msg ) {
return msg.substring( 0 , 1 );
}
/**
* Retourne les données utiles du message
* @param msg : message à parser
* @return Données utilies
*/
public String getData( String msg ) {
String data ;
if( msg.length() > 1 ) {
data = new String( msg.substring( 1 , msg.length() ) ) ;
} else {
data = new String( "" ) ;
}
return data ;
}
/**
* Envoi un message de début du tournoi à tous les client BT
*/
public void startTournament() {
String msg = new String( "T" + _controler.getNbPlayer() );
BtClient cl ;
_endlog = true ;
for( int i = 0 ; i < _controler.getNbPlayer() ; i++ ) {
cl = (BtClient) _client.elementAt(i) ;
cl.open() ;
// Envoie du top départ
cl.writeData( msg );
cl.close();
cl.startTimer();
}
_checkTimeOut.start();
}
/**
* Envoi un message de fin de partie à tous les clients BT
*/
public void sendEndMessage(){
// End of game
String msgRank = new String( "F" );
BtClient cl ;
for( int i = 0 ; i < _controler.getNbPlayer() ; i++ ) {
cl = (BtClient) _client.elementAt(i) ;
cl.open() ;
// Envoi de la trame de fin
cl.writeData( msgRank );
// Envoi de la trame de classement
this.sendRanking( cl ) ;
cl.setActive( 0 );
cl.close();
}
}
/**
* Envoi le classement à un client BT
* @param cl : Client BT
*/
private void sendRanking(BtClient cl) {
String msgRank = new String( "S" + _controler.getRanking() );
cl.writeData( msgRank );
}
/**
* Fonction d'initialisation des client Bt
*/
public void init() {
}
/**
* Retourne la liste des client BT inscrit auprés du serveur
* @return
*/
public Vector getClients() {
return _client;
}
}