private void processTuple(KeyValPair<MerchantKey, Long> tuple) {
   MerchantKey merchantKey = tuple.getKey();
   MutableDouble lastSma = lastSMAMap.get(tuple.getKey());
   long txValue = tuple.getValue();
   if (lastSma != null && txValue > lastSma.doubleValue()) {
     double lastSmaValue = lastSma.doubleValue();
     double change = txValue - lastSmaValue;
     if (change > threshold) { // generate an alert
       AverageAlertData data = getOutputData(merchantKey, txValue, change, lastSmaValue);
       alerts.add(data);
       // if (userGenerated) {   // if its user generated only the pass it to WebSocket
       if (merchantKey.merchantType == MerchantTransaction.MerchantType.BRICK_AND_MORTAR) {
         avgAlertNotificationPort.emit(
             getOutputData(
                 data,
                 String.format(
                     brickMortarAlertMsg,
                     txValue,
                     change,
                     lastSmaValue,
                     merchantKey.merchantId,
                     merchantKey.terminalId)));
       } else { // its internet based
         avgAlertNotificationPort.emit(
             getOutputData(
                 data,
                 String.format(
                     internetAlertMsg, txValue, change, lastSmaValue, merchantKey.merchantId)));
       }
       // }
     }
   }
 }
 @Override
 public void process(KeyValPair<MerchantKey, Double> tuple) {
   MutableDouble currentSma = currentSMAMap.get(tuple.getKey());
   if (currentSma == null) { // first sma for the given key
     double sma = tuple.getValue();
     currentSMAMap.put(tuple.getKey(), new MutableDouble(sma));
     // lastSMAMap.put(tuple.getKey(), new MutableDouble(sma));
   } else { // move the current SMA value to the last SMA Map
     // lastSMAMap.get(tuple.getKey()).setValue(currentSma.getValue());
     currentSma.setValue(tuple.getValue()); // update the current SMA value
   }
 }
 @Override
 public void process(Map<String, DimensionObject<String>> tuple) {
   for (Map.Entry<String, DimensionObject<String>> e : tuple.entrySet()) {
     Map<String, MutableDouble> obj = dataMap.get(e.getKey());
     DimensionObject<String> eObj = e.getValue();
     if (obj == null) {
       obj = new HashMap<String, MutableDouble>();
       obj.put(eObj.getVal(), new MutableDouble(eObj.getCount()));
       dataMap.put(e.getKey(), obj);
     } else {
       MutableDouble n = obj.get(eObj.getVal());
       if (n == null) {
         obj.put(eObj.getVal(), new MutableDouble(eObj.getCount()));
       } else {
         n.add(eObj.getCount());
       }
     }
   }
 }
  @Override
  public void endWindow() {
    for (AverageAlertData data : alerts) {
      try {
        avgAlertOutputPort.emit(JsonUtils.toJson(data));
      } catch (IOException e) {
        logger.warn("Exception while converting object to JSON", e);
      }
    }

    alerts.clear();

    for (Map.Entry<MerchantKey, MutableDouble> entry : currentSMAMap.entrySet()) {
      MerchantKey key = entry.getKey();
      MutableDouble currentSma = entry.getValue();
      MutableDouble lastSma = lastSMAMap.get(key);
      if (lastSma == null) {
        lastSma = new MutableDouble(currentSma.doubleValue());
        lastSMAMap.put(key, lastSma);
      } else {
        lastSma.setValue(currentSma.getValue());
      }
    }
  }
 @Override
 public void process(String timeBucket, String key, String field, Number value) {
   String finalKey = timeBucket + "|" + key;
   Map<String, Number> m = dataMap.get(finalKey);
   if (value == null) {
     return;
   }
   if (m == null) {
     m = new HashMap<String, Number>();
     m.put(field, new MutableDouble(value));
     dataMap.put(finalKey, m);
   } else {
     Number n = m.get(field);
     if (n == null) {
       m.put(field, new MutableDouble(value));
     } else {
       ((MutableDouble) n).add(value);
     }
   }
 }
  /**
   * Updates the representation of the text form.
   *
   * @param invocations Invocations to display.
   */
  @SuppressWarnings("unchecked")
  private void updateRepresentation(List<InvocationSequenceData> invocations) {
    sourceInvocations = invocations;
    resetDisplayed = false;

    MutableDouble duration = new MutableDouble(0d);
    List<SqlStatementData> sqlList = new ArrayList<>();
    InvocationSequenceDataHelper.collectSqlsInInvocations(invocations, sqlList, duration);
    double totalInvocationsDuration = 0d;
    for (InvocationSequenceData inv : invocations) {
      totalInvocationsDuration += inv.getDuration();
    }
    double percentage = (duration.toDouble() / totalInvocationsDuration) * 100;

    slowest80List.clear();
    int slowest80 = getSlowestSqlCount(duration.toDouble(), sqlList, 0.8d, slowest80List);
    int slowest20 = sqlList.size() - slowest80;
    slowest20List = CollectionUtils.subtract(sqlList, slowest80List);

    totalSql.setText(
        "<form><p><b>" + TOTAL_SQLS + "</b> " + sqlList.size() + "</p></form>", true, false);
    totalDuration.setText(
        "<form><p><b>"
            + TOTAL_DURATION
            + "</b> "
            + NumberFormatter.formatDouble(duration.doubleValue())
            + " ms</p></form>",
        true,
        false);

    String formatedPercentage = NumberFormatter.formatDouble(percentage, 1);
    if (CollectionUtils.isNotEmpty(sqlList)) {
      Color durationInInvocationColor =
          ColorFormatter.getPerformanceColor(
              GREEN_RGB, YELLOW_RGB, RED_RGB, percentage, 20d, 80d, resourceManager);
      percentageOfDuration.setColor("durationInInvocationColor", durationInInvocationColor);
      percentageOfDuration.setText(
          "<form><p><b>"
              + SQLS_DURATION_IN_INVOCATION
              + "</b> <span color=\"durationInInvocationColor\">"
              + formatedPercentage
              + "%</span></p></form>",
          true,
          false);
    } else {
      percentageOfDuration.setText(
          "<form><p><b>"
              + SQLS_DURATION_IN_INVOCATION
              + "</b> "
              + formatedPercentage
              + "%</p></form>",
          true,
          false);
    }

    String slowest80String = getCountAndPercentage(slowest80, sqlList.size());
    String slowest20String = getCountAndPercentage(slowest20, sqlList.size());
    if (CollectionUtils.isNotEmpty(sqlList)) {
      double slowest80Percentage = ((double) slowest80 / sqlList.size()) * 100;
      if (Double.isNaN(slowest80Percentage)) {
        slowest80Percentage = 0;
      }
      Color color8020 =
          ColorFormatter.getPerformanceColor(
              GREEN_RGB, YELLOW_RGB, RED_RGB, slowest80Percentage, 70d, 10d, resourceManager);
      slowestCount.setColor(SLOWEST8020_COLOR, color8020);
      slowestHyperlinkSettings.setForeground(color8020);

      StringBuilder text = new StringBuilder("<b>" + SLOWEST_80_20 + "</b> ");
      if (slowest80 > 0) {
        text.append("<a href=\"" + SLOWEST80_LINK + "\">" + slowest80String + "</a>");
      } else {
        text.append("<span color=\"" + SLOWEST8020_COLOR + "\">" + slowest80String + "</span>");
      }
      text.append(" / ");
      if (slowest20 > 0) {
        text.append("<a href=\"" + SLOWEST20_LINK + "\">" + slowest20String + "</a>");
      } else {
        text.append("<span color=\"" + SLOWEST8020_COLOR + "\">" + slowest20String + "</span>");
      }
      slowestContent = text.toString();
    } else {
      slowestContent = "<b>" + SLOWEST_80_20 + "</b> " + slowest80String + " / " + slowest20String;
    }
    slowestCount.setText("<form><p>" + slowestContent + "</p></form>", true, false);

    main.layout();
  }