@Override
  public void execute() {
    globalTickExecution = Monitor.getInstance().getGlobalTicks();
    // remove the app from the request- queue???
    if (app.getOriginalRequest() != null) {
      RequestGenerator.getInstance().removeRequestFromQueue(app.getOriginalRequest());
    }

    selectedVm.createApp(this.app);
  }
  @Override
  public void init(Resource problemApp) {
    this.setProblemResource(problemApp);
    this.setProblemType(problemApp.getProblemType());
    this.preconditionsOk = false;
    this.curInstance = null;
    this.selectedVm = null;
    this.costs = 0;
    this.app = null;

    this.costs = Configuration.getInstance().getAppInsertIntoVmCosts();

    if (problemApp instanceof App) { // only apps can be inserted
      app = (App) problemApp;
      if (app.getVm() == null) { // only new apps can be inserted
        prediction = 0;
        int curFitFactor = 0;

        for (PhysicalMachine pm : Monitor.getInstance().getPms()) {
          if (pm.isRunning()) {
            for (VirtualMachine vm : pm.getVms()) {
              curFitFactor = calculateFit(app, vm);
              if (curFitFactor > prediction) {
                preconditionsOk = true;
                prediction = curFitFactor;
                this.selectedVm = vm;
              }
            }
          }
        }
      }
    }
  }
  // create an instance in the format of CreateAppInsertIntoVm.arff
  // eval can either be a Instance - MissingValue or the evaluation value
  private Instance createInstance(double eval, VirtualMachine vm) {
    Instance instance = new Instance(64);

    LinkedList<Integer> cpuallhist = vm.getCpuAllocationHistory(10);
    LinkedList<Integer> cpuusehist = vm.getCpuUsageHistory(10);

    LinkedList<Integer> memallhist = vm.getMemoryAllocationHistory(10);
    LinkedList<Integer> memusehist = vm.getMemoryUsageHistory(10);

    LinkedList<Integer> storageallhist = vm.getStorageAllocationHistory(10);
    LinkedList<Integer> storageusehist = vm.getStorageUsageHistory(10);

    // CPU/Memory/Storage - Allocation history before the new vm was created
    for (int i = 0; i < 10; i++) {
      // cpu allocation
      instance.setValue(getKnowledgeBase().attribute(i), clusterValue(cpuallhist.get(i)));
      // cpu usage
      instance.setValue(getKnowledgeBase().attribute(i + 10), clusterValue(cpuusehist.get(i)));

      // memory allocation
      instance.setValue(getKnowledgeBase().attribute(i + 20), clusterValue(memallhist.get(i)));
      // memory usage
      instance.setValue(getKnowledgeBase().attribute(i + 30), clusterValue(memusehist.get(i)));

      // storage allocation
      instance.setValue(getKnowledgeBase().attribute(i + 40), clusterValue(storageallhist.get(i)));
      // storage usage
      instance.setValue(getKnowledgeBase().attribute(i + 50), clusterValue(storageusehist.get(i)));
    }

    // SLAs
    // CPU
    instance.setValue(getKnowledgeBase().attribute(60), clusterValue(app.getCpu()));
    // Memory
    instance.setValue(getKnowledgeBase().attribute(61), clusterValue(app.getMemory()));
    // Storage
    instance.setValue(getKnowledgeBase().attribute(62), clusterValue(app.getStorage()));

    // Evaluation
    instance.setValue(getKnowledgeBase().attribute(63), eval);

    return instance;
  }
  @Override
  public boolean evaluate() {
    if (curInstance == null) {
      curInstance = createInstance(0, selectedVm); // create a Instance with the past values
    }

    if (app.getSuspendedTicks() > 0
        || app.getVm().getSuspendedTicks() > 0
        || app.getVm().getPm().getSuspendedTicks() > 0) {
      return false;
    } else if (waitForEvaluation > 0) {
      waitForEvaluation--;
      return false;
    } else {
      // System.out.println("APP - Running Ticks: " + app.getRunningTicks());
      LinkedList<Integer> cpuusagehist = selectedVm.getPm().getCpuUsageHistory(10);

      LinkedList<Integer> memusagehist = selectedVm.getPm().getMemoryUsageHistory(10);

      LinkedList<Integer> storageusagehist = selectedVm.getPm().getStorageUsageHistory(10);

      double evaluation =
          (255
                  - calculateUsageRatio(cpuusagehist, 85)
                  - calculateUsageRatio(memusagehist, 85)
                  - calculateUsageRatio(storageusagehist, 85))
              / 255;

      // subtract SLA Violations
      evaluation -=
          (app.getCpuSlaErrorcount() + app.getMemorySlaErrorcount() + app.getStorageSlaErrorcount())
              / 10;

      // minimum of 0
      // evaluation = Math.max(0, evaluation);
      Monitor.getInstance().logExecution(app, this, evaluation, this.globalTickExecution);
      curInstance.setValue(getKnowledgeBase().attribute(63), evaluation);
      this.setLocalEvaluation(evaluation);
      getKnowledgeBase().add(curInstance);
    }
    return true;
  }
  // calculate if an App fits to a pm
  // TODO: gst: use WEKA to calc fit factor!!
  private int calculateFit(App app2, VirtualMachine vm) {
    int output = 0;
    if (Action.isOnlyLearning() == false && CreateAppInsertIntoVm.evaluation != null) {
      // is free space available in the VM
      if (app2.getCpu() + vm.getCurrentCpuUsage() < vm.getCurrentCpuAllocation()
          && app2.getMemory() + vm.getCurrentMemoryUsage() < vm.getCurrentMemoryAllocation()
          && app2.getStorage() + vm.getCurrentStorageUsage() < vm.getCurrentCpuAllocation()) {

        Instance instance = createInstance(Instance.missingValue(), vm);
        instance.setDataset(CreateAppInsertIntoVm.getKnowledgeBase());

        try {
          output = (int) (evaluation.evaluateModelOnce(classifier, instance) * 100);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    } else {
      if (app2.getCpu() + vm.getCurrentCpuUsage() < vm.getCurrentCpuAllocation()
          && app2.getMemory() + vm.getCurrentMemoryUsage() < vm.getCurrentMemoryAllocation()
          && app2.getStorage() + vm.getCurrentStorageUsage() < vm.getCurrentCpuAllocation()) {
        output = randomData.nextInt(1, 100);
      }
    }
    return output;
  }