@Plugin(
      name = "Add End Artificial Events",
      parameterLabels = {"Log"},
      returnLabels = {"Altered log"},
      returnTypes = {XLog.class},
      userAccessible = true,
      help = "Adds an artificial  end task to every trace in the log file")
  @UITopiaVariant(
      affiliation = "Department of Computer Science University of Pisa",
      author = "R.Guanciale,G.Spagnolo et al.",
      email = "*****@*****.**",
      pack = "PetriNetReplayAnalysis")
  public XLog addEvents(PluginContext context, XLog oldLog) {

    context.getFutureResult(0).setLabel(XConceptExtension.instance().extractName(oldLog));

    context.getProgress().setMinimum(0);
    context.getProgress().setMaximum(oldLog.size());
    context.getProgress().setIndeterminate(false);
    context.getProgress().setValue(0);

    XAttributeMap logattlist = copyAttMap(oldLog.getAttributes());
    XLog newLog = new XLogImpl(logattlist);
    for (int i = 0; i < oldLog.size(); i++) {
      XTrace oldTrace = oldLog.get(i);
      XTrace newTrace = new XTraceImpl(copyAttMap(oldTrace.getAttributes()));
      for (int j = 0; j < oldTrace.size(); j++) {
        XEvent oldEvent = oldTrace.get(j);
        XEvent newEvent = new XEventImpl(copyAttMap(oldEvent.getAttributes()));
        newTrace.add(newEvent);
      }

      Date time = new Date();
      try {
        time =
            ((XAttributeTimestampImpl)
                    oldTrace.get(oldTrace.size() - 1).getAttributes().get("time:timestamp"))
                .getValue();
        time.setTime(time.getTime() + 1);
      } catch (Exception ex) {
      }

      newTrace.add(makeEvent("ArtificialEnd", time));

      newLog.add(newTrace);
      context.getProgress().inc();
    }
    return newLog;
  }
  @PluginVariant(requiredParameterLabels = {0})
  public JComponent visualize(final PluginContext context, final XLog log) {
    JPanel panel = new JPanel(new BorderLayout());
    JLabel lbInfo = new JLabel();
    lbInfo.setText(
        "Log " + log.getAttributes().get("concept:name") + " has " + log.size() + " traces ");

    JTable tbTraces = new JTable(new XTraceTableModel(log));
    panel.add(lbInfo, BorderLayout.NORTH);
    panel.add(new JScrollPane(tbTraces), BorderLayout.CENTER);
    return panel;
  }
  private XLog[] createdXFolds() {

    if (log.size() < fold) fold = log.size();
    XLog[] logs = new XLog[fold];

    for (int i = 0; i < fold; i++) {
      logs[i] = factory.createLog(log.getAttributes());
    }

    if (log.size() == fold) {
      int pos = 0;
      for (XTrace t : log) {
        logs[pos].add(t);
        pos++;
      }
    } else {
      boolean finish = false;
      while (!finish) {
        finish = true;
        for (XTrace t : log) {
          int pos = r.nextInt(fold);
          logs[pos].add(t);
        }
        for (int i = 0; i < logs.length; i++) {
          if (logs[i].size() == 0) {
            finish = false;
          }
        }
        if (!finish) {
          for (int i = 0; i < fold; i++) {
            logs[i].clear();
          }
        }
      }
    }

    return logs;
  }
 @Override
 public int getRowCount() {
   return log.size();
 }
  @PluginVariant(
      requiredParameterLabels = {0, 1, 2, 3},
      variantLabel = "PerformanceDetailsSettingsWithMarking")
  // @Plugin(name = "PerformanceDetailsSettingsWithMarking", returnLabels = { "Performance Total" },
  // returnTypes = { TotalPerformanceResult.class }, parameterLabels = {}, userAccessible = true)
  // @UITopiaVariant(affiliation = "Department of Computer Science University of Pisa", author =
  // "R.Guanciale,G.Spagnolo et al.", email = "*****@*****.**", pack =
  // "PetriNetReplayAnalysis")
  public TotalPerformanceResult getPerformanceDetails(
      PluginContext context,
      XLog log,
      Petrinet net,
      ReplayFitnessSetting setting,
      Marking marking,
      XEventClassifier classif) {

    TotalPerformanceResult performance = new TotalPerformanceResult();

    XEventClasses classes = getEventClasses(log, classif);
    if (map == null) {
      // Map<Transition, XEventClass>
      map = getMapping(classes, net);
    }

    context
        .getConnectionManager()
        .addConnection(new LogPetrinetConnectionImpl(log, classes, net, map));

    PetrinetSemantics semantics = PetrinetSemanticsFactory.regularPetrinetSemantics(Petrinet.class);

    Replayer<ReplayFitnessCost> replayer =
        new Replayer<ReplayFitnessCost>(
            context, net, semantics, map, ReplayFitnessCost.addOperator);

    int replayedTraces = 0;
    context.getProgress().setMinimum(0);
    context.getProgress().setMaximum(log.size());
    for (XTrace trace : log) {
      List<XEventClass> list = getList(trace, classes);
      try {
        System.out.println("Replay :" + replayedTraces);
        List<Transition> sequence;

        sequence = replayer.replayTrace(marking, list, setting);
        if (sequence != null) {
          sequence = sortHiddenTransection(net, sequence, map);
          String tracename = getTraceName(trace);
          updatePerformance(net, marking, sequence, semantics, trace, performance, map, tracename);
          replayedTraces++;
          context.getProgress().inc();
          System.out.println("Replayed");
        }

      } catch (Exception ex) {
        System.out.println("Failed");
        context.log("Replay of trace " + trace + " failed: " + ex.getMessage());
      }
    }

    context.log(
        "(based on a successful replay of "
            + replayedTraces
            + " out of "
            + log.size()
            + " traces)");

    ReplayAnalysisConnection connection = new ReplayAnalysisConnection(performance, log, net);
    context.getConnectionManager().addConnection(connection);

    return performance;
  }