Skip to content
Snippets Groups Projects
Select Git revision
  • master default
1 result

existing-simulations.component.ts

Blame
  • existing-simulations.component.ts 15.90 KiB
    import { Component, EventEmitter, OnInit, Output } from "@angular/core";
    import { Simulation } from "../utils/data/simulation";
    import { SimulationService } from "../utils/services/simulation.service";
    import {
      animate,
      state,
      style,
      transition,
      trigger,
      AnimationEvent,
    } from "@angular/animations";
    import { socketStatusAnimation } from "../utils/animations/socket-status.animation";
    import { RxStompService } from "@stomp/ng2-stompjs";
    import {
      NbToastrService,
      NbDateService,
      NbDialogService,
    } from "@nebular/theme";
    import { FormControl } from "@angular/forms";
    import { AbstractControl, FormBuilder, Validators } from "@angular/forms";
    import { Network } from "../utils/data/network";
    import { NetworkService } from "../utils/services/network.service";
    import { SimulationCreationComponent } from "../simulation-creation/simulation-creation.component";
    import { City } from "../utils/data/city";
    
    @Component({
      selector: "ngx-existing-simulations",
      templateUrl: "./existing-simulations.component.html",
      styleUrls: ["./existing-simulations.component.scss"],
      animations: [
        trigger("expansionIndicator", [
          state(
            "expanded",
            style({
              transform: "rotate(180deg)",
            })
          ),
          transition("collapsed => expanded", animate("100ms ease-in")),
          transition("expanded => collapsed", animate("100ms ease-out")),
        ]),
        trigger("accordionItemBody", [
          state(
            "collapsed",
            style({
              overflow: "hidden",
              visibility: "hidden",
              height: 0,
            })
          ),
          state(
            "expanded",
            style({
              overflow: "hidden",
              visibility: "visible",
            })
          ),
          transition("collapsed => expanded", animate("100ms ease-in")),
          transition("expanded => collapsed", animate("100ms ease-out")),
        ]),
        socketStatusAnimation,
      ],
    })
    export class ExistingSimulationsComponent implements OnInit {
      selectedCity: City = undefined;
      simulations: Simulation[] = [];
      compareWithSimulations: Simulation[] = [];
      selectedSimulation: Simulation;
      @Output() selectedSimulationToEmit = new EventEmitter<Simulation>();
      networks: Network[] = [];
      travelDemandModels: Object[] = [
        "Travel Demand Model 1 (hardcoded)",
        "Travel Demand Model 2 (hardcoded)",
      ];
      selectedNetwork: Network = undefined;
      preprocessData: any = {
        status: "",
      };
      generatePopulation: any = {
        status: "",
      };
      generateTravelDemand: any = {
        status: "",
      };
      runSimulation: any = {
        status: "",
      };
      calculateKPIS: any = {
        status: "",
      };
      selectedCompareWithSimulation: Simulation;
      runDss: any = {
        status: "",
      };
      createCalibrationDatasets: any = {
        status: "",
      };
      preprocessDataBtnDisabled: boolean;
      generatePopulationBtnDisabled: boolean;
      datePickerFormControlFrom = new FormControl(new Date(2020, 0, 1));
      datePickerFormControlTo = new FormControl(new Date(2020, 0, 2));
      datePickerDateMin: Date;
      datePickerDateMax: Date;
      datePickerFromDateMax: Date;
      datePickerToDateMin: Date;
      datesValid: boolean = true;
      createCalibrationDatasetsBtnDisabled: boolean;
      runSimulationBtnDisabled: boolean;
      calculateKPISBtnDisabled: boolean;
      runDssBtnDisabled: boolean;
      selectedScenario: number;
      generateTravelDemandForm = this.formBuilder.group({
        travelDemandModelName: ["", Validators.required],
        selectedNetwork: ["", Validators.required],
      });
      dialogRef: any;
    
      constructor(
        private simulationService: SimulationService,
        private rxStompService: RxStompService,
        private toastrService: NbToastrService,
        private formBuilder: FormBuilder,
        private networkService: NetworkService,
        protected dateService: NbDateService<Date>,
        private dialogService: NbDialogService
      ) {
        this.datePickerDateMin = new Date(2020, 0, 1);
        this.datePickerDateMax = this.dateService.addMonth(
          this.dateService.today(),
          1
        );
      }
    
      ngOnInit(): void {
        this.resetButtonsAndStatuses();
        this.calculateKPISBtnDisabled = true;
    
        this.simulationService
          .getSimulationsAll()
          .subscribe((returnedSimulations) => {
            for (let l = 0; l < Object.entries(returnedSimulations).length; l++) {
              let c = Simulation.deserialize(
                Object.entries(returnedSimulations)[l][1]
              );
              this.simulations.push(c);
            }
          });
    
        console.log(
          "rxStompService is probably working but server never sends updated because simulation is not triggered"
        );
    
        this.rxStompService
          .watch("/topic/simulationRunStatus")
          .subscribe((updatedSimulationFrame) => {
            console.log(
              "%cthis content is just copypasted from a similar file",
              "background: sienna; font-weight: bold; color: black; font-family: serif"
            );
    
            let updatedSimulation = JSON.parse(updatedSimulationFrame.body);
            let index = this.simulations.findIndex(
              (simulation) => simulation.id == updatedSimulation.id
            );
            if (index == -1) {
              this.simulations.push(Simulation.deserialize(updatedSimulation));
            } else {
              this.simulations[index] = Simulation.deserialize(updatedSimulation);
              this.simulations[index].statusWSMessage =
                updatedSimulationFrame.headers.statusWSMessage;
              this.simulations[index].animationState =
                this.simulations[index].animationState == "hidden"
                  ? "show"
                  : "replaceHide";
            }
          });
    
        this.networkService.getNetworks().subscribe((res) => {
          this.networks = res;
        });
    
        this.datePickerFormControlFrom.valueChanges.subscribe((x) => {
          this.datePickerToDateMin = this.dateService.addDay(x, 1);
          this.evaluateDatesValid();
        });
    
        this.datePickerFormControlTo.valueChanges.subscribe((x) => {
          this.datePickerFromDateMax = this.dateService.addDay(x, -1);
          this.evaluateDatesValid();
        });
      }
    
      evaluateDatesValid() {
        if (
          this.datePickerFormControlFrom.value < this.datePickerFormControlTo.value
        ) {
          this.datesValid = true;
        } else {
          this.datesValid = false;
        }
      }
    
      onSelect(simulation) {
        this.selectedCity = simulation.city;
        this.selectedSimulation = simulation;
        this.selectedSimulationToEmit.emit(simulation);
        this.compareWithSimulations = [];
        this.calculateKPISBtnDisabled = false;
    
        this.simulations.forEach((sim) => {
          if (simulation.city.cityId == sim.city["cityId"]) {
            if (simulation.id != sim.id) {
              this.compareWithSimulations.push(sim);
            }
          }
        });
      }
    
      onPreprocessData() {
        this.preprocessDataBtnDisabled = true;
        this.preprocessData.status = "running";
        this.generatePopulation.status = "created";
        this.generateTravelDemand.status = "created";
        this.simulationService
          .getPreprocessData(this.selectedCity.cityId)
          .subscribe(
            (res) => {
              this.generatePopulationBtnDisabled = false;
              this.preprocessData.status = "success";
            },
            (error) => {
              console.log("🚀☢ ~ error", error);
              this.showToast(
                `${error["message"]}`,
                `${error["error"]["error"]}`,
                "danger"
              );
              this.preprocessData.status = "error";
            }
          );
      }
    
      onGeneratePopulation() {
        this.generatePopulationBtnDisabled = true;
        this.generatePopulation.status = "running";
        this.showToast("This should take about 20 seconds", "Info", "info");
        this.simulationService
          .getGeneratePopulation(this.selectedCity.cityId)
          .subscribe(
            (res) => {
              this.generatePopulation.status = "";
            },
            (error) => {
              console.log("🚀☢ ~ error", error);
              this.showToast(
                `${error["message"]}`,
                `${error["error"]["error"]}`,
                "danger"
              );
              this.generatePopulation.status = "error";
            }
          );
      }
    
      onGenerateTravelDemand() {
        this.generateTravelDemand.status = "running";
        this.showToast("This should take about 10 seconds", "Info", "info");
    
        this.simulationService
          .postTravelDemand(
            this.selectedCity.cityId,
            this.generateTravelDemandForm.value.travelDemandModelName,
            this.generateTravelDemandForm.value.selectedNetwork.id,
            this.selectedSimulation.id
          )
          .subscribe(
            (res) => {
              this.generateTravelDemand.status = "";
            },
            (error) => {
              console.log("🚀☢ ~ error", error);
              this.showToast(
                `${error["message"]}`,
                `${error["error"]["error"]}`,
                "danger"
              );
              this.generateTravelDemand.status = "error";
            }
          )
          .add(() => {
            this.preprocessDataBtnDisabled = false;
          });
      }
    
      onCreateCalibrationDatasets() {
        this.createCalibrationDatasetsBtnDisabled = true;
        this.createCalibrationDatasets.status = "running";
        this.showToast(
          "this should take about 45 seconds for one day duration and about 8 additional seconds for every additional day",
          "Info",
          "info"
        );
        let startTime, endTime;
        startTime = new Date();
    
        this.simulationService
          .getNetworkFromSimulation(this.selectedSimulation.id)
          .subscribe((res) => {
            this.simulationService
              .postCalibrationPreprocess(
                this.datePickerFormControlFrom.value,
                this.datePickerFormControlTo.value,
                res.id
              )
              .subscribe(
                (res) => {
                  endTime = new Date();
                  let timeDiff = endTime - startTime;
                  timeDiff /= 1000;
                  this.showToast(
                    `add/finally statement - postCalibrationPreprocess is over.
                    It took ${timeDiff} seconds to complete.`,
                    "Success",
                    "success"
                  );
                  this.createCalibrationDatasets.status = "";
                },
                (error) => {
                  console.log("🚀☢ ~ error", error);
                  this.showToast(
                    `${error["message"]}`,
                    `${error["error"]["error"]}`,
                    "danger"
                  );
                  this.createCalibrationDatasets.status = "error";
                }
              )
              .add(() => {
                this.createCalibrationDatasetsBtnDisabled = false;
              });
          });
      }
    
      onRunSimulation() {
        this.runSimulationBtnDisabled = true;
        this.runSimulation.status = "running";
        this.showToast("This may take a while ...", "Info", "info");
        this.simulationService
          .runSimulation(this.selectedSimulation)
          .subscribe(
            (res) => {
              console.log("currently doing nothing with result");
            },
            (error) => {
              this.showToast(
                `${error["message"]}`,
                `${error["error"]["error"]}`,
                "danger"
              );
              this.runSimulation.status = "error";
            }
          )
          .add(() => {
            this.runSimulationBtnDisabled = false;
          });
      }
    
      onCalculateKPIS() {
        this.calculateKPISBtnDisabled = true;
        this.calculateKPIS.status = "running";
        this.showToast(
          "this should take a few minutes to complete.",
          "Info",
          "info"
        );
        let startTime, endTime;
        startTime = new Date();
        this.simulationService
          .getCalculateKPIs(this.selectedCity.cityId, this.selectedSimulation.id)
          .subscribe(
            (res) => {
              this.calculateKPIS.status = "";
              endTime = new Date();
              let timeDiff = endTime - startTime;
              timeDiff /= 1000;
              this.showToast(
                `onCalculateKPIS is over.
                    It took ${timeDiff} seconds to complete.`,
                "Success",
                "success"
              );
            },
            (error) => {
              console.log("🚀☢ ~ error", error);
              this.calculateKPIS.status = "error";
              this.showToast(
                `${error["message"]}. If simulations do not exist this button cannot get any data. Use run simulation first.`,
                `${error["name"]}`,
                "danger",
                10000
              );
            }
          )
          .add(() => {
            this.calculateKPISBtnDisabled = false;
          });
      }
    
      onRunDss() {
        this.runDssBtnDisabled = true;
        this.runDss.status = "running";
        this.simulationService
          .postRunDss(
            [this.selectedSimulation.id, this.selectedCompareWithSimulation.id],
            this.selectedCity.cityId
          )
          .subscribe(
            (res) => {
              this.showToast(
                `onRunDss is over. Deselect the simulation and select it again to have newly generated file loaded.`,
                "Success",
                "success"
              );
              this.runDss.status = "";
    
              // rudimentary way of convincing our-spider-chart to redownload evaluated json
              this.selectedSimulationToEmit.emit(undefined);
              setTimeout(() => {
                this.selectedSimulationToEmit.emit(this.selectedSimulation);
                this.showToast(`Updating spider chart.`, "Info", "info");
              }, 0);
            },
            (error) => {
              this.runDss.status = "error";
              this.showToast(`Working, please wait`, `Info`, "info");
            }
          )
          .add(() => {
            this.runDssBtnDisabled = false;
          });
      }
    
      onReset() {
        this.selectedSimulation = undefined;
        this.generateTravelDemandForm.reset();
    
        if (!this.generatePopulationBtnDisabled) {
          this.showToast(
            "Looks like we're in the middle of creating data for Preprocess Data, Generate Population and Generate Travel Demand. Data might be polluted and might need to be recreated.",
            "Warning",
            "warning"
          );
          setTimeout(() => {
            this.preprocessData.status = "error";
            this.generatePopulation.status = "error";
            this.generateTravelDemand.status = "error";
          }, 250);
        }
    
        this.resetButtonsAndStatuses();
      }
    
      resetButtonsAndStatuses() {
        this.preprocessData.status = "";
        this.generatePopulation.status = "";
        this.generateTravelDemand.status = "";
        this.createCalibrationDatasets.status = "";
        this.runSimulation.status = "";
        this.calculateKPIS.status = "";
        this.runDss.status = "";
        this.preprocessDataBtnDisabled = false;
        this.generatePopulationBtnDisabled = true;
        this.calculateKPISBtnDisabled = false;
        this.runDssBtnDisabled = false;
      }
    
      showToast(msg: string, title: string, status: string, duration?: number) {
        this.toastrService.show(msg, title, { status: status, duration: duration });
      }
    
      onAnimationEventDone(event: AnimationEvent, index: number) {
        if (
          event.toState == "show" &&
          this.simulations[index].animationState == "show"
        )
          this.simulations[index].animationState = "shown";
        else if (
          event.toState == "shown" &&
          this.simulations[index].animationState == "shown"
        )
          this.simulations[index].animationState = "hide";
        else if (
          event.toState == "hide" &&
          this.simulations[index].animationState == "hide"
        )
          this.simulations[index].animationState = "hidden";
        else if (
          event.toState == "replaceHide" &&
          this.simulations[index].animationState == "replaceHide"
        )
          this.simulations[index].animationState = "replaceShow";
        else if (
          event.toState == "replaceShow" &&
          this.simulations[index].animationState == "replaceShow"
        )
          this.simulations[index].animationState = "shown";
      }
    
      onAnimationEventStart(event: AnimationEvent, index: number) {
        if (event.toState == "show" || event.toState == "replaceShow") {
          (event.element as HTMLElement).innerHTML =
            this.simulations[index].statusWSMessage;
        }
      }
    
      get travelDemandModelName() {
        return this.generateTravelDemandForm.get("travelDemandModelName");
      }
    
      get networkId() {
        return this.generateTravelDemandForm.get("networkId");
      }
    
      checkValid(control: AbstractControl) {
        return control.invalid && (control.dirty || control.touched);
      }
    
      onAddSimulation(): void {
        this.dialogRef = this.dialogService.open(SimulationCreationComponent, {});
      }
    }