diff --git a/.gitIgnore b/.gitIgnore index 5b7035925128d2960b18daf23a5e282e83d1118c..472e3223a8b568a8ea378b9925cbd855d5cb2c6e 100644 --- a/.gitIgnore +++ b/.gitIgnore @@ -1 +1,4 @@ -CreateDB.py \ No newline at end of file +practice/ +dataset/ +ui/ +__pycache__/ \ No newline at end of file diff --git a/src/features/db.py b/src/features/db.py new file mode 100644 index 0000000000000000000000000000000000000000..b9e18fc949188e38dc37cb98bb149cda60cf3ed7 --- /dev/null +++ b/src/features/db.py @@ -0,0 +1,14 @@ +import mysql.connector + +# ! Temporary credential +id_cred = 101 +name_cred = "Ferguso" + +db = mysql.connector.connect( + host="localhost", + user="root", + passwd="root", + database="toptrackr" +) + +mycursor = db.cursor() \ No newline at end of file diff --git a/src/features/input_data.py b/src/features/input_data.py new file mode 100644 index 0000000000000000000000000000000000000000..a2f20f215fa7c1f082f58d90ed5f33a154c76341 --- /dev/null +++ b/src/features/input_data.py @@ -0,0 +1,116 @@ +from PyQt5 import QtCore, QtGui, QtWidgets +from db import db, mycursor, id_cred +import datetime + +class input_data(QtWidgets.QWidget): + def __init__(self): + super().__init__() + self.Frame = QtWidgets.QFrame() + self.setupUi() + self.Frame.show() + + def setupUi(self): + self.Frame.setObjectName("Frame") + self.Frame.resize(376, 280) + self.Frame.setStyleSheet("background-color: rgb(238, 238, 238);") + self.Frame.setFrameShape(QtWidgets.QFrame.Panel) + self.Frame.setFrameShadow(QtWidgets.QFrame.Raised) + + self.setupComboBox() + self.setupButtonBox() + self.setupDateInput() + self.setupLabel() + self.setupMeasureInput() + + self.retranslateUi() + QtCore.QMetaObject.connectSlotsByName(self.Frame) + + def setupComboBox(self): # * Combobox - kendaraan atau listrik + self.comboBox = QtWidgets.QComboBox(self.Frame) + self.comboBox.setGeometry(QtCore.QRect(50, 20, 241, 31)) + self.comboBox.setFont(self.createFont("Lucida Console", 10)) + self.comboBox.setEditable(False) + self.comboBox.setObjectName("comboBox") + self.comboBox.addItem("") + self.comboBox.addItem("") + self.comboBox.setItemIcon(0, QtGui.QIcon('src/resources/img/lamp.png')) + self.comboBox.setItemIcon(1, QtGui.QIcon('src/resources/img/motorbike.png')) + self.comboBox.currentTextChanged.connect(self.changeUnit) + + def setupButtonBox(self): # * Button save or discard + self.buttonBox = QtWidgets.QDialogButtonBox(self.Frame) + self.buttonBox.setGeometry(QtCore.QRect(210, 240, 156, 23)) + self.buttonBox.setFont(self.createFont("Lucida Console", 10)) + self.buttonBox.setAcceptDrops(False) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Save) + self.buttonBox.setObjectName("buttonBox") + self.buttonBox.accepted.connect(self.save) + self.buttonBox.rejected.connect(self.discard) + + def setupDateInput(self): # * Date Input + self.dateEdit = QtWidgets.QDateEdit(self.Frame) + self.dateEdit.setGeometry(QtCore.QRect(110, 100, 121, 31)) + self.dateEdit.setFont(self.createFont("Lucida Console", 10)) + self.dateEdit.setObjectName("dateEdit") + + def setupLabel(self): # * Label + self.label = QtWidgets.QLabel(self.Frame) + self.label.setGeometry(QtCore.QRect(240, 150, 71, 16)) + self.label.setFont(self.createFont("Lucida Console", 10)) + self.label.setObjectName("label") + + def setupMeasureInput(self): # * Measurement input + self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.Frame) + self.doubleSpinBox.setGeometry(QtCore.QRect(110, 140, 121, 31)) + self.doubleSpinBox.setFont(self.createFont("Lucida Console", 10)) + self.doubleSpinBox.setObjectName("doubleSpinBox") + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.Frame.setWindowTitle(_translate("Frame", "Frame")) + self.comboBox.setItemText(0, _translate("Frame", "Listrik")) + self.comboBox.setItemText(1, _translate("Frame", "Kendaraan bermotor")) + self.label.setText(_translate("Frame", "kWh")) + + def discard(self): + pass + # Go back to summary window + + def save(self): + inDatabase = False + dateInForm = self.dateEdit.date().toPyDate().strftime('%Y-%m-%d') + mycursor.execute(f"SELECT EXISTS(SELECT * FROM carbon_trace WHERE TanggalInput = '{dateInForm}' AND ID_Customer = {id_cred})") + for x in mycursor: + if x[0] == 1: + inDatabase = True + break + + if inDatabase: + if self.comboBox.currentText() == "Listrik": + mycursor.execute(f"UPDATE carbon_trace SET KuantitasListrik = {self.doubleSpinBox.value()} WHERE TanggalInput = '{dateInForm}' AND ID_Customer = {id_cred}") + else: + mycursor.execute(f"UPDATE carbon_trace SET KuantitasJarakMotor = {self.doubleSpinBox.value()} WHERE TanggalInput = '{dateInForm}' AND ID_Customer = {id_cred}") + else: + if self.comboBox.currentText() == "Listrik": + mycursor.execute(f"INSERT INTO carbon_trace (ID_Customer, TanggalInput, KuantitasListrik) VALUES ({id_cred}, '{dateInForm}', {self.doubleSpinBox.value()} )") + else: + mycursor.execute(f"INSERT INTO carbon_trace (ID_Customer, TanggalInput, KuantitasJarakMotor) VALUES ({id_cred}, '{dateInForm}', {self.doubleSpinBox.value()} )") + db.commit() + + def changeUnit(self): + if self.comboBox.currentText() == "Listrik": + self.label.setText("kWh") + else: + self.label.setText("km") + + def createFont(self, fontName, fontSize): + font = QtGui.QFont() + font.setFamily(fontName) + font.setPointSize(fontSize) + return font + +# if __name__ == "__main__": +# import sys +# app = QtWidgets.QApplication(sys.argv) +# ui = input_data() +# sys.exit(app.exec_()) \ No newline at end of file diff --git a/src/features/progress_bar_pallete.py b/src/features/progress_bar_pallete.py new file mode 100644 index 0000000000000000000000000000000000000000..f0f9aaa4c2fcae0ac6ac5dd7682c271354ce0c56 --- /dev/null +++ b/src/features/progress_bar_pallete.py @@ -0,0 +1,27 @@ +default = """ +QProgressBar{ + border: 2px solid grey; + border-radius: 5px; + text-align: center +} + +QProgressBar::chunk { + background-color: green; + width: 10px; + margin: 1px; +} +""" + +overload = """ +QProgressBar{ + border: 2px solid grey; + border-radius: 5px; + text-align: center +} + +QProgressBar::chunk { + background-color: red; + width: 10px; + margin: 1px; +} +""" \ No newline at end of file diff --git a/src/features/summary_data.py b/src/features/summary_data.py new file mode 100644 index 0000000000000000000000000000000000000000..a6893a908a434d4b1ca5687fca27d8e19f774dc3 --- /dev/null +++ b/src/features/summary_data.py @@ -0,0 +1,236 @@ +from PyQt5 import QtCore, QtGui, QtWidgets +from db import db, mycursor, name_cred +from datetime import date, datetime +from input_data import * +from progress_bar_pallete import * + +performance = { + "Buruk": f"You can try to do better, upgrade to\npremium and see our tips and trick", + "Menengah": f"You are doing great, but you can do better\nby upgrade to premium and see the tips and trick", + "Baik": f"You are doing excellent job\nto decrease the emission" +} + +class summary_data(QtWidgets.QWidget): + def __init__(self): + super().__init__() + self.Frame = QtWidgets.QFrame() + self.setupUi() + self.Frame.show() + + def setupUi(self): + self.Frame.setObjectName("Frame") + self.Frame.resize(696, 491) + self.Frame.setStyleSheet("background-color: rgb(238, 238, 238);") + self.Frame.setFrameShape(QtWidgets.QFrame.Panel) + self.Frame.setFrameShadow(QtWidgets.QFrame.Raised) + + self.setupLabel() + self.setupLabelTotal() + self.setupLabelElectricity() + self.setupLabelMotorbike() + self.setupProgressBar1() + self.setupProgressBar2() + self.setupPushButton() + self.setupPushButtonWeekly() + self.setupPushButtonMonthly() + + self.retranslateUi() + QtCore.QMetaObject.connectSlotsByName(self.Frame) + + # * Frame component + def setupLabel(self): + self.label = QtWidgets.QLabel(self.Frame) + self.label.setGeometry(QtCore.QRect(180, 20, 291, 81)) + self.label.setFont(self.createFont("Lucida Console", 10)) + self.label.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) + self.label.setWordWrap(False) + self.label.setObjectName("label") + + def setupLabelTotal(self): + self.label_total = QtWidgets.QLabel(self.Frame) + self.label_total.setObjectName("label_total") + self.label_total.setGeometry(QtCore.QRect(30, 130, 621, 121)) + self.label_total.setFont(self.createFont("Lucida Console", 10)) + self.label_total.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) + self.label_total.setWordWrap(False) + + def setupLabelElectricity(self): + self.label_electricity = QtWidgets.QLabel(self.Frame) + self.label_electricity.setObjectName("label_electricity") + self.label_electricity.setGeometry(QtCore.QRect(94, 279, 170, 81)) + self.label_electricity.setFont(self.createFont("Lucida Console", 10)) + self.label_electricity.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) + self.label_electricity.setWordWrap(False) + + def setupLabelMotorbike(self): + self.label_motorbike = QtWidgets.QLabel(self.Frame) + self.label_motorbike.setObjectName("label_motorbike") + self.label_motorbike.setGeometry(QtCore.QRect(406, 280, 170, 81)) + self.label_motorbike.setFont(self.createFont("Lucida Console", 10)) + self.label_motorbike.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) + self.label_motorbike.setWordWrap(False) + + def setupProgressBar1(self): + self.progressBarElectric = QtWidgets.QProgressBar(self.Frame) + self.progressBarElectric.setGeometry(QtCore.QRect(120, 370, 151, 31)) + self.progressBarElectric.setFont(self.createFont("Lucida Console", 10)) + self.progressBarElectric.setStyleSheet(default) + self.progressBarElectric.setObjectName("progressBarElectric") + + def setupProgressBar2(self): + self.progressBarMotor = QtWidgets.QProgressBar(self.Frame) + self.progressBarMotor.setGeometry(QtCore.QRect(430, 370, 151, 31)) + self.progressBarMotor.setFont(self.createFont("Lucida Console", 10)) + self.progressBarMotor.setStyleSheet(default) + self.progressBarMotor.setObjectName("progressBarMotor") + + def setupPushButton(self): + self.pushButton = QtWidgets.QPushButton(self.Frame) + self.pushButton.setGeometry(QtCore.QRect(270, 440, 131, 31)) + self.pushButton.setFont(self.createFont("Lucida Console", 10)) + self.pushButton.setObjectName("pushButton") + + def setupPushButtonWeekly(self): + self.pushButton_weekly = QtWidgets.QPushButton(self.Frame) + self.pushButton_weekly.setObjectName("pushButton_weekly") + self.pushButton_weekly.setGeometry(QtCore.QRect(210, 80, 91, 31)) + self.pushButton_weekly.setStyleSheet("background-color: rgb(41, 255, 148);") + self.pushButton_weekly.clicked.connect(lambda: self.updateContent("Weekly")) + self.pushButton_weekly.clicked.connect(lambda: self.setGreen("Weekly")) + + def setupPushButtonMonthly(self): + self.pushButton_monthly = QtWidgets.QPushButton(self.Frame) + self.pushButton_monthly.setObjectName("pushButton_monthly") + self.pushButton_monthly.setGeometry(QtCore.QRect(340, 80, 91, 31)) + self.pushButton_monthly.clicked.connect(lambda: self.updateContent("Monthly")) + self.pushButton_monthly.clicked.connect(lambda: self.setGreen("Monthly")) + + # * Set the initial filling + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.Frame.setWindowTitle(_translate("Frame", "Frame")) + self.progressBarElectric.setFormat(_translate("Frame", "%p%")) + self.label.setText(_translate("Frame", f"{date.today().strftime('%d %B %Y')}\nHello, {name_cred}")) + self.pushButton.setText(_translate("Frame", "Catat Emisi [+]")) + self.pushButton_weekly.setText(_translate("Frame", "Weekly")) + self.pushButton_monthly.setText(_translate("Frame", "Monthly")) + self.updateContent("Weekly") + + # * Utility for filling + def createFont(self, fontName, fontSize): + font = QtGui.QFont() + font.setFamily(fontName) + font.setPointSize(fontSize) + return font + + def updateContent(self, period): + self.label_motorbike.setText(f"Motorbike summary\n{self.sumMotorbikeEmission(period)} km") + self.label_electricity.setText(f"Electricity summary\n{self.sumElectricityEmission(period)} kWh") + self.label_total.setText(f"Carbon dioxide total\n{self.sumCarbonDioxide(period)} gram CO2\n\n{self.getPerformanceText(period)}") + + p, q = self.getPercentValue(period) + self.progressBarElectric.setValue(int(p)) + self.progressBarMotor.setValue(int(q)) + + if p == 100: + self.progressBarElectric.setStyleSheet(overload) + else: + self.progressBarElectric.setStyleSheet(default) + + if q == 100: + self.progressBarMotor.setStyleSheet(overload) + else: + self.progressBarMotor.setStyleSheet(default) + + def getPercentValue(self, period): + if period == "Monthly": + percentValElectric = self.sumElectricityEmission("Weekly") / 127 * 100 + percentValMotor = self.sumMotorbikeEmission("Weekly") / 50 * 100 + p = min(100, percentValElectric) + q = min(100, percentValMotor) + return p,q + elif period == "Weekly": + percentValElectric = self.sumElectricityEmission("Monthly") / 893 * 100 + percentValMotor = self.sumMotorbikeEmission("Monthly") / 300 * 100 + p = min(100, percentValElectric) + q = min(100, percentValMotor) + return p,q + + def setGreen(self, period): + if period == "Weekly": + self.pushButton_weekly.setStyleSheet("background-color: rgb(41, 255, 148);") + self.pushButton_monthly.setStyleSheet("background-color: rgb(238, 238, 238);") + elif period == "Monthly": + self.pushButton_monthly.setStyleSheet("background-color: rgb(41, 255, 148);") + self.pushButton_weekly.setStyleSheet("background-color: rgb(238, 238, 238);") + + # * Measurement utility + def sumMotorbikeEmission(self, period): + if(period == "Weekly"): + dateBegin, dateLast = self.getRangeDate() + mycursor.execute(f"SELECT SUM(KuantitasJarakMotor) FROM carbon_trace WHERE ID_Customer = {id_cred} AND TanggalInput BETWEEN '{dateBegin}' AND '{dateLast}'") + elif(period == "Monthly"): + today = date.today() + # today = datetime.date(2022, 1, 14) # ! For testing + mycursor.execute(f"SELECT SUM(KuantitasJarakMotor) FROM carbon_trace WHERE ID_Customer = {id_cred} AND MONTH(TanggalInput) = {today.month} AND YEAR(TanggalInput) = {today.year}") + val = mycursor.fetchall() + if val[0][0] is None: + return 0 + return val[0][0] + + def sumElectricityEmission(self, period): + if(period == "Weekly"): + dateBegin, dateLast = self.getRangeDate() + mycursor.execute(f"SELECT SUM(KuantitasListrik) FROM carbon_trace WHERE ID_Customer = {id_cred} AND TanggalInput BETWEEN '{dateBegin}' AND '{dateLast}'") + elif(period == "Monthly"): + today = date.today() + # today = datetime.date(2022, 1, 14) # ! For testing + mycursor.execute(f"SELECT SUM(KuantitasListrik) FROM carbon_trace WHERE ID_Customer = {id_cred} AND MONTH(TanggalInput) = {today.month} AND YEAR(TanggalInput) = {today.year}") + val = mycursor.fetchall() + if val[0][0] is None: + return 0 + return val[0][0] + + def sumCarbonDioxide(self, period): + if(period == "Weekly"): + return (self.sumElectricityEmission("Weekly") * 385) + (self.sumMotorbikeEmission("Weekly") * 132) + elif(period == "Monthly"): + return (self.sumElectricityEmission("Monthly") * 385) + (self.sumMotorbikeEmission("Monthly") * 132) + + def getPerformanceText(self, period): + if period == "Weekly": + totalEmission = self.sumCarbonDioxide("Weekly") + if totalEmission <= 3000: + return performance["Baik"] + elif totalEmission > 3000 and totalEmission < 7000: + return performance["Menengah"] + else: + return performance["Buruk"] + elif period == "Monthly": + totalEmission = self.sumCarbonDioxide("Monthly") + if totalEmission <= 13000: + return performance["Baik"] + elif totalEmission > 13000 and totalEmission < 30000: + return performance["Menengah"] + else: + return performance["Buruk"] + + def getRangeDate(self): + today = date.today() + # today = datetime.date(2022, 1, 14) # ! For testing + if today.strftime("%A") == "Monday": + lastMonday = today + else: + lastMonday = today - datetime.timedelta(days=today.weekday()) + + if today.strftime("%A") == "Sunday": + nextSunday = today + else: + nextSunday = today + datetime.timedelta( (6-today.weekday()) % 7 ) + return lastMonday, nextSunday + +# if __name__ == "__main__": +# import sys +# app = QtWidgets.QApplication(sys.argv) +# ui = summary_data() +# sys.exit(app.exec_()) \ No newline at end of file diff --git a/src/features/your_features.py b/src/features/your_features.py deleted file mode 100644 index 180b740e00080d4109d956f92b0d128ca0a26ea8..0000000000000000000000000000000000000000 --- a/src/features/your_features.py +++ /dev/null @@ -1 +0,0 @@ -# Create here \ No newline at end of file diff --git a/src/resources/img/lamp.png b/src/resources/img/lamp.png new file mode 100644 index 0000000000000000000000000000000000000000..498af51e2b5ceee4c57665ad9b33434d2aadf3cd Binary files /dev/null and b/src/resources/img/lamp.png differ diff --git a/src/resources/img/motorbike.png b/src/resources/img/motorbike.png new file mode 100644 index 0000000000000000000000000000000000000000..6611ff46aa6ee7d1403e622f8cb82285acc2fac6 Binary files /dev/null and b/src/resources/img/motorbike.png differ