package molekuly;

import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

import rup.česky.společně.P;

import rup.česky.tvary.Kruh;


/*******************************************************************************
 * Třída Molekula_13a definuje metody, které vygenerují na plátno
 * náhodně rozmístěné molekuly, které pak další verze třídy rozpohybují.
 * Slouží především k demonstraci práce s množinami.
 *
 * @author    Rudolf Pecinovský
 * @version   0.00.000,  0.0.2003
 */
public class Molekula_13a extends Kruh
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Frekvence překreslování plánta s molekulami. */
    private static final int FREKVENCE = 50;

    /** MAximální počet pokusů věnovaných na umístění další moelkuly. */
    private static final int POKUSŮ = 3;

    /** Společný průměr všech moelkul. */
    private static final int PRŮMĚR = 50;

    /** Maximální povolená rychlost molekuly,
     * tj. kolik bodů může molekula urazit za sekundu. */
    private static int maxR = 300 ;

    /** Množina všech dosud vygenerovaných molekul. */
    private static final Set<Molekula_13a> molekuly =
                           new LinkedHashSet<Molekula_13a>();

    /** Společný generátor náhodných čísel. */
    private static final Random rnd = new Random();





//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================

    /** Počet dosud vytvořených instancí. */
    private static int počet = 0;

    /** Maximální povolené souřadnice molekuly. */
    private static int maxX;
    private static int maxY;

    static { nastavMaxima(); }



//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Pořadí vytvoření dané instance v rámci třídy. */
    private final int pořadí = ++počet;


//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** Složky aktuální pozice molekuly. */
    private double x, y;

    /** Složky aktuální rychlosti molekuly. */
    private double rx, ry;



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ METODY TŘÍDY ======================================================

    /***************************************************************************
     * Nastaví maximální povolené souřadnice molekul
     * podle aktuální velikosti aktivního plátna.
     */
    public static void nastavMaxima()
    {
        maxX = AP.getBšířka() - PRŮMĚR;
        maxY = AP.getBVýška() - PRŮMĚR;
    }

//------------------------------------------------------------------------------

    /***************************************************************************
     * Vytvoří zadaný počet náhodně umístěných molekul.
     *
     * @param molekul   Požadovaný počet vytvořených molekul
     */
    public static void nováSada_1( int molekul )
    {
        molekuly.clear();   //Zapomenu všechny dříve uložené
        for( int m=1;   m <= molekul;   m++ )
        {
            System.out.println("Generace " + (počet+1) + ". molekuly:");
            další_1();
        }
    }


    /***************************************************************************
     * Najde náhodné umístění další molekuly tak, aby se nepřekrývala s žádnou
     * z dosud vytvořených molekul, a nechá molekulu na této pozici vytvořit.
     */
    public static void další_1()
    {
        int x, y;         //Navrhované souřadnice nové molekuly
        int K_PROVĚŘENÍ = molekuly.size();  //Počet dosud vytvořených
        int prověřeno;
        int pokus = 0;
        do{
            //Generace návrhu nové pozice
            x = rnd.nextInt( maxX );
            y = rnd.nextInt( maxY );
            System.out.print( "  " + ++pokus + ". pokus: x=" + x +
                                                      ", y=" + y );
            //Otestování případných kolizí
            prověřeno = 0;
            //Projdeme množinu a otestujeme molekulu za molekulou
            for( Molekula_13a m : molekuly )
            {
                if( PRŮMĚR > P.délka( x, y, m.x,  m.y ) )
                {
                    System.out.println(" koliduje s " + m.pořadí +
                                       ". molekulou" );
                    break;
                }
                prověřeno++;    //Další byla prověřena
            }
        //Nebyly-li prověřeny všechny, je třeba zkusit znovu
        }while( prověřeno < K_PROVĚŘENÍ );
        System.out.println( " - ÚSPĚŠNÝ" );

        Molekula_13a m = new Molekula_13a( x, y );
    }

//------------------------------------------------------------------------------

    /***************************************************************************
     * Vytvoří sadu náhodně umístěných molekul. Generaci ukončí poté,
     * co se po zadaném počtu pokusů nepodaří najít vhodné umístění
     * pro další molekulu.
     *
     * @param molekul   Maximálně povolený počet pokusů při hledání
     *                  pozice vytvářené molekuly
     */
    public static int nováSada_2( int pokusů )
    {
        int počet = 0;
        molekuly.clear();
        do{
            System.out.println("Generace " + ++počet + ". molekuly:");
        }while( další_2( pokusů ) );   //Dokud se daří molekuly generovat
        System.out.println("Vygenerovali jsme " + (počet-1) + " molekul");
        return počet - 1;
    }

//------------------------------------------------------------------------------

    /***************************************************************************
     * Vytvoří sadu náhodně umístěných molekul. Generaci ukončí poté,
     * so se po zadaném počtu pokusů nepodaří najít umístění pro další molekulu.
     *
     * @param molekul   Požadovaný počet vytvořených molekul
     */
    public static int nováSada_3( int molekul, int pokusů )
    {
        int počet = 0;
        molekuly.clear();
        do{
            if( ++počet > molekul )
                return počet;
            System.out.println("Generace " + počet + ". molekuly:");
        }while( další_2( pokusů ) );    //Dokud se daří molekuly generovat
        System.out.println("Vygenerovali jsme " + (počet-1) + " molekul");
        return počet-1 ;
    }

//------------------------------------------------------------------------------

    /***************************************************************************
     * Najde náhodné umístění další molekuly tak, aby se nepřekrývala s žádnou
     * z dosud vytvořených molekul, a nechá molekulu na této pozici vytvořit.
     * Nepodaří-li se to do zadaného maximálního počtu pokusů,
     * vzdá další snažení a vrátí false. Jinak vrátí true.
     *
     * @param pokusů    Maximálně povolený počet pokusů při hledání
     *                  pozice vytvářené molekuly
     *
     * @return Příznak úspěšnosti: true = podařilo se vytvořit další molekulu
     */
    public static boolean další_2( int pokusů )
    {
        int x, y;         //Navrhované souřadnice nové molekuly
        int K_PROVĚŘENÍ = molekuly.size();  //Počet dosud vytvořených
        int prověřeno;
        int pokus = 0;
        do{
            if( pokus >= pokusů )
                return false;   //Na daný počet pokusů se generace nezdařila

            //Generace návrhu nové pozice
            x = rnd.nextInt( maxX );
            y = rnd.nextInt( maxY );
            System.out.print( "  " + ++pokus + ". pokus: x=" + x +
                                                      ", y=" + y );
            //Otestování případných kolizí
            prověřeno = 0;
            //Projdeme množinu a otestujeme molekulu za molekulou
            for( Molekula_13a m : molekuly )
            {
                if( PRŮMĚR > P.délka( x, y, m.x,  m.y ) )
                {
                    System.out.println(" koliduje s " + m.pořadí +
                                       ". molekulou" );
                    break;
                }
                prověřeno++;    //Další byla prověřena
            }
        //Nebyly-li prověřeny všechny, je třeba zkusit znovu
        }while( prověřeno < K_PROVĚŘENÍ );
        System.out.println( " - ÚSPĚŠNÝ" );

        Molekula_13a m = new Molekula_13a( x, y );
        return true;
    }



//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Na pozici o zadaných souřadnicích vytvoří molekulu s náhodnou rychlostí
     * a nechá ji zobrazit na aktivním plátně.
     */
    public Molekula_13a(int x, int y)
    {
        super( x, y, PRŮMĚR );
        this.x = x;
        this.y = y;
        this.rx = (rnd.nextDouble() - 0.5) * 2 * maxR / FREKVENCE;
        this.ry = (rnd.nextDouble() - 0.5) * 2 * maxR / FREKVENCE;
        molekuly.add( this );      //Přidej molekulu do množiny vygenerovaných
        AP.přidej( this );         //a nech ji zobrazit na aktivní plátno
    }



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== PŘEKRYTÉ METODY IMPLEMENTOVANÝCH ROZHRANÍ =================================
//== PŘEKRYTÉ ABSTRAKTNÍ METODY RODIČOVSKÉ TŘÍDY ===============================
//== PŘEKRYTÉ KONKRÉTNÍ METODY RODIČOVSKÉ TŘÍDY ================================
//== NOVĚ ZAVEDENÉ METODY INSTANCÍ =============================================
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== VNOŘENÉ A VNITŘNÍ TŘÍDY ===================================================
//== TESTY A METODA MAIN =======================================================
}





