diff --git a/ehci4intel-main/app.py b/ehci4intel-main/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5f09b5393ad1315c1daa1179ba17f27f837adb7
--- /dev/null
+++ b/ehci4intel-main/app.py
@@ -0,0 +1,521 @@
+from PyQt5.QtWidgets import *
+from PyQt5.QtCore import *
+from PyQt5.QtGui import *
+from pyqtgraph import *
+import psutil
+import re
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
+from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QComboBox, QWidget, QMessageBox
+import numpy as np
+from scipy.signal import savgol_filter
+import sys
+import os
+import os.path
+import time
+import ctypes
+import win32com.client
+import subprocess
+import pyqtgraph as pg
+import pandas as pd
+from PyQt5.QtGui import QIcon, QPixmap
+
+
+class Window(QMainWindow):
+    POWER_GADGET_PATH = None
+    LOG_FILE = None
+
+    def __init__(self):
+        super().__init__()
+        self.setWindowTitle("EHCI")
+        stylesheet = open("syle.css", "r").read()
+        self.setGeometry(100, 100, 1280, 800)
+        self.setup_ui()
+        self.update_data()
+        self.graph_canvas = FigureCanvas(plt.Figure())
+        self.setStyleSheet(stylesheet)
+        
+        icon = QPixmap('EHCI.png')
+        icon = icon.scaled(120, 120, aspectRatioMode=QtCore.Qt.KeepAspectRatio)  # Adjust the size (64, 64) to the desired dimensions
+        self.setWindowIcon(QIcon('EHCI.png'))
+        self.energy_data = []
+        
+        
+        
+
+        self.app_plot_widgets = {}
+
+    def add_new_plot_widget(self, title):
+        plot_widget = pg.PlotWidget()
+        plot_widget.setTitle(title)
+        self.graph_layout.addWidget(plot_widget)
+        return plot_widget
+
+    def setup_ui(self):
+        # Set the main window layout
+        main_layout = QVBoxLayout()
+
+        # Add a horizontal layout for buttons and labels
+        top_layout = QHBoxLayout()
+
+        # Button to set the Intel Power Gadget path
+        set_path_btn = QPushButton("Set Power Gadget Path")
+        set_path_btn.clicked.connect(self.set_power_gadget_path)
+        top_layout.addWidget(set_path_btn)
+
+        # Button to monitor an app
+        monitor_app_btn = QPushButton("Monitor App")
+        monitor_app_btn.clicked.connect(self.monitor_app)
+        top_layout.addWidget(monitor_app_btn)
+
+        # Button to create a log file
+        create_log_btn = QPushButton("Create Log")
+        create_log_btn.clicked.connect(self.create_log)
+        top_layout.addWidget(create_log_btn)
+
+        # Button to generate an energy report
+        generate_report_btn = QPushButton("Generate Energy Report")
+        generate_report_btn.clicked.connect(self.generate_energy_report)
+        top_layout.addWidget(generate_report_btn)
+
+        # Button to compare apps
+        compare_apps_btn = QPushButton("Compare Apps")
+        compare_apps_btn.clicked.connect(self.compare_apps)
+        top_layout.addWidget(compare_apps_btn)
+
+        # Button to exit the application
+        exit_app_btn = QPushButton("Exit")
+        exit_app_btn.clicked.connect(self.exit_app)
+        top_layout.addWidget(exit_app_btn)
+
+        # Add the top layout to the main layout
+        main_layout.addLayout(top_layout)
+
+        # Add battery information labels
+        self.battery_name_label = QLabel()
+        main_layout.addWidget(self.battery_name_label)
+        self.estimated_charge_remaining_label = QLabel()
+        main_layout.addWidget(self.estimated_charge_remaining_label)
+        self.design_capacity_label = QLabel()
+        main_layout.addWidget(self.design_capacity_label)
+        self.full_charge_capacity_label = QLabel()
+        main_layout.addWidget(self.full_charge_capacity_label)
+        self.battery_capacity_label = QLabel()
+        main_layout.addWidget(self.battery_capacity_label)
+        
+        self.user_type_label = QLabel("User Type:", self)
+        self.user_type_label.move(20, 130) # Adjust the position as needed
+        main_layout.addWidget(self.user_type_label)
+        
+        self.graph_layout = QVBoxLayout()
+        self.setLayout(self.graph_layout)
+        
+
+        self.user_type_combobox = QComboBox(self)
+        self.user_type_combobox.addItem("Normal")
+        self.user_type_combobox.addItem("Special Needs")
+        self.user_type_combobox.move(100, 130) # Adjust the position as needed
+        main_layout.addWidget(self.user_type_combobox)
+
+        self.button = QPushButton("Perform Action", self)
+        self.button.move(20, 170)  # Adjust the position as needed
+        self.button.clicked.connect(self.on_button_click)
+        main_layout.addWidget(self.button)
+        
+        
+        # Add power and energy consumption labels
+        self.power_label = QLabel()
+        main_layout.addWidget(self.power_label)
+        self.energy_consumption_label = QLabel()
+        main_layout.addWidget(self.energy_consumption_label)
+
+        # Add the graph canvas
+        #self.graph_canvas = FigureCanvas(plt.Figure())
+        #self.graph_canvas.setGeometry(320, 10, 960, 600)
+        #main_layout.addWidget(self.graph_canvas)
+        
+        self.app_name_label = QLabel()
+        main_layout.addWidget(self.app_name_label)
+        
+        self.energy_consumption_label = QLabel("", self)
+        main_layout.addWidget(self.energy_consumption_label)
+        
+        self.energy_consumption_graph = pg.PlotWidget(title="Energy Consumption")
+        main_layout.addWidget(self.energy_consumption_graph)
+        
+        # Add this line to store multiple monitored apps
+        self.monitored_apps = [] 
+        self.monitored_apps_label = QLabel("", self)
+        self.monitored_apps_energy = {}
+        main_layout.addWidget(self.monitored_apps_label) 
+        
+        # Set the main layout for the window
+        central_widget = QWidget()
+        central_widget.setLayout(main_layout)
+        self.setCentralWidget(central_widget)
+        main_layout.addWidget(central_widget)
+        
+              
+        self.show()
+    
+        # Set up a timer to update data every second
+        self.update_timer = QTimer(self)
+        self.update_timer.timeout.connect(self.update_data)
+        self.update_timer.start(1000)
+        
+        
+     
+    def on_button_click(self):
+        selected_user_type = self.user_type_combobox.currentText()
+        if selected_user_type == "Normal":
+            self.perform_action_for_normal_user()
+        elif selected_user_type == "Special Needs":
+            self.perform_action_for_special_needs_user()
+    def perform_action_for_normal_user(self):
+        # Add the code to perform the action for normal users here
+        print("Performing action for a normal user")
+
+    def perform_action_for_special_needs_user(self):
+        # Add the code to perform the action for users with special needs here
+        print("Performing action for a user with special needs")
+        
+            
+    def update_ui(self, app_name):
+        # Get energy consumption details for the selected app
+        energy_data = self.energy_data[app_name]
+
+        total_energy = sum(self.energy_data.values())
+        energy_percentage = (energy_data / total_energy) * 100
+
+        # Calculate average power usage
+        avg_power_usage = energy_data / self.monitoring_duration
+
+        # Calculate estimated battery drain time
+        battery = psutil.sensors_battery()
+        battery_drain_time = battery.percent / (energy_data / 100) if battery else 0
+
+        # Update labels
+        self.energy_absolute_label.setText(f"Energy Consumption (Wh): {energy_data:.2f}")
+        self.energy_percentage_label.setText(f"Energy Consumption (%): {energy_percentage:.2f}")
+        self.avg_power_usage_label.setText(f"Average Power Usage (W): {avg_power_usage:.2f}")
+        self.battery_drain_time_label.setText(f"Estimated Battery Drain Time (h): {battery_drain_time:.2f}")
+
+        # Update the graph
+        self.update_graph(app_name)
+
+        # Update system-wide metrics
+        self.cpu_label.setText(f"CPU Utilization: {psutil.cpu_percent()}%")
+        self.memory_label.setText(f"Memory Utilization: {psutil.virtual_memory().percent}%")
+        self.app_dropdown.currentTextChanged.connect(self.update_ui)
+
+    def update_data(self):
+        self.get_battery_data()
+        if self.POWER_GADGET_PATH:
+            power_data = self.get_power_data(self.POWER_GADGET_PATH, 1)
+            if 'Processor Power_0(Watt)' in power_data:
+                power = float(power_data['Processor Power_0(Watt)'])
+                self.power_label.setText(f"Processor Power: {power:.2f} W")
+                energy_consumption = power * 1 / 3600
+                self.energy_consumption_label.setText(f"Energy Consumption: {energy_consumption:.5f} Wh")
+
+                self.energy_data.append(energy_consumption)
+                self.energy_consumption_graph.plot(self.energy_data, clear=True, pen="b")
+
+    def update_app_graph(self, app_name, data):
+        app_plot_widget = self.app_plot_widgets[app_name]
+        app_plot_widget.plot(data, clear=True)
+
+    def update_graph(self, app_name):       
+    # Clear the current graph
+        self.graph_canvas.figure.clf()
+
+        # Create a new graph
+        ax = self.graph_canvas.figure.subplots()
+
+        # Get power usage data for the selected app
+        power_data = self.power_data[app_name]
+
+        # Plot the power usage over time
+        ax.plot(power_data["timestamps"], power_data["values"], label=app_name)
+        ax.set_xlabel("Time")
+        ax.set_ylabel("Power Usage (W)")
+        ax.set_title("Power Usage Over Time")
+        ax.legend()
+
+    # Refresh the graph
+        self.graph_canvas.draw()
+
+    def get_battery_data(self):
+        wmi = win32com.client.GetObject("winmgmts:")
+        battery_data = wmi.ExecQuery("Select * from Win32_Battery")
+
+        batteries = []
+        for battery in battery_data:
+            batteries.append(battery)
+            self.battery_name_label.setText(f"Battery Name: {battery.Name}")
+            self.estimated_charge_remaining_label.setText(f"Estimated Charge Remaining: {battery.EstimatedChargeRemaining}%")
+            self.design_capacity_label.setText(f"Design Capacity: {battery.DesignCapacity} mWh")
+            self.full_charge_capacity_label.setText(f"Full Charge Capacity: {battery.FullChargeCapacity} mWh")
+
+            # Read and show battery capacity
+            if battery.FullChargeCapacity is not None and battery.DesignCapacity is not None:
+                battery_capacity = (battery.FullChargeCapacity / battery.DesignCapacity) * 100
+                self.battery_capacity_label.setText(f'Battery capacity: {battery_capacity:.2f}%')
+            else:
+                self.battery_capacity_label.setText('Battery capacity information unavailable')
+
+        return batteries
+    def is_app_running(app_name):
+        for process in psutil.process_iter(['name']):
+            if process.info['name'] == app_name:
+                return True
+        return False
+
+
+    def get_power_data(self, power_gadget_path, duration):
+        script_dir = os.path.dirname(os.path.abspath(__file__))
+        power_log_path = os.path.join(power_gadget_path, "PowerLog3.0.exe")
+        log_file = os.path.join(script_dir, "power_log.csv")
+        command = f'"{power_log_path}" -duration {duration} -file "{log_file}"'
+
+        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        time.sleep(duration + 1)  # Wait for the logging process to finish
+        process.terminate()
+
+        while not os.path.exists(log_file):
+            time.sleep(0.1)
+
+        with open(log_file, "r") as f:
+            lines = f.readlines()
+            headers = lines[0].strip().split(',')
+            values = lines[1].strip().split(',')
+
+            power_data = {}
+            for i in range(len(headers)):
+                power_data[headers[i]] = values[i]
+
+        os.remove(log_file)
+        return power_data
+ 
+    def set_power_gadget_path(self):
+        folder_path = QFileDialog.getExistingDirectory(self, "Select directory")
+
+        if folder_path:
+            self.POWER_GADGET_PATH = folder_path
+            print(f"PowerLog3.0 path set to {self.POWER_GADGET_PATH}")
+
+
+    def create_log(self):
+        file_name, _ = QFileDialog.getSaveFileName(self, "Save file", "log.csv", "csv files (*.csv);;All Files (*)")
+
+        if file_name:
+            if (os.path.exists(file_name)):
+                os.remove(file_name)
+            
+            f = open(file_name, "x")
+            f.close()
+            self.LOG_FILE = file_name
+    
+    
+    def get_energy_consumption(self, app_path):
+        # Run the app with the powerlog.bat script and log the energy consumption
+        powerlog_exe = os.path.join(self.POWER_GADGET_PATH, "PowerLog3.0.exe")
+        log_file = "power_log.csv"
+        command = f'"{powerlog_exe}" -duration 10 -file "{log_file}"'
+
+        batch_file_content = f"""
+@echo off
+start /b "" cmd /c "{command} >> {log_file}"
+start /wait "" "{app_path}"
+"""
+
+        batch_file_path = os.path.join(os.path.dirname(log_file), "monitoring.bat")
+
+        with open(batch_file_path, "w") as f:
+            f.write(batch_file_content)
+
+        try:
+            os.startfile(batch_file_path, "runas")
+        except Exception as e:
+            QMessageBox.critical(self, "Error", f"An error occurred while running the monitoring process: {e}")
+        finally:
+            os.remove(batch_file_path)
+
+    # Calculate the energy consumption of the app
+        while not os.path.exists(log_file):
+            time.sleep(0.1)
+        
+        with open(log_file, "r") as f:
+            lines = f.readlines()
+            headers = lines[0].strip().split(',')
+            values = lines[1].strip().split(',')
+
+            power_data = {}
+            for i in range(len(headers)):
+                power_data[headers[i]] = float(values[i])
+
+        os.remove(log_file)
+        energy_consumption = sum(self.energy_data)
+        return energy_consumption
+    
+    def update_monitored_apps_label(self):
+        app_names = [os.path.basename(app_path) for app_path in self.monitored_apps]
+        app_names_text = "\n".join(app_names)
+        self.app_name_label.setText(f"Monitored Apps:\n{app_names_text}")
+       
+    def mess_with_app(self):
+        self.get_battery_data()
+        while True:
+            power_data = self.get_power_data(self.POWER_GADGET_PATH, 0.1)
+            if 'Processor Power_0(Watt)' in power_data:
+                power = float(power_data['Processor Power_0(Watt)']) * random.uniform(0.5, 1.5)
+                self.power_label.setText(f"Processor Power: {power:.2f} W")
+                energy_consumption = power * 0.1 / 3600
+                self.energy_consumption_label.setText(f"Energy Consumption: {energy_consumption:.5f} Wh")
+            self.energy_data.append(energy_consumption)
+            window_size = 5
+            if len(self.energy_data) > window_size:
+                smoothed_energy_data = savgol_filter(self.energy_data, window_length=11, polyorder=3)
+                self.energy_consumption_graph.plot(smoothed_energy_data, clear=True, pen="b")
+            else:
+                self.energy_consumption_graph.plot(self.energy_data, clear=True, pen="b")
+            time.sleep(0.1)
+    def exit_app(self):
+        sys.exit()
+
+    def is_admin():
+        try:
+            return ctypes.windll.shell32.IsUserAnAdmin()
+        except:
+            return False
+    def generate_energy_report(self):
+        report_file = os.path.join(self.current_directory, f"energy_report_{self.report_counter}.html")
+        command = f'powercfg /ENERGY /OUTPUT "{report_file}" /DURATION 5'
+
+        if is_admin():
+            try:
+                process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+                stdout, stderr = process.communicate()
+                print(f"Command output: {stdout.decode()}")  # Debug line
+                print(f"Command error: {stderr.decode()}")   # Debug line
+            except Exception as e:
+                QMessageBox.critical(self, "Error", f"An error occurred while running the energy monitoring process: {e}")
+        else:
+            # Re-run the script with admin rights
+            ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
+        
+
+        time.sleep(sampling_interval)
+
+        energy_usage = self.parse_energy_usage_from_report(report_file)
+        energy_usage_data.append(energy_usage)
+
+        os.remove(report_file)
+
+        return energy_usage_data
+    
+    def parse_energy_usage_from_report(self, report_file):
+        # Extract the energy usage value from the report_file
+        # This depends on the format of the energy report generated by the 'powercfg' command
+        energy_usage = 0
+
+        with open(report_file, "r") as f:
+            content = f.read()
+            # Assume energy usage is in the format "Energy usage (Wh): X" where X is a float
+            match = re.search(r"Energy usage \(Wh\):\s+([\d.]+)", content)
+            if match:
+                energy_usage = float(match.group(1))
+
+        return energy_usage
+
+    def moving_average(data, window_size):
+        data_series = pd.Series(data)
+        windows = data_series.rolling(window=window_size)
+        moving_averages = windows.mean()
+
+        return moving_averages.tolist()
+
+
+    def monitor_app(self,  app_name):
+        app_path, _ = QFileDialog.getOpenFileName(self, "Choose exe", "", "exe files (*.exe)")
+        app_plot_widget = self.add_new_plot_widget(app_name)
+
+    # Store the app's plot widget in a dictionary
+        self.app_plot_widgets[app_name] = app_plot_widget
+        if app_path:
+            if app_path not in self.monitored_apps:
+                self.monitored_apps.append(app_path)
+                app_name = os.path.basename(app_path)
+                print(f"Monitoring {app_name}")
+                self.update_monitored_apps_label()
+                energy_consumption = self.get_energy_consumption(app_path)
+                self.monitored_apps_energy[app_name] = energy_consumption
+            else:
+                QMessageBox.warning(self, "Warning", "The selected app is already being monitored.")
+
+            # Add the following code to the monitor_app function
+            powerlog_exe = os.path.join(self.POWER_GADGET_PATH, "PowerLog3.0.exe")
+            log_file = "power_log.csv"
+            command = f'"{powerlog_exe}" -duration 10 -file "{log_file}"'
+
+            batch_file_content = f"""
+@echo off
+start /b "" cmd /c "{command} >> {log_file}"
+start /wait "" "{app_path}"
+"""
+
+            batch_file_path = os.path.join(os.path.dirname(log_file), "monitoring.bat")
+
+            with open(batch_file_path, "w") as f:
+                f.write(batch_file_content)
+
+            try:
+                os.startfile(batch_file_path, "runas")
+                energy_usage_data = self.generate_energy_report(app_path, num_samples=10, sampling_interval=1)
+                smoothed_data = self.moving_average(energy_usage_data, window_size=3)
+
+
+            except Exception as e:
+                QMessageBox.critical(self, "Error", f"An error occurred while running the monitoring process: {e}")
+            finally:
+                os.remove(batch_file_path)
+    def compare_apps(self):
+        if len(self.monitored_apps) < 2:
+            QMessageBox.warning(self, "Warning", "Please monitor at least two apps before comparing their energy consumption.")
+            return
+
+        # Clear the current graph
+        self.graph_canvas.figure.clf()
+
+        # Create a new graph
+        ax = self.graph_canvas.figure.subplots()
+
+        app_names = list(self.monitored_apps_energy.keys())
+        energy_consumption_values = list(self.monitored_apps_energy.values())
+
+        # Create a bar chart
+        bars = ax.bar(app_names, energy_consumption_values)
+
+        # Add data labels on top of each bar
+        for bar in bars:
+            height = bar.get_height()
+            ax.annotate(f"{height:.2f}",
+                        xy=(bar.get_x() + bar.get_width() / 2, height),
+                        xytext=(0, 3),  # 3 points vertical offset
+                        textcoords="offset points",
+                        ha="center", va="bottom")
+
+        ax.set_xlabel("Applications")
+        ax.set_ylabel("Energy Consumption (Wh)")
+        ax.set_title("Energy Consumption Comparison")
+
+        # Refresh the graph
+        self.graph_canvas.draw()
+      
+if __name__ == '__main__':
+    app = QApplication(sys.argv)
+    window = Window()
+    
+    sys.exit(app.exec())            
+    
+    
\ No newline at end of file