/* * #%L * IsisFish data * %% * Copyright (C) 2006 - 2014 Ifremer, CodeLutin, Yves Reecht * %% * 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 2 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 static org.nuiton.i18n.I18n.n_; import static org.nuiton.i18n.I18n._; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import scripts.ResultName; import scripts.SiMatrix; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.nuiton.math.matrix.*; import fr.ifremer.isisfish.IsisFishDAOHelper; import fr.ifremer.isisfish.simulator.MetierMonitor; import fr.ifremer.isisfish.simulator.SimulationContext; import fr.ifremer.isisfish.types.TimeStep; import fr.ifremer.isisfish.types.Month; import fr.ifremer.isisfish.datastore.RegionStorage; import fr.ifremer.isisfish.entities.*; import fr.ifremer.isisfish.rule.AbstractRule; import fr.ifremer.isisfish.util.Doc; // pour pouvoir afficher une aide contextuelle (BUG#1605) import java.io.*; import java.util.*; import org.apache.commons.collections.*; /** * CantonnementPreSimu.java * * Created: 30 novembre 2006 * * @author anonymous * @version $Revision: 1.2 $ * * Last update: $Date: 2014-03-19 14:12:34 $ * by : $Author: bpoussin $ */ public class ReductionEffortMwZPreSimu extends AbstractRule { /** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory.getLog(CantonnementPreSimu.class); // Paramètre modifiable dans l'interface: @Doc(value="Fichier de zones de réduction d'effort Marxan") public String param_fileEffortMwZ = "" ; protected Map tableNonActivite = new HashMap(); protected boolean affectNonActivite = false; 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_NO_ACTIVITY, }; @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 _("Effort reduction by zone and gear: need for Marxan with Zones formated outputs"); } // Fonction tirée de CantonnementPreSimu: private void reportNonActivite(SimulationContext context, List listestrategies, List metiers, Metier metier, List chomageMonth) { for(Strategy strategy : listestrategies) { SetOfVessels SetOfBateau = strategy.getSetOfVessels(); EffortDescription effort = SetOfBateau.getPossibleMetiers(metier); if (effort != null){ for (Month month : chomageMonth) { StrategyMonthInfo InfoMois = strategy.getStrategyMonthInfo(month); log.info("debut reportNonActivite"); // On regarde si on a déjà une entrée pour le mois courant MatrixND matNonActiviteMois=tableNonActivite.get(month); if (matNonActiviteMois == null){ matNonActiviteMois = MatrixFactory.getInstance().create( ResultName.MATRIX_NO_ACTIVITY, new List[]{listestrategies, metiers}, new String[]{n_("Strategies"), n_("Metiers")}); tableNonActivite.put(month, matNonActiviteMois); } matNonActiviteMois.setValue(strategy, metier, InfoMois.getProportionMetier(metier)); log.info("fin reportNonActivite"); InfoMois.setProportionMetier(metier, 0); MetierMonitor metierMon = context.getMetierMonitor(); metierMon.isLimited(metier, month); metierMon.addforbiddenMetier(metier, month); } } } } /** * Fonction pour ajouter une paire zone-engin a la matrice noActivity * Adaptée de l'init de CantonnementPreSimu. * * @param context: La simulation pour laquelle on utilise cette règle. * @param param_zone: la zone de cantonnement. * @param param_gear: l'engin concerné. */ private void addNoActivity(SimulationContext context, Zone param_zone, Gear param_gear) throws Exception { // Cantonnements valables toute l'année (AMP permanentes): Month param_beginMonth = Month.JANUARY; Month param_endMonth = Month.DECEMBER; SiMatrix siMatrix = SiMatrix.getSiMatrix(context); ZoneDAO zoneDao = IsisFishDAOHelper.getZoneDAO(context.getDB()); MetierSeasonInfoDAO metierSeasonInfoDao = IsisFishDAOHelper.getMetierSeasonInfoDAO(context.getDB()); List SaisonFermee = Month.getMonths(param_beginMonth, param_endMonth); List maillefermee = param_zone.getCell(); FisheryRegion region = RegionStorage.getFisheryRegion(context.getDB()); List listestrategies= region.getStrategy(); List metiers = region.getMetier(); for (Metier metier : metiers) { log.info("metier examiné " + metier.getName()); if (param_gear != null && !metier.getGear().equals(param_gear)){ log.info("l engin du métier n est pas concerné"); } else { log.info("l engin du métier est bien concerné"); List saisons = metier.getMetierSeasonInfo(); for (MetierSeasonInfo saisonmetier: saisons){ int inter = siMatrix.nbCellInter(saisonmetier.getZone(), param_zone); if (inter != 0){ List MailleMetier = siMatrix.getCells(saisonmetier.getZone()); // les mailles qui restent dans la zone metier List newCellMetier = new ArrayList(MailleMetier); newCellMetier.removeAll(maillefermee); List saison=saisonmetier.getMonths(); if (saison.containsAll(SaisonFermee)){ log.info("il y a bien intersection entre la zone métier et le cantonnement pour la saison "+saison.toString()); // calcule de la zone restante: boolean ToutFerme=false; boolean DebInclus=saison.contains(param_beginMonth); boolean FinInclus=saison.contains(param_endMonth); //creation du nouveau secteur de metier Zone secteurResult = zoneDao.create(); secteurResult.setName("MetaCantonnement-" + metier.getName() + "-" + saison.toString()); secteurResult.setComment("Secteur créé durant la simulation."); // on ajoute les mailles restants de la zone metier dans la zone resultante secteurResult.addAllCell(newCellMetier); // test pour savoir si toute la zone de pratique du metier // (reunion de toutes les zones metiers de metier a date) // est totalement incluse dans la zone Cantonnement if (newCellMetier.size() != 0){ //le cas intersection.length==mailleMetier est dans condition // si toute la zone de pratique du metier n'est pas incluse dans zone Cantonnement ToutFerme=false; } else { log.info("Toute la zone metier est ferme"); ToutFerme=true; } // 1er cas: la saison métier est identique (ou totalement incluse dans la saison fermée, dans ce cas là, on change juste // le secteur if (SaisonFermee.containsAll(saison)){ log.info("toute la saison metier est incluse dans la saison de fermeture"); //si tout est fermé, on met le metier au chômage if (ToutFerme==true) { log.info ("toute la zone est fermée, le metier passe donc à chômage pour cette saison"); reportNonActivite(context, listestrategies, metiers, metier, saison); } else { log.info("tout n'est pas fermée, le secteur de pêche devient " + secteurResult); for (Month month : SaisonFermee){ metier.getMetierSeasonInfo(month).clearZone(); metier.getMetierSeasonInfo(month).addZone(secteurResult); } } } // 2ème cas de figure: moisDeb est inclus mais pas moisFin (ou alors c'est le dernier mois) else if (DebInclus && ((!FinInclus) || param_endMonth.equals(saison.get(saison.size()-1)))) { log.info ("il y a intersection de la saison de fermeture avec la saison métier de " + param_beginMonth + " à " + saison.get(saison.size()-1)); //si tout est fermé on met les proportions à 0 pour les mois fermes if (ToutFerme==true){ log.info ("toute la zone métier est fermée"); List chomageMonth = new ArrayList(SaisonFermee); chomageMonth.retainAll(saison); log.info ("de "+chomageMonth.get(0)+" a "+ chomageMonth.get(chomageMonth.size()-1)+ ", le metier est donc mis au chomage"); reportNonActivite(context, listestrategies, metiers, metier, chomageMonth); } else { //on commence par crée les nouvelles saisons saisonmetier.setLastMonth(param_beginMonth.previous()); //on crée un nouveau infoSaisonMetier MetierSeasonInfo NouvelInfoSaison= metierSeasonInfoDao.create(); NouvelInfoSaison.setMetier(metier); NouvelInfoSaison.setFirstMonth(param_beginMonth); NouvelInfoSaison.setLastMonth(saison.get(saison.size()-1)); NouvelInfoSaison.addZone(secteurResult); NouvelInfoSaison.setComment("saison crée pendant la simulation") ; metier.addMetierSeasonInfo(NouvelInfoSaison); log.info ("de "+saison.get(0)+" à "+param_beginMonth.previous()+" le metier peche en "+saisonmetier.getZone()); log.info ("de "+param_beginMonth+" à "+saison.get(saison.size()-1)+" le metier peche en "+secteurResult); } } // 3ème cas de figure: moisFin est inclus mais pas moisDeb (ou alors il est égal au premier mois) else if (((!DebInclus) || param_beginMonth.equals(saison.get(0))) && FinInclus) { log.info ("il y a intersection de la saison de fermeture avec la saison métier de "+param_beginMonth+" à "+saison.get(saison.size()-1)); //si tout est fermé on met les proportions à 0 pour les mois fermes if (ToutFerme==true){ log.info ("toute la zone est fermee"); List chomageMonth = new ArrayList(SaisonFermee); chomageMonth.retainAll(saison); reportNonActivite(context, listestrategies, metiers, metier, chomageMonth); } else { //on commence par crée les nouvelles saisons saisonmetier.setFirstMonth(param_endMonth.next()); //on crée un nouveau infoSaisonMetier MetierSeasonInfo NouvelInfoSaison= metierSeasonInfoDao.create(); NouvelInfoSaison.setMetier(metier); NouvelInfoSaison.setFirstMonth(saison.get(0)); NouvelInfoSaison.setLastMonth(param_endMonth); NouvelInfoSaison.addZone(secteurResult); NouvelInfoSaison.setComment("saison crée pendant la simulation") ; metier.addMetierSeasonInfo(NouvelInfoSaison); log.info ("de "+saison.get(0)+" à "+param_endMonth+" le metier peche en "+secteurResult); log.info ("de "+param_endMonth.next()+" à "+saison.get(saison.size()-1)+" le metier peche en "+saisonmetier.getZone()); } } // dernier cas de figure: les deux sont inclus et sont différents des bornes else { //si tout est fermé on met les proportions à 0 pour les mois fermes if (ToutFerme==true){ log.info("toute la zone métier est fermée"); reportNonActivite(context, listestrategies, metiers, metier, SaisonFermee); } else { //on commence par crée les nouvelles saisons // saisonmetier.setFirstMonth(param_beginMonth.previous()); //on crée un nouveau infoSaisonMetier MetierSeasonInfo NouvelInfoSaison = metierSeasonInfoDao.create(); NouvelInfoSaison.setMetier(metier); NouvelInfoSaison.setFirstMonth(param_beginMonth); NouvelInfoSaison.setLastMonth(param_endMonth); NouvelInfoSaison.addZone(secteurResult); NouvelInfoSaison.setComment("saison crée pendant la simulation") ; metier.addMetierSeasonInfo(NouvelInfoSaison); //on crée un nouveau infoSaisonMetier MetierSeasonInfo NouvelInfoSaison2 = metierSeasonInfoDao.create(); NouvelInfoSaison2.setMetier(metier); NouvelInfoSaison2.setFirstMonth(param_endMonth.next()); NouvelInfoSaison2.setLastMonth(saison.get(saison.size()-1)); NouvelInfoSaison2.setZone(saisonmetier.getZone()); NouvelInfoSaison2.setComment("saison crée pendant la simulation") ; metier.addMetierSeasonInfo(NouvelInfoSaison2); log.info ("de "+saison.get(0)+" à "+param_beginMonth.previous()+" le metier peche en "+saisonmetier.getZone()); log.info ("de "+param_beginMonth+" à "+param_endMonth+" le metier peche en "+secteurResult); log.info ("de "+param_endMonth.next()+" à "+saison.get(saison.size()-1)+" le metier peche en "+saisonmetier.getZone()); } } } } } } } } /** * Appelé au démarrage de la simulation, cette méthode permet d'initialiser * des valeurs * @param context La simulation pour lequel on utilise cette regle */ @Override public void init(SimulationContext context) throws Exception { // chargement du fichier BufferedReader fReader = new BufferedReader(new FileReader(new File(param_fileEffortMwZ))); // BufferedReader fReader = new BufferedReader(new FileReader(new File("Y:/PANACHE/Analyses/5_Analyse_MwZ_outputs/effortRedISIS_3.csv"))); String line; // lecture du fichier, ligne par ligne do { // lecture de la ligne: line = fReader.readLine(); if (line != null){ // Découpe des colonnes String[] columns = line.split(";"); String nomEngin = columns[0]; String reductionEffort = columns[1]; String cellules = columns[2]; // Découpe des cellules String[] nomCellules = cellules.split(","); // Récuperation des objets de manipulation des zones, des cellules et des engins: ZoneDAO zoneDao = IsisFishDAOHelper.getZoneDAO(context.getDB()); CellDAO cellDao = IsisFishDAOHelper.getCellDAO(context.getDB()); GearDAO gearDao = IsisFishDAOHelper.getGearDAO(context.getDB()); // Récuperation de l'engin concerné d'après son nom: Gear engin = gearDao.findByName(nomEngin); // Création de la zone de réduction d'effort String nom = "ZoneEffortReduction-" + nomEngin + "-" + reductionEffort; Zone zone = zoneDao.newInstance(); zone.setName(nom); zoneDao.create(zone); // Ajout des cellules dans la nouvelle zone: for (String cellule : nomCellules) { Cell cell = cellDao.findByName(cellule); zone.addCell(cell); } // Transformation de la proportion de réduction d'effort en double: Double propEffortReduction = Double.parseDouble(reductionEffort); // Sauvegarde de la proportion de réduction d'effort. // Si ==1.0, la zone est ajouté à la matrice noActivity pour les métiers utilisant l'engin concerné. if (propEffortReduction < 1.0) { // Sauvegarde dans le context de la proportion de la zone: context.setValue("Proportion-" + nom, propEffortReduction); }else{ addNoActivity(context, zone, engin); // Ce qui suit est en principe inutile (puisque zone en NoActivity pour les métiers utilisant l'engin) // ...À commenter pour vérifier que le cantonnement fonctionne : // context.setValue("Proportion-" + nom, propEffortReduction); } // sauvegarde dans le context des zones de réduction d'effort pour l'engin List enginZones = (List)context.getValue("ZoneReduction-" + nomEngin); if (enginZones == null) { enginZones = new ArrayList(); } enginZones.add(zone); context.setValue("ZoneReduction-" + nomEngin, enginZones); } } while (line != null); } /** * La condition qui doit être 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 concerné * @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; MatrixND mat = tableNonActivite.get(step.getMonth()); if (mat != null && affectNonActivite == false) { result = true; } return result; // fin } /** * 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 concerné */ @Override public void preAction(SimulationContext context, TimeStep step, Metier metier) throws Exception { // on ne doit le faire qu'une seul fois quelque soit le nombre de metier affectNonActivite=true; MatrixND mat = tableNonActivite.get(step.getMonth()); MetierMonitor metierMon = context.getMetierMonitor(); MatrixND noActivity = metierMon.getNoActivity(step); if (noActivity == null){ metierMon.setNoActivity(step, mat.copy()); } else{ noActivity = noActivity.add(mat); } } /** * Si la condition est vrai alors cette action est executée 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 concerné */ @Override public void postAction(SimulationContext context, TimeStep step, Metier metier) throws Exception { affectNonActivite = false; } }