package rules;

import static org.nuiton.i18n.I18n._;
import static org.nuiton.i18n.I18n.n_;

import java.io.File;
import java.io.FileReader;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.math.matrix.MapFunction;
import org.nuiton.math.matrix.MatrixFactory;
import org.nuiton.math.matrix.MatrixND;
import org.nuiton.util.FileUtil;

import scripts.ResultName;
import scripts.SiMatrix;
import fr.ifremer.isisfish.datastore.ResultStorage;
import fr.ifremer.isisfish.simulator.ResultManager;
import fr.ifremer.isisfish.entities.EffortDescription;
import fr.ifremer.isisfish.entities.Metier;
import fr.ifremer.isisfish.entities.Population;
import fr.ifremer.isisfish.entities.Strategy;
import fr.ifremer.isisfish.entities.StrategyMonthInfo;
import fr.ifremer.isisfish.rule.AbstractRule;
import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.types.TimeStep;
import fr.ifremer.isisfish.types.Month;
import fr.ifremer.isisfish.util.Doc;
import resultinfos.MatrixGrossValueOfLandingsOtherSpeciesPerStrategyMet;

/**
 * GraviteVPUE1Anchois.java
 * 
 * Created: 26 aout 2008
 * 
 * @author anonymous <anonymous@labs.libre-entreprise.org>
 * @version $Revision: 1.2 $
 * 
 * Last update: $Date: 2008-10-23 08:59:38 $ by : $Author: Stephanie $
 */
public class GraviteVPUE1LangEtGrossValueOtherSpeciesECOMOD extends
        AbstractRule {
    /** to use log facility, just put in your code: log.info("..."); */
    static private Log log = LogFactory
            .getLog(GraviteVPUE1LangEtGrossValueOtherSpeciesECOMOD.class);

    @Doc(value = "do the doc of param coeffOthers0")
    public String param_nomfichier_coeffOthers0 = "Inputs_Langoustine/CoeffOthers_Intercept_Langoustine/CoeffOthersNephrops.csv";
    @Doc(value = "do the doc of param coeffOthers1")
    public String param_nomfichier_coeffOthers1 = "Inputs_Langoustine/CoeffOthers_Intercept_Langoustine/CoeffOthersHake.csv";
    @Doc(value = "do the doc of param coeffOthers2")
    public String param_nomfichier_coeffOthers2 = "Inputs_Langoustine/CoeffOthers_Intercept_Langoustine/CoeffOthersBenthic.csv";
    @Doc(value = "do the doc of param gravite")
    public boolean param_gravite = false;
    // doit etre a vrai si gravite s'applique sinon la methode calcul uniquement les grossvalue otherspecies	

    static final protected String BETA_O = "BetaOthers";
    static final protected String ALPHA_O = "AlphaOthers";

    protected File CoeffOthers0;
    protected File CoeffOthers1;
    protected File CoeffOthers2;

    protected MatrixND matrixCoeffOthers;

    protected List<Metier> metiers;
    // interdit de faire des set sur les strategies de la map, il faut recuperer les strategies de la date courante
    protected Map<String, Strategy> mesStrategies;

    /** stocke la somme des prop initiales [str x month] */
    private MatrixND SommePropInitial = null;
    /**
     * stocke par strat*met, la derniÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Â ÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã‚Â ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬ÃƒÂ¢Ã¢â‚¬Å¾Ã‚Â¢ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€šÃ‚Â ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡Ãƒâ€šÃ‚Â¬ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¾Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Â ÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡Ãƒâ€šÃ‚Â¬ÃƒÆ’Ã¢â‚¬Â¦Ãƒâ€šÃ‚Â¡ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¡ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¯ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Â ÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã‚Â ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬ÃƒÂ¢Ã¢â‚¬Å¾Ã‚Â¢ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¬ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã‚Â¦ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¡ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Â ÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡Ãƒâ€šÃ‚Â¬ÃƒÆ’Ã¢â‚¬Â¦Ãƒâ€šÃ‚Â¡ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¡ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¿ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Â ÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã‚Â ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬ÃƒÂ¢Ã¢â‚¬Å¾Ã‚Â¢ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¬ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã‚Â¦ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¡ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Â ÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡Ãƒâ€šÃ‚Â¬ÃƒÆ’Ã¢â‚¬Â¦Ãƒâ€šÃ‚Â¡ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¡ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â½re attractivite pour chaque mois [str x
     * met x month]
     */

    /** permet de stocker les CPUE nominales [str x met] */
    private MatrixND valuePerUnitOfEffort = null;

    public String[] necessaryResult = {
    // put here all necessary result for this rule
            // example: 
            // ResultName.MATRIX_BIOMASS,
            // ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET,
            ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_STRATEGY_MET,
            //ResultName.MATRIX_EFFORT_PER_STRATEGY_MET,
            ResultName.MATRIX_EFFORT_NOMINAL_PER_STRATEGY_MET, // garder la ,

    };

    public String[] getNecessaryResult() {
        return this.necessaryResult;
    }

    /**
     * Permet d'afficher a l'utilisateur une aide sur la regle.
     * 
     * @return L'aide ou la description de la regle
     */
    public String getDescription() throws Exception {
        return _("calcule les proportion par metier chaque mois en fonction de la VPUE du metier l'annee precedante et les gross Values otherSpecies");
        /*"HYPOTHESES GRAVITE"
        " attention cette regle doit toujours etre mise avant les mesures de gestion"+
        " si pour un metier Effort (metier annee-1,mois) = 0 et propinitiale (metier, mois) !=0 (ie metier potentiellement pratique), alors "+
        on remet propInitiale pour tous les metiers (premiere vue complete pour tous les metiers de  la strategie - graviteVPUE1-, une alternative
        pourrait etre de chercher lapremiere annee avant annee -1 pour laquelle le metier, ayant une propInitiale non nulle , aurait une VPUE (metier,mois) non nulle
        et recuperer la propStr (metier,mois) pour cette annee et on l'affecte annee courante - mois, les autres metiers se partageant la proportion d'effort restante 
        en fonction de leur VPUE  - graviteVPUE2-, une alternative pourrait etre de chercher la premiere annee avant annee -1 pour laquelle tous les metiers, 
         ayant une propInitiale non nulle, auraient eu une propStr non nulle, (surement difficile a trouver) -  - graviteVPUE3- d'autres hypotheses pourraient etre envisagees)
        "*/
        /*Calcul des gross Value Other Species en fonction de l'effort par strategie et par metier a date
        Avant annee 1 (premiere annee d'appliaction de Gravite) - il faut deja faire les calculs des grossValues des autres especes
        A partir de l'annee 1 : Gravite s'applique, il faut donc attendre de connaitre l'allocation de l'effort a date (dependant des gross values species et otherspecies a date - 1)
        pour pouvoir calculer les grossValueOtherSpecies a date

        */
    }

    /**
     * function used to initialise MatrixND to NaN double
     */
    private MapFunction nanFunction = new MapFunction() {
        public double apply(double value) {
            return Double.NaN;
        }
    };

    /**
     * Appele au demarrage de la simulation, cette methode permet d'initialiser
     * des valeurs
     * 
     * @param simulation
     *            La simulation pour lequel on utilise cette regle
     */
    public void init(SimulationContext context) throws Exception {
        TimeStep step = new TimeStep(0);

        List<Strategy> strs = SiMatrix.getSiMatrix(context).getStrategies(step);
        List<Metier> metiers = SiMatrix.getSiMatrix(context).getMetiers(step);
        List<Month> months = Arrays.asList(Month.MONTH);

        SommePropInitial = MatrixFactory.getInstance().create(
                "SommePropInitial", new List[] { strs, months },
                new String[] { "Strategies", "Months" });
        SommePropInitial.map(nanFunction);

        valuePerUnitOfEffort = MatrixFactory.getInstance().create(
                "ValuePerUnitOfEffort", new List[] { strs, metiers },
                new String[] { "Strategies", "Metiers" });
        valuePerUnitOfEffort.map(nanFunction);

        for (Strategy str : strs) {
            List<Metier> strMetiers = SiMatrix.getSiMatrix(context).getMetiers(
                    str, step);
            List<StrategyMonthInfo> infos = str.getStrategyMonthInfo();
            for (StrategyMonthInfo info : infos) {
                double somme = 0;
                for (Metier strMetier : strMetiers) {
                    somme += info.getProportionMetier(strMetier);
                }
                // FIXME soit on somme pour toutes les str le meme metier; donc pas de notion de str.getName dans la cle
                // soit pour une str on somme tous ces metiers (mais ce doit etre 1; donc pas de notion de metier.getName dans la cle
                SommePropInitial.setValue(str, info.getMonth(), somme);
            }
        }

        // load coefficients of relation others file in a matrix
        if (param_nomfichier_coeffOthers0 == null
                || "".equals(param_nomfichier_coeffOthers0)) {
            CoeffOthers0 = FileUtil.getFile(".*.csv",
                    "fichier 0 csv separateur ';'");
            CoeffOthers1 = FileUtil.getFile(".*.csv",
                    "fichier 1 csv separateur ';'");
            CoeffOthers2 = FileUtil.getFile(".*.csv",
                    "fichier 2 csv separateur ';'");
        } else {
            CoeffOthers0 = new File(param_nomfichier_coeffOthers0);
            CoeffOthers1 = new File(param_nomfichier_coeffOthers1);
            CoeffOthers2 = new File(param_nomfichier_coeffOthers2);
        }

        // reccuperation des metiers et strategies
        SiMatrix siMatrix = SiMatrix.getSiMatrix(context);
        List<String> coeffs = Arrays.asList(new String[] { ALPHA_O, BETA_O });

        // creation de mes strategies qui ne contient pas les espagnols
        //mesStrategies = new HashMap<String, Strategy>();
        //for(Strategy str : strs) {
        //	mesStrategies.put(str.getName(), str);
        //}

        MatrixND matCoeffOthers0 = MatrixFactory.getInstance().create(
                "matCoeffOthers0", new List[] { metiers, coeffs },
                new String[] { "Metiers", "Coeff" });
        MatrixND matCoeffOthers1 = MatrixFactory.getInstance().create(
                "matCoeffOthers1", new List[] { metiers, coeffs },
                new String[] { "Metiers", "Coeff" });
        MatrixND matCoeffOthers2 = MatrixFactory.getInstance().create(
                "matCoeffOthers2", new List[] { metiers, coeffs },
                new String[] { "Metiers", "Coeff" });

        matCoeffOthers0.importCSV(new FileReader(CoeffOthers0), new int[] { 0,
                0 });
        matCoeffOthers1.importCSV(new FileReader(CoeffOthers1), new int[] { 0,
                0 });
        matCoeffOthers2.importCSV(new FileReader(CoeffOthers2), new int[] { 0,
                0 });

        // captures non simulees
        matrixCoeffOthers = MatrixFactory.getInstance().create(
                "matrixCoeffOthers", new List[] { strs, metiers, coeffs },
                new String[] { "Strategies", "Metiers", "Coeff" });

        MatrixND matImport = MatrixFactory.getInstance().create(
                new int[] { 14, 2 });
        ;
        for (Strategy str : strs) {
            log.info("str =" + str.getName());
            for (Metier met : metiers) {
                for (String coeff : coeffs) {
                    if ("NephropsLargeLesSables".equals(str.getName())
                            || "NephropsLargeGuilvinec".equals(str.getName())
                            || "NephropsIntermediateLesSables".equals(str
                                    .getName())
                            || "NephropsIntermediateGuilvinec".equals(str
                                    .getName())) {
                        matImport = matCoeffOthers0;
                    } else if ("HakeLargeLesSables".equals(str.getName())
                            || "HakeLargeGuilvinec".equals(str.getName())
                            || "HakeIntermediateLesSables"
                                    .equals(str.getName())
                            || "HakeIntermediateGuilvinec"
                                    .equals(str.getName())) {
                        matImport = matCoeffOthers1;
                    } else if ("BenthicLargeLesSables".equals(str.getName())
                            || "BenthicLargeGuilvinec".equals(str.getName())
                            || "BenthicIntermediateLesSables".equals(str
                                    .getName())
                            || "BenthicIntermediateGuilvinec".equals(str
                                    .getName())) {
                        matImport = matCoeffOthers2;
                    }
                    matrixCoeffOthers.setValue(str, met, coeff, matImport
                            .getValue(met, coeff));
                }// fin de for coeff	
            }// fin de for met
        }//	fin de for strategy
        log.info("matrixCoeffOthers : " + matrixCoeffOthers);

    }

    /**
     * La condition qui doit etre vrai pour faire les actions
     * 
     * @param simulation
     *            La simulation pour lequel on utilise cette regle
     * @return vrai si on souhaite que les actions soit faites
     */
    public boolean condition(SimulationContext context, TimeStep step, Metier metier)
            throws Exception {

        return true; // on y passe a chaque pas de temps 
    }

    /**
     * Si la condition est vrai alors cette action est executee avant le pas de
     * temps de la simulation.
     * 
     * @param simulation
     *            La simulation pour lequel on utilise cette regle
     */
    // Booleen permettant que ne boucler que sur un seul metier dans la preaction :
    boolean first = true;

    public void preAction(SimulationContext context, TimeStep step, Metier metier)
            throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("first = " + first + "step:" + step);
        }
        log.info("first = " + first + " ,on passe dans la preaction ?");
        if (first) { // on passe dans preaction pour la premiere fois

            log.info("Oui, preaction : ");

            List<Strategy> strs = SiMatrix.getSiMatrix(context).getStrategies(
                    step);
            List<Population> populations = SiMatrix.getSiMatrix(context)
                    .getPopulations(step);
            List<Metier> metiers = SiMatrix.getSiMatrix(context).getMetiers(
                    step);
            //ResultStorage resultmanager = context.getSimulationStorage()
              //      .getResultStorage();
              ResultManager resultmanager = context.getResultManager();
            //on commence par creer une instance de resultats de matrice GrossValuesOtherSpecies
            MatrixND GrossValueOtherSpeciesPerStrMet = MatrixFactory
                    .getInstance()
                    .create(
                            //ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_OTHER_SPECIES_PER_STRATEGY_MET,
                            MatrixGrossValueOfLandingsOtherSpeciesPerStrategyMet.NAME,
                            new List[] { strs, metiers },
                            new String[] { n_("Strategies"), n_("Metiers") });
            log.info("GrossValueOtherSpeciesPerStrMet initialisee "
                    + GrossValueOtherSpeciesPerStrMet);

            // si annee>=1 alors on fait le calcul des gravite puis on met a jour les gross value otherspecies
            if ((step.getYear() > 0) & (param_gravite == true)) {
                ////////Initialisation des matrices qui resultent de la simulation////////////////////////////////////////////////////////////
                log.info("calcul de Gravite");
                //Calcul de l effort nominal par strategy met    
                MatrixND EffortNominalPerStrMet = null;
                EffortNominalPerStrMet = resultmanager.getMatrix(step
                        .previousYear(),
                        ResultName.MATRIX_EFFORT_NOMINAL_PER_STRATEGY_MET);
                log.info("EffortNominalPerStrMet calculee "
                        + EffortNominalPerStrMet);

                //on commence par creer une matrice de valeurs (somme sur ttes les especes capturees) par strategie met
                MatrixND GrossValuePerStrMet = null;
                GrossValuePerStrMet = resultmanager
                        .getMatrix(
                                step.previousYear(),
                                ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_STRATEGY_MET)
                        .copy();
                log.info("GrossValuePerStrMet calculee " + GrossValuePerStrMet);

                //ajouter pour tous les metiers les valeurs liees qux autres especes calculees par modele lineaire
                // Boucle sur les strategies de mes strategies
                //List <Strategy> mStr = strs;
                for (Strategy strIndex : strs) {
                    // interdit de faire des set sur les strategies de la semantique de la matrice, il faut recuperer les strategies de la date courante
                    Strategy str = (Strategy) context.getDB().findByTopiaId(
                            strIndex.getTopiaId());

                    StrategyMonthInfo smi = str.getStrategyMonthInfo(step
                            .getMonth());
                    Collection<EffortDescription> strMet = str
                            .getSetOfVessels().getPossibleMetiers();
                    //2) calcul les valeurs non simulees du mois l annee precedante
                    for (EffortDescription effort : strMet) {
                        Metier met = effort.getPossibleMetiers();
                        log.info("Boucle metier 1, metier possible: "
                                + met.getName());
                        double eff = EffortNominalPerStrMet.getValue(str, met);
                        log.info("effort str" + str.getName() + met.getName()
                                + " : " + eff);

                        //GrossValueAutres par strategie 
                        // Hypothese 1 = pas de distinction entre les metiers  n'agira donc pas sur la gravite)
                        // Hypothese 2 = a distinguer selon les metiers - agira sur la gravite 
                        // l'hypothese est le resultat des coef dans la matrice en entree si tous identiques quelque soit le metier dans la strategie alors H1
                        // sinon H2
                        double valMetOther = matrixCoeffOthers.getValue(str,
                                met, ALPHA_O)
                                + matrixCoeffOthers.getValue(str, met, BETA_O)
                                * eff;
                        if (valMetOther < 0) {
                            valMetOther = 0;
                        }
                        double valMet = valMetOther
                                + GrossValuePerStrMet.getValue(str, met);
                        //log.info("valOtherMetAnchois :"+matrixCoeffOthers.getValue(str,met)*eff);						
                        //log.info("GrossValuePerStrMet avant : "+GrossValuePerStrMet.getValue(str,met));
                        GrossValuePerStrMet.setValue(str, met, valMet);
                        log.info("valOtherMetLangoustine : " + valMet);
                        log.info("GrossValuePerStrMet apres : "
                                + GrossValuePerStrMet.getValue(str, met));

                    }
                }

                //////////////////////////////////////////////////////////////////////////////////////////////////////////
                valuePerUnitOfEffort.map(nanFunction); //reinitialisation avant calcul pour date

                for (Strategy str : strs) {
                    log.info("INFO: Boucle creation valuePerUnitEffort : "
                            + str.getName());
                    //log.info("Boucle creation catchperuniteffort : "+ str.getName());	
                    StrategyMonthInfo smi = str.getStrategyMonthInfo(step
                            .getMonth());
                    Collection<EffortDescription> strMet = str
                            .getSetOfVessels().getPossibleMetiers();
                    //SiMatrix.getSiMatrix(context).getMetiers(str, step);

                    // boucle pour tester s'il existe un metier pour lequel effort(metier)=0 et PropInitiale(metier)=0 (Condition)
                    boolean testCondition = false;
                    double somme = 0;//initialisation de la somme des VPUE des metiers de la strategie
                    for (EffortDescription ed : strMet) {
                        Metier strMetier = ed.getPossibleMetiers();
                        log.info("Pour str=" + str.getName() + " et metier="
                                + strMetier.getName());
                        double effort = EffortNominalPerStrMet.getValue(str,
                                strMetier);
                        // on teste effort pour le calcul des VPUE 
                        // si effort != 0 , valeur/effort
                        //sinon (effort =0) , deux cas de figure : 
                        //    1. soit propInitiale =0 pour ce metier et dans ce cas VPUE =0 et ca ne doit pas impacter le calcul de la gravite pour les autres metiers de str
                        //   2. soit propInitiale! =0 et dans ce cas, on mettra PropInitiale pour tous les metiers de str
                        if (effort > 0) {// a peche au mois, annee-1
                            //on recupere la capture tot                   
                            double value = GrossValuePerStrMet.getValue(str,
                                    strMetier);
                            log.info("DEBUG: value : " + value);
                            log.info("DEBUG: effort : " + effort);
                            double vpue = value / effort;
                            valuePerUnitOfEffort.setValue(str, strMetier, vpue);
                            log.info("value/effort= " + vpue);
                            somme += value / effort;
                        } else if ((effort == 0)
                                & (smi.getProportionMetier(strMetier) == 0)) {// n'a jamais peche avec ce metier
                            valuePerUnitOfEffort.setValue(str, strMetier, 0);
                            log.info("n'a jamais peche avec ce metier");
                        } else {// n'a pas peche au mois, annee -1, mais avait une prop d'effort non nul a l'annee=0
                            testCondition = true;// ie somme est incomplete mais pas grave car on mettra PropInitiale a tous les metiers
                            log
                                    .info("n'a pas peche au mois, annee -1, mais avait une prop d'effort non nul a l'annee=0");
                        }
                    }
                    log.info("testCondition pour str" + str.getName() + ":"
                            + testCondition);
                    // a partir des VPUE stockees dans valuePerUnitOfEffort, on calcule la gravite
                    double newProp = 0;
                    log
                            .info("a partir des VPUE stockees dans valuePerUnitOfEffort, on calcule la gravite");
                    if (!testCondition) {
                        double SommeVPUEstrat = somme;
                        log.info("SommeVPUEstrat=" + SommeVPUEstrat);
                        for (EffortDescription ed : strMet) {
                            Metier strMetier = ed.getPossibleMetiers();
                            log.info("PropStrInitiale(metier="
                                    + strMetier.getName() + ")"
                                    + smi.getProportionMetier(strMetier));
                            log
                                    .info("SommePropInitial.getValue(str, step.getMonth()="
                                            + SommePropInitial.getValue(str,
                                                    step.getMonth()));
                            log
                                    .info("valuePerUnitOfEffort.getValue(str, strMetier)"
                                            + valuePerUnitOfEffort.getValue(
                                                    str, strMetier));
                            if (SommeVPUEstrat == 0) {
                                newProp = 0;
                            } else {
                                newProp = SommePropInitial.getValue(str, step
                                        .getMonth())
                                        * valuePerUnitOfEffort.getValue(str,
                                                strMetier) / SommeVPUEstrat;
                            }
                            log.info("newProp(metier=" + strMetier.getName()
                                    + ")" + newProp);
                            smi.setProportionMetier(strMetier, newProp);
                            log.info("PropStrNouvelle(metier="
                                    + strMetier.getName() + ")"
                                    + smi.getProportionMetier(strMetier));
                            // annee>= 1 calcul des gross Value otherSpecies avec les nouvelles valeurs d'effort calculees par gravite 
                            //avec la nouvelle proportion on en deduit la gross Value of Species de date pour ce str-met
                            double valMetOtherSpecies = matrixCoeffOthers
                                    .getValue(str, strMetier, ALPHA_O)
                                    + matrixCoeffOthers.getValue(str,
                                            strMetier, BETA_O) * newProp;
                            //tester si valMetOtherSpecies <= alors mettre a 0
                            if (valMetOtherSpecies < 0) {
                                valMetOtherSpecies = 0;
                            }
                            GrossValueOtherSpeciesPerStrMet.setValue(str,
                                    strMetier, valMetOtherSpecies);
                            log.info("valOtherMetLangoustine : "
                                    + valMetOtherSpecies);
                            log.info("GrossValuePerStrMet apres : "
                                    + GrossValueOtherSpeciesPerStrMet.getValue(
                                            str, strMetier));
                        }
                    }
                    // else  ie on met propInitiale dans PropStr(str,annee,mois)
                    // rien n'a faire car au debut de chaque pas de temps, PropStr est par defaut initialise a la valeur de la base de donnees (val initiales)
                }//fin de boucle sur strategy	
                // resultats grossvalue otherspecies mis dans le resultManager
                resultmanager
                        .addResult(
                                step,
                                //ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_OTHER_SPECIES_PER_STRATEGY_MET,
                                MatrixGrossValueOfLandingsOtherSpeciesPerStrategyMet.NAME,
                                GrossValueOtherSpeciesPerStrMet);

            } else if ((step.getYear() == 0) || (param_gravite == false)) {
                //si annee==0 alors on ne fait que le calcul des gross value other species
                for (Strategy str : strs) {
                    log.info("INFO: Boucle creation valuePerUnitEffort : "
                            + str.getName());
                    //log.info("Boucle creation catchperuniteffort : "+ str.getName());	
                    StrategyMonthInfo smi = str.getStrategyMonthInfo(step
                            .getMonth());
                    Collection<EffortDescription> strMet = str
                            .getSetOfVessels().getPossibleMetiers();
                    for (EffortDescription ed : strMet) {
                        Metier strMetier = ed.getPossibleMetiers();
                        log.info("PropStrInitiale(metier="
                                + strMetier.getName() + ")"
                                + smi.getProportionMetier(strMetier));
                        double valMetOtherSpecies = matrixCoeffOthers.getValue(
                                str, strMetier, ALPHA_O)
                                + matrixCoeffOthers.getValue(str, strMetier,
                                        BETA_O)
                                * smi.getProportionMetier(strMetier);
                        //tester si valMetOtherSpecies <= alors mettre a 0
                        if (valMetOtherSpecies < 0) {
                            valMetOtherSpecies = 0;
                        }
                        GrossValueOtherSpeciesPerStrMet.setValue(str,
                                strMetier, valMetOtherSpecies);
                        log.info("valOtherMetLangoustine : "
                                + valMetOtherSpecies);
                        log.info("GrossValuePerStrMet apres : "
                                + GrossValueOtherSpeciesPerStrMet.getValue(str,
                                        strMetier));
                    }
                }
                // resultats grossvalue otherspecies mis dans le resultManager
                resultmanager
                        .addResult(
                                step,
                                //ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_OTHER_SPECIES_PER_STRATEGY_MET,
                                MatrixGrossValueOfLandingsOtherSpeciesPerStrategyMet.NAME,
                                GrossValueOtherSpeciesPerStrMet);
            } // fin de calcul pour annee ==0
            first = false;

        }// fin de first= true

        if (log.isDebugEnabled()) {
            log.debug("fin Gravite CPUEAction avant");
        }

    }

    /**
     * Si la condition est vrai alors cette action est executee apres le pas de
     * temps de la simulation.
     * 
     * @param simulation
     *            La simulation pour lequel on utilise cette regle
     */
    public void postAction(SimulationContext context, TimeStep step, Metier metier)
            throws Exception {
        first = true;

    }

}
