/* * #%L * IsisFish data * %% * Copyright (C) 2006 - 2014 Ifremer, CodeLutin, * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ package rules; import fr.ifremer.isisfish.annotations.Doc; import fr.ifremer.isisfish.datastore.ResultStorage; import fr.ifremer.isisfish.entities.*; import fr.ifremer.isisfish.rule.AbstractRule; import fr.ifremer.isisfish.simulator.PopulationMonitor; import fr.ifremer.isisfish.simulator.MetierMonitor; import fr.ifremer.isisfish.simulator.ResultManager; import fr.ifremer.isisfish.simulator.SimulationContext; import fr.ifremer.isisfish.types.Month; import fr.ifremer.isisfish.types.TimeStep; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.math.matrix.MatrixFactory; import org.nuiton.math.matrix.MatrixIterator; import org.nuiton.math.matrix.MatrixND; import resultinfos.*; import scripts.SiMatrix; import java.util.*; /** * Cette regles tient compte de la taille minimum des poissons capturable. * * Created: 30 novembre 2006 * * @author sl * @version $Revision: 1.1 $ * from TACseries_Metier_OptionLO_postAction.java * Last update: $Date: 2024-09-27 $ by : $Author: bpoussin $ * * from MCLnetters_EWG2511.java and TACpoidsPop.java * MCL for a population by country and by gear * Gear and country are supposed to be mentioned in metier name * Reaction when a is forbidden : * l'effort est reporte sur un metier de la meme strategie, * n'ayant pas l'espece comme capture principale et meme engin * sinon metier de substitution = sans condition sur les engins et prop !=0 * sinon on cherche des metiers non vises avec prop !=0 */ public class MCL_GearCountry_GEMMBE extends AbstractRule { /** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory.getLog(MCL_GearCountry_GEMMBE.class); @Doc(value = "Begin step") public TimeStep param_beginStep = new TimeStep(12); @Doc(value = "End date") public TimeStep param_endStep = new TimeStep(193); @Doc(value = "Affected population") public Population param_pop = null; @Doc(value = "Affected Gears; (string patterns in metier name)") public String param_pattern_1 = "filet"; @Doc(value = "Affected Country; (string patterns in metier name)") public String param_pattern_2 = "ES"; //15/04/2026 : FR n'est pas dans tous les noms de metier francais ie TAC filet FR="filet" "ES", TAC chalut FR="OT" "es", TAC chalut ES = "OT""fr",TAC filet ES "GNS""FRA" // A changer des que fr est dans le nom des metiers fr des moins de 12m - changer les patterns et enlever le ! ligne 161 @Doc(value = "TAC allocation (as a ratio)") public double param_alloc = 1; @Doc(value = "If 0, TAC is computed elsewhere, tacName must be filled to retrieve value, otherwise enter TAC in kg time series, one value per year of simulations, separated by ; for ISIS fleets") public String param_tacInKgs = "3000;6000;;"; @Doc(value = "If tacInKgs = 0, TAC is computed elsewhere and stored in simulation context into this name") public String param_tacName = ""; @Doc(value = "Proportion survival of discards") public double param_propSurvie = 0; @Doc(value = "Landings Obligation Implemented ?") public boolean param_LandingsObligation = true; // public boolean param_DeMinimis = false; protected boolean affectation = false; int nbY = param_endStep.getYear() - param_beginStep.getYear()+1 ; protected double [] tacSeries = new double[nbY]; List listMetNames; List listMet = new ArrayList(); protected MatrixND TacPopMatrix; protected String[] necessaryResult = { // put here all necessary result for this rule MatrixCatchPerStrategyMetPerZonePop.NAME, MatrixLandingPerMet.NAME, MatrixLandingWeight.NAME, MatrixTacPerPop.NAME, MatrixDiscardsPerStrMetPerZonePop.NAME // ResultName.MATRIX_BIOMASS, // ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET, }; @Override 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 */ @Override public String getDescription() throws Exception { return "Implement Quota for the selected metiers using provided annual values. If TAc = 0, uses values from the simulationContext. Saves month when fishing stops in a matrix."; } /** * Appele au demarrage de la simulation, cette methode permet * d'initialiser des valeurs de la * * @param context La simulation pour laquelle on utilise cette regle */ @Override public void init(SimulationContext context) throws Exception { SiMatrix siMatrix = SiMatrix.getSiMatrix(context); TimeStep date = new TimeStep(0); // Add TAC values to a vector indexed by TAC year (from TAC starting year on) String[] StrTacSeries = param_tacInKgs.split(";"); for ( int i = 0 ; i < StrTacSeries.length; i++) { tacSeries[i] = Double.parseDouble(StrTacSeries[i]); } // Add metier names to a list //String[] StrMetNames = param_metNames.split(";"); // filets espagnols String[] GearsInMetNames = param_pattern_1.split(";"); String[] CountryInMetNames = param_pattern_2.split(";"); // list of metiers containing both patterns in metier name List listAllMets = context.getMetierDAO().findAll(); listMet = new ArrayList(); listMetNames = new ArrayList(); for (Metier met : listAllMets) { if (met.getName().contains(param_pattern_1) && !(met.getName().contains(param_pattern_2)) ) { listMet.add(met); listMetNames.add(met.getName()); System.out.println("Affected Metier : " + met.getName()); } } if(!listMet.isEmpty()) { System.out.println("List of affected Metiers : " + listMetNames); } if(listMet.isEmpty()) { System.out.println("liste des metiers affectee VIDE"); } } /** * @param context * @param date * @param param_species * @param metier * @return */ private boolean isCaptureDate(TimeStep step, Species species, Metier metier) { MetierSeasonInfo info = metier.getMetierSeasonInfo(step.getMonth()); TargetSpecies target = info.getSpeciesTargetSpecies(species); boolean result; if (target != null) { result = true; } else { result = false; } return result; } /** * La condition qui doit etre vrai pour faire les actions. * * @param context la simulation pour lequel on utilise cette regle * @param step le pas de temps courant * @param metier le metier concerne * @return vrai si on souhaite que les actions soit faites */ @Override public boolean condition(SimulationContext context, TimeStep step, Metier metier) throws Exception { boolean result = false; if(listMetNames.contains(metier.getName())){ if (step.before(param_beginStep)) { result = false; } else if (step.after(param_endStep)) { result = false; }else {result = true;} } return result; } /** * Si la condition est vrai alors cette action est executee avant le pas de * temps de la simulation. * * @param context la simulation pour lequel on utilise cette regle * @param step le pas de temps courant * @param metier le metier concerne */ @Override public void preAction(SimulationContext context, TimeStep step, Metier metier) throws Exception { log.info ("enters preact for metier "+metier.getName()); // flag metiers and set price to 0 // metier flag = 0 si pas concern par le TAC ou tac pas atteint // metier flag = 1 si TAC atteint et rejet // metier flag = 2 si TAC atteint et interdit if(context.getValue(metier.getName()+param_pop.getName()+"flag") != null && (int) context.getValue(metier.getName()+param_pop.getName()+"flag") == 2){ // context.getMetierMonitor().addforbiddenMetier(metier); log.info("added to forbidden met" + metier.getName()); //recupere toutes les strategies pratiquant le metier et pour lesquelles la proportion !=0 SiMatrix siMatrix = SiMatrix.getSiMatrix(context); Set strs = new HashSet<>(); for (Strategy str : siMatrix.getStrategies(step)) { double prop = str.getStrategyMonthInfo(step.getMonth()) .getProportionMetier(metier); if (prop != 0) { strs.add(str); } } // Pour ces strategies l'effort du metier est mis a 0; pas de reallocation // NB : pourquoi 2 boubles str ? for (Strategy str : strs) { StrategyMonthInfo smi = str.getStrategyMonthInfo(step .getMonth()); // 1er cas de figure: l'effort est reporte sur un metier de la // meme strategie, n'ayant pas l'espece comme capture principale // et pechant avec le meme engin Set possibleMetierCase1 = new HashSet<>(); // 2eme cas de figure: on cherche un metier de substitution // sans condition sur les engins, mais qui soit pratique Set possibleMetierCase2 = new HashSet<>(); // 3 eme cas de figure: on cherche des metiers non vises, // sans consideration sur les engins, et pour lesquels la // proportion peut etre nulle Set possibleMetierCase3 = new HashSet<>(); for (EffortDescription effort : str.getSetOfVessels() .getPossibleMetiers()) { Metier newMetier = effort.getPossibleMetiers(); if ( /*!aimedMetiers.contains(newMetier) &&*/!metier.getName().equalsIgnoreCase("nonActiviy") && !metier.getName().equalsIgnoreCase("nonActivie") && !metier.getName().equalsIgnoreCase( "non Activite") && !context.getMetierMonitor().getForbiddenMetier() .contains(newMetier)) { possibleMetierCase3.add(newMetier); if (smi.getProportionMetier(newMetier) != 0) { possibleMetierCase2.add(newMetier); if (metier.getGear().equals(newMetier.getGear())) { possibleMetierCase1.add(newMetier); } } } } Set possibleMetier = null; if (possibleMetierCase1.size() != 0) { log.info("[TAC] Use case 1"); possibleMetier = possibleMetierCase1; } else if (possibleMetierCase2.size() != 0) { log.info("[TAC] Use case 2"); possibleMetier = possibleMetierCase2; } else if (possibleMetierCase3.size() != 0) { log.info("[TAC] Use case 3"); possibleMetier = possibleMetierCase3; } if (possibleMetier != null) { // on repartit maintenant l'effort entre les differents metiers // possibles dans la meme strategie si un metier possible existe // bien la repartion est proportionnelle a l'effort deja alloue // dans la strategie double somme = 0; for (Metier met : possibleMetier) { somme += smi.getProportionMetier(met); } for (Metier met : possibleMetier) { double newProportion = smi.getProportionMetier(met) + (smi.getProportionMetier(metier) * smi.getProportionMetier(met) / somme); smi.setProportionMetier(met, newProportion); } smi.setProportionMetier(metier, 0); //le metier vise a alors une proportion nulle log.info("[TAC] il y a des metiers possibles"); } else { log.info("[TAC] Use no activity"); // sinon on met tout dans le metier nonActivite MetierMonitor metierMon = context.getMetierMonitor(); MatrixND mat = metierMon.getOrCreateNoActivity(step, MatrixNoActivity.NAME, siMatrix .getStrategies(step), siMatrix .getMetiers(step)); mat.setValue(str, metier, smi.getProportionMetier(metier)); smi.getProportionMetier().setValue(metier, 0); } } } affectation = true; // pour rentrer une fois dans postaction } /** * Si la condition est vrai alors cette action est executee apres le pas * de temps de la simulation. * * @param context La simulation pour lequel on utilise cette regle * @param step le pas de temps courant * @param metier le metier concerne */ @Override public void postAction(SimulationContext context, TimeStep step, Metier metier) throws Exception { if (affectation) { double prevLandings = 0; double catchMonth = 0; double currentCatch = 0; double ratio = 0; PopulationMonitor popMon = context.getPopulationMonitor(); ResultManager resManager = context.getResultManager(); if(context.getValue("TACatteint"+param_pop.getName()+listMetNames)==null || !(Boolean) context.getValue("TACatteint"+param_pop.getName()+listMetNames)){ log.info( "TAC pas encore atteint jusqu ici, test"); // Retrieve TAC value and allocation to the set of metiers double TAC = 0; int year = step.getYear(); int tacYear = year - param_beginStep.getYear(); if (tacSeries[tacYear] != 0){ TAC = tacSeries[tacYear];} TAC = TAC * param_alloc; log.info("TAC value" + TAC); double tmp2 = 0; // Compute landings until last step for the set of metiers in listMet ResultStorage matResult = context.getSimulationStorage().getResultStorage(); for (TimeStep dat = new TimeStep(0); dat.before(step); dat = dat.next()) { MatrixND mattest = matResult.getMatrix(dat, param_pop, MatrixLandingWeight.NAME); log.info( "step " +dat + "mat landings " +mattest ); if( dat.getYear() == year) { MatrixND mat = matResult.getMatrix(dat, param_pop, MatrixLandingWeight.NAME); //double catchListMet = 0; for(Metier met : listMet){ tmp2 = mat.getSubMatrix(1,met).sumAll(); prevLandings += tmp2; log.info( "step " +dat + "landings met" +met +tmp2 ); } } } // Add catch of the current month String TMP = "tmp"; MatrixND mat = popMon.getCatch(param_pop).copy(); SiMatrix siMatrix = SiMatrix.getSiMatrix(context); MatrixND matW = siMatrix.matrixToWeightMatrix(step, 2, TMP, mat); for(Metier met : listMet){ catchMonth += matW.getSubMatrix(1,met).sumAll(); } currentCatch = prevLandings + catchMonth; // compare TAC and landings log.info("[TAC] landings = " + currentCatch+ " >= TAC:" + TAC); if (currentCatch >= TAC) { context.setValue("TACatteint"+param_pop.getName()+listMetNames,true); log.info("tac atteint for " +listMetNames); ratio = (TAC-prevLandings)/catchMonth; // flag metiers and set price to 0 // metier flag = 0 si pas concern par le TAC ou tac pas atteint // metier flag = 1 si TAC atteint et rejet // metier flag = 2 si TAC atteint et interdit if(param_LandingsObligation){ context.setValue("priceSwitch"+param_pop.getName(),1); // strict application for (Metier met : listMet){ log.info("loop metier flag : "+met.getName()); context.setValue(met.getName()+param_pop.getName()+"flag",2); } }else { for (Metier met : listMet){ context.setValue(met.getName()+param_pop.getName()+"flag",1); } } //---------------------------------------------------------------------------------------------------- // Store infos in MatrixTacPerPop // add the month when TAC was reached to Matrix TAC per pop // Store infos in MatrixTacPerPop if(TacPopMatrix == null){ TacPopMatrix = MatrixFactory.getInstance().create( MatrixTacPerPop.NAME, //new List[] { Arrays.asList(new String[]{"TAC0","listMetcatch0","ratio0","TAC1","listMetcatch1","ratio1"})}); new List[] { Arrays.asList(new String[]{"TAC","catchMonth","prevLandings","ratio","Year","TACreachedMonth"})}); } TacPopMatrix.setValue("TAC", TAC); TacPopMatrix.setValue("catchMonth", catchMonth); TacPopMatrix.setValue("prevLandings", prevLandings); TacPopMatrix.setValue("ratio", ratio); TacPopMatrix.setValue("Year", year); TacPopMatrix.setValue("TACreachedMonth", step.getMonth().getMonthNumber()); TacPopMatrix.setName(MatrixTacPerPop.NAME+listMetNames); //matResult.addResult(step, param_pop, TacPopMatrix); matResult.addResult(true,step,param_pop,TacPopMatrix); } } // fin du test de TAC // Le TAC est atteint if(context.getValue("TACatteint"+param_pop.getName()+listMetNames)!=null && (Boolean) context.getValue("TACatteint"+param_pop.getName()+listMetNames)){ // rejet ou reajustement des captures /*MatrixND eff = popMon.getN(param_pop); MatrixND cat = popMon.getCatch(param_pop); MatrixND discard = popMon.getDiscard(step, param_pop); // if the matrix does not exist it is created with the same format as catch if(discard == null){ discard = popMon.getCatch(param_pop).copy().mults(0); discard.setName(MatrixDiscardsPerStrMetPerZonePop.NAME); } for (MatrixIterator i = cat.iteratorNotZero(); i.next();) { Object[] coordonnees = i.getSemanticsCoordinates(); Strategy str = (Strategy) coordonnees[0]; Metier met = (Metier) coordonnees[1]; PopulationGroup group = (PopulationGroup) coordonnees[2]; Zone zone = (Zone)coordonnees[3]; if(listMet.contains(met)){ log.info(met.getName()); if(param_LandingsObligation) { eff.setValue(group, zone,eff.getValue(group, zone)+ i.getValue() * (1-ratio)); i.setValue(i.getValue()*ratio); }else{ //discard, catch not modified discard.setValue(str,met,group,zone,i.getValue()*(1-ratio)); if (param_propSurvie > 0) { eff.setValue(group, zone,eff.getValue(group, zone)+ i.getValue() * (1-ratio) * param_propSurvie); } } } } popMon.holdCatch(param_pop, cat); resManager.addResult(step, param_pop, cat); popMon.addDiscard(step, param_pop, discard);*/ } if(step.getMonth().equals(Month.DECEMBER)){ // reinit priceSwitch at the beginning of each year context.setValue("priceSwitch"+param_pop.getName(),0); context.setValue("TACatteint"+param_pop.getName()+listMetNames,false); for (Metier met : listMet){ context.setValue(met.getName()+param_pop.getName()+"flag",0); log.info("flag?" +context.getValue(met.getName()+param_pop.getName()+"flag")); } } // on a affecte une fois cette meta pop au rejet il ne faut pas le // refaire pour ce pas de temps affectation = false; } } }