diff --git a/hdhdjshxh/README.md b/hdhdjshxh/README.md new file mode 100644 index 00000000..aa25895c --- /dev/null +++ b/hdhdjshxh/README.md @@ -0,0 +1,23 @@ +## Basic Features + +Based on the given Python code, +you are required to add the following functions to the Python script. + +- Using Scapy, identify the following items from the given PCAP files on Moodle: + + - Scenario + While Wireshark captured the network traffic in the internal network, + the host (IP: 192.168.186.155) performed the Nmap + to scan the targeted server (IP: 192.168.186.156). + + - How many packets are? + - What ports have been scanned? + - How many ports have been scanned? + +- Display the results of items in a textbox in the GUI interface. + +- Add a clear button which can be used to clear all input and output in the GUI. + +- Use two threads, one thread for GUI execution and another thread for analysing PCAP files. + +- Store all the information (e.g. date and time, PCAP filename, and the results of items) related to analysing PCAP files in the SQLite database. diff --git a/hdhdjshxh/gitUpdate.bat b/hdhdjshxh/gitUpdate.bat new file mode 100644 index 00000000..8e2e00e9 --- /dev/null +++ b/hdhdjshxh/gitUpdate.bat @@ -0,0 +1,7 @@ +git status . + +@pause + +git add . +git commit -m"update hdhdjshxh," +start git push \ No newline at end of file diff --git a/hdhdjshxh/history.md b/hdhdjshxh/history.md new file mode 100644 index 00000000..bd82a11c --- /dev/null +++ b/hdhdjshxh/history.md @@ -0,0 +1,12 @@ +### Quotation factor: + +- setup + + - setup fee 50 + +- difficulty + + - 3 question HKD 150 + +HKD 150 +deposit 50 diff --git a/hdhdjshxh/package.json b/hdhdjshxh/package.json new file mode 100644 index 00000000..869c6af6 --- /dev/null +++ b/hdhdjshxh/package.json @@ -0,0 +1,13 @@ +{ + "name": "hdhdjshxh", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "gitUpdate": "git add . && git commit -m\"update hdhdjshxh,\"" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/hdhdjshxh/prompt.md b/hdhdjshxh/prompt.md new file mode 100644 index 00000000..14906967 --- /dev/null +++ b/hdhdjshxh/prompt.md @@ -0,0 +1,59 @@ +### How many packets are? + +using scapy +how to read a file named 'PCAP/ay2223_sasp_nmapcatured_1.pcap' +show the number of packet of the file ? + + + +### What ports have been scanned? + + +using scapy +how to read a file named 'PCAP/ay2223_sasp_nmapcatured_1.pcap' +show the what ports have been scanned ? +classify them in source port and destination port +```python +from scapy.all import * + +# Provide the path to your PCAP file +pcap_file = 'PCAP/ay2223_sasp_nmapcatured_1.pcap' + +# Read the PCAP file +packets = rdpcap(pcap_file) + +# Create an empty set to store unique destination ports +scanned_ports = set() + +for packet in packets: + # Check if it's a TCP packet with destination port information + if TCP in packet and packet[TCP].dport not in scanned_ports: + scanned_ports.add(packet[TCP].dport) + +print("Ports that have been scanned:") +for port in sorted(scanned_ports): + print(port) +``` + +### How many ports have been scanned? + +using scapy +how to read a file named 'PCAP/ay2223_sasp_nmapcatured_1.pcap' +How many ports have been scanned ? + +```python +from scapy.all import * + +packets = rdpcap('PCAP/ay2223_sasp_nmapcatured_1.pcap') + +scanned_ports = set() # Set to store unique scanned ports + +for pkt in packets: + if pkt.haslayer(TCP): + dst_port = pkt[TCP].dport # Destination port + scanned_ports.add(dst_port) + +print("Number of ports scanned:", len(scanned_ports)) + +``` + diff --git a/hdhdjshxh/task1/SASP Assignment 1c Python Scripting 2023 (pcap info).doc b/hdhdjshxh/task1/SASP Assignment 1c Python Scripting 2023 (pcap info).doc new file mode 100644 index 00000000..ec5cec2f Binary files /dev/null and b/hdhdjshxh/task1/SASP Assignment 1c Python Scripting 2023 (pcap info).doc differ diff --git a/hdhdjshxh/task1/SASP Assignment 1c Python Scripting 2023 v3.doc b/hdhdjshxh/task1/SASP Assignment 1c Python Scripting 2023 v3.doc new file mode 100644 index 00000000..97bc4380 Binary files /dev/null and b/hdhdjshxh/task1/SASP Assignment 1c Python Scripting 2023 v3.doc differ diff --git a/hdhdjshxh/task1/helloworld.py b/hdhdjshxh/task1/helloworld.py new file mode 100644 index 00000000..83390134 --- /dev/null +++ b/hdhdjshxh/task1/helloworld.py @@ -0,0 +1,9 @@ +import tkinter as tk + +# Create an instance of the Tk class (root window) +window = tk.Tk() + +# Add widgets and functionality to the window + +# Start the event loop for application execution +window.mainloop() diff --git a/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_1.pcap b/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_1.pcap new file mode 100644 index 00000000..4392ef01 Binary files /dev/null and b/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_1.pcap differ diff --git a/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_2.pcap b/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_2.pcap new file mode 100644 index 00000000..e2935202 Binary files /dev/null and b/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_2.pcap differ diff --git a/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_3.pcap b/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_3.pcap new file mode 100644 index 00000000..ba1ede26 Binary files /dev/null and b/hdhdjshxh/task1/original/PCAP/ay2223_sasp_nmapcatured_3.pcap differ diff --git a/hdhdjshxh/task1/original/Pipfile b/hdhdjshxh/task1/original/Pipfile new file mode 100644 index 00000000..9daa3732 --- /dev/null +++ b/hdhdjshxh/task1/original/Pipfile @@ -0,0 +1,12 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] + +[requires] +python_version = "3.11" +python_full_version = "3.11.3" diff --git a/hdhdjshxh/task1/original/SASP Assignment 1c Python Scripting 2023 (pcap info).doc b/hdhdjshxh/task1/original/SASP Assignment 1c Python Scripting 2023 (pcap info).doc new file mode 100644 index 00000000..ec5cec2f Binary files /dev/null and b/hdhdjshxh/task1/original/SASP Assignment 1c Python Scripting 2023 (pcap info).doc differ diff --git a/hdhdjshxh/task1/original/sasp-part-b-assignment-v1.py b/hdhdjshxh/task1/original/sasp-part-b-assignment-v1.py new file mode 100644 index 00000000..1bccda30 --- /dev/null +++ b/hdhdjshxh/task1/original/sasp-part-b-assignment-v1.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 + +import sqlite3 +from sqlite3 import Error +import tkinter as tk +from tkinter import ttk +from scapy.all import * +from datetime import datetime + +def create_connection(db_file): + conn = None + try: + conn = sqlite3.connect(db_file) + except Error as e: + print(e) + return conn + +def select_all_pcaprecords(conn): + cur = conn.cursor() + cur.execute("SELECT * FROM pcap_records") + + rows = cur.fetchall() + return rows + +def open_popup(text_display): + top = tk.Toplevel(mainwindow) + top.geometry("550x250") + top.title("Analysis Results!") + popup_text = tk.Text(top, height=10, width=65,font=('Consolas',10)) + popup_text.grid(row=0,column=0,padx=5,pady=5,sticky=tk.W) + popup_text.insert(tk.END,text_display) + +def callback(event): + filepath = "./outputfiles/" + # get the index of the mouse click + index = event.widget.index("@%s,%s" % (event.x, event.y)) + + # get the indices of all "adj" tags + tag_indices = list(event.widget.tag_ranges('tag')) + + # iterate them pairwise (start and end index) + for start, end in zip(tag_indices[0::2], tag_indices[1::2]): + # check if the tag matches the mouse click index + if event.widget.compare(start, '<=', index) and event.widget.compare(index, '<', end): + # return string between tag start and end + filename = filepath + event.widget.get(start, end) + print(filename) + file1 = open(filename,'r') + lines = file1.readlines() + d = "" + for line in lines: + d += line.strip() + "\n" + + open_popup(d) + +def display_to_text(in_data): + displaytext.tag_config("tag",foreground="blue") + displaytext.tag_bind("tag","", callback) + displaytext.insert(tk.END, 'ID' + "\t" + "PCAP Filename" + " " + "Date" + "\t\t\t\t" + "Time" + "\t" + "Output File\n") + displaytext.insert(tk.END, '==' + "\t" + "==========================" + "\t" + "========" + "\t" + "====" + "\t" + "===========\n") + for row in in_data: + displaytext.insert(tk.END, str(row[0]) + "\t" + row[1] + " \t\t\t" + row[2] + "\t" + row[3] + " " + row[4] + "\t") + displaytext.insert(tk.END,row[4],"tag") + displaytext.insert(tk.END,"\n") + +def get_current_date(): + now = datetime.now() + return now.strftime('%Y%m%d') + +def get_current_time(): + now = datetime.now() + return now.strftime('%H%M%S') + + +def analysispcap(): + pcapFile = getfiletextbox.get() + pcap = rdpcap(pcapFile) + numofpackets = len(pcap) + resultstextbox.insert(tk.END,numofpackets) + +def saveresult(): + pcapFile = getfiletextbox.get() + analysis_date = get_current_date() + analysis_time = get_current_time() + analysis_output = resultstextbox.get("1.0","end-1c") + output_filename = analysis_date + analysis_time + '.txt' + print(pcapFile) + print(analysis_date) + print(analysis_time) + print(analysis_output) + print(output_filename) + +# ====================== Main Start Here ===================================================== + +database = r"saspdemo.db" +conn = create_connection(database) +rows = select_all_pcaprecords(conn) +data = [] + +for row in rows: + data.append([row[0], row[1], row[2], row[3], row[4]]) + +mainwindow = tk.Tk() +mainwindow.title("SASP Part B Assignment AY2223 - PCAP Analysis By Chan Tai Man") +tabControl = ttk.Notebook(mainwindow) + +tab1 = ttk.Frame(tabControl) +tab2 = ttk.Frame(tabControl) + +tabControl.add(tab1, text ='Network Traffic Analysis') +tabControl.add(tab2, text ='History') +tabControl.pack(expand = 1, fill ="both") + +# =================== tab 1 GUI Layout ======================================================== + +getfilelabel = tk.Label(tab1,text='Start to work on your assignment',fg='red',font=('Consolas',12)) +getfilelabel.grid(row=0,column=0,padx=5,sticky=tk.W) + + +# =================== tab 2 GUI Layout ======================================================== + +displaybtn = tk.Button(tab2, text="DISPLAY", fg='blue', width=20, command=lambda:display_to_text(data)) +displaybtn.grid(row=0,column=0, padx=5,pady=10,sticky=tk.W) + +displaytext = tk.Text(tab2,height=10, width=100,font=('Consolas',10)) +displaytext.grid(row=2,column=0,padx=5,pady=5,sticky=tk.W) + +mainwindow.mainloop() diff --git a/hdhdjshxh/task1/original/saspdemo.db b/hdhdjshxh/task1/original/saspdemo.db new file mode 100644 index 00000000..6ee02c8e Binary files /dev/null and b/hdhdjshxh/task1/original/saspdemo.db differ diff --git a/hdhdjshxh/task1/requirements.txt b/hdhdjshxh/task1/requirements.txt new file mode 100644 index 00000000..2146001c --- /dev/null +++ b/hdhdjshxh/task1/requirements.txt @@ -0,0 +1,478 @@ +aardwolf==0.2.2 +adblockparser==0.7 +AdvancedHTTPServer==2.2.0 +aesedb==0.1.3 +aiocmd==0.1.2 +aioconsole==0.3.1 +aiodns==3.0.0 +aiofiles==23.1.0 +aiohttp==3.8.4 +aiomultiprocess==0.9.0 +aioredis==1.3.1 +aiosignal==1.3.1 +aiosmb==0.4.4 +aiosqlite==0.17.0 +aiowinreg==0.0.7 +ajpy==0.0.4 +alembic==1.8.1.dev0 +altgraph==0.17.3 +aniso8601==9.0.1 +anyio==3.6.2 +apispec==5.2.2 +apispec-webframeworks==0.5.2 +appdirs==1.4.4 +APScheduler==3.9.1 +arc4==0.3.0 +arrow==1.2.3 +asciitree==0.3.3 +asgiref==3.6.0 +asn1crypto==1.5.1 +asn1tools==0.164.0 +asttokens==2.2.1 +asyauth==0.0.9 +async-timeout==4.0.2 +asysocks==0.2.2 +attrs==22.2.0 +autobahn==22.7.1 +autocommand==2.2.2 +Automat==22.10.0 +Babel==2.10.3 +backcall==0.2.0 +backoff==2.2.1 +base58==1.0.3 +bcrypt==3.2.2 +beautifulsoup4==4.11.2 +beniget==0.4.1 +bidict==0.22.1 +binwalk==2.3.3 +bitstruct==8.15.1 +bleach==5.0.1 +blinker==1.5 +bluepy==1.3.0 +boltons==21.0.0 +bottle==0.12.23 +Bottleneck==1.3.5 +Brlapi==0.8.4 +Brotli==1.0.9 +cbor==1.0.0 +censys==2.1.9 +certifi==2022.9.24 +cffi==1.15.1 +chardet==5.1.0 +charset-normalizer==3.0.1 +cheroot==9.0.0+ds1 +CherryPy==18.8.0 +cherrypy-cors==1.6 +cli-helpers==2.3.0 +click==8.1.3 +click-plugins==1.1.1 +cmd2==2.4.2+ds +colorama==0.4.6 +configobj==5.0.8 +constantly==15.1.0 +contourpy==1.0.7 +crackmapexec==5.4.0 +cryptography==38.0.4 +cryptography37==37.0.2 +cvss==2.4 +cycler==0.11.0 +Cython==0.29.32 +dbus-python==1.3.2 +debtags==2.1 +decorator==5.1.1 +defusedxml==0.7.1 +Deprecated==1.2.13 +dicttoxml==1.7.15 +diskcache==5.4.0 +distlib==0.3.6 +distro==1.8.0 +Django==3.2.19 +dnslib==0.9.23 +dnspython==2.3.0 +docopt==0.6.2 +donut-shellcode==0.9.3 +dropbox==11.34.0 +dsinternals==1.2.4 +ecdsa==0.18.0 +email-validator==1.3.0 +et-xmlfile==1.0.1 +executing==1.2.0 +ExifRead==3.0.0 +faraday-agent-dispatcher==2.4.0 +faraday-agent-parameters-types==1.2.0 +faraday-cli==2.1.8 +faraday-plugins==1.10.0 +faradaysec==4.3.5 +fastapi==0.92.0 +feedparser==6.0.10 +fierce==1.5.0 +filedepot==0.5.2 +filelock==3.9.0 +filteralchemy==0.1.0 +flasgger==0.9.5 +Flask==2.2.2 +Flask-Classful==0.15.0.dev1 +Flask-KVSession-fork==0.6.4 +Flask-Limiter==3.3.0 +Flask-Login==0.6.2 +Flask-Mail==0.9.1 +Flask-Principal==0.4.0 +Flask-RESTful==0.3.9 +Flask-Security-Too==4.0.0 +Flask-SocketIO==5.3.2 +Flask-SQLAlchemy==3.0.3 +Flask-WTF==1.1.1 +flatbuffers==2.0.8+dfsg1.2 +fonttools==4.38.0 +frozenlist==1.3.3 +fs==2.4.16 +future==0.18.2 +gast==0.5.2 +GDAL==3.6.2 +GeoIP==1.3.2 +geoip2==2.9.0 +geojson==3.0.0 +gitdb==4.0.9 +GitPython==3.1.30 +gpg==1.18.0 +graphene==2.1.9 +graphene-sqlalchemy==2.1.2 +graphql-core==2.2.1 +graphql-relay==2.0.1 +greenlet==2.0.2 +h11==0.14.0 +h2==4.1.0 +hashID==3.1.4 +hiredis==1.0.1 +hkdf==0.0.3 +hpack==4.0.0 +html2text==2020.1.16 +html5lib==1.1 +httpagentparser==1.9.1 +httpcore==0.16.3 +httpx==0.23.3 +humanize==0.0.0 +hupper==1.10.3 +hyperframe==6.0.0 +hyperlink==21.0.0 +icalendar==4.0.3 +idna==3.3 +impacket==0.10.0 +importlib-metadata==4.12.0 +incremental==21.3.0 +inflect==2.1.0 +iniconfig==1.1.1 +invoke==2.0.0 +ipwhois==1.2.0 +IPy==1.1 +ipython==8.5.0 +itsdangerous==2.1.2 +jaraco.classes==3.2.1 +jaraco.collections==3.8.0 +jaraco.context==4.2.0 +jaraco.functools==3.5.0 +jaraco.text==3.11.1 +jdcal==1.0 +jedi==0.18.2 +Jinja2==3.1.2 +jq==1.2.1 +jsonpointer==2.3 +jsonschema==4.10.3 +kaitaistruct==0.10 +kali-tweaks==2023.2.2 +KismetCaptureBtGeiger==2021.7.1 +KismetCaptureFreaklabsZigbee==2018.7.0 +KismetCaptureRtl433==2020.10.1 +KismetCaptureRtladsb==2020.10.1 +KismetCaptureRtlamr==2020.10.1 +kiwisolver==0.0.0 +ldap3==2.9.1 +ldapdomaindump==0.9.3 +lightdm-gtk-greeter-settings==1.2.2 +limits==2.8.0 +llvmlite==0.39.1 +log-symbols==0.0.14 +louis==3.24.0 +lsassy==3.1.6 +lxml==4.9.2 +lz4==4.0.2+dfsg +macholib==1.16.2 +magic-wormhole==0.12.0 +Mako==1.2.4.dev0 +Markdown==3.4.1 +markdown-it-py==2.1.0 +MarkupSafe==2.1.2 +marshmallow==3.18.0 +marshmallow-sqlalchemy==0.29.0 +masky==0.1.1 +matplotlib==3.6.3 +matplotlib-inline==0.1.6 +maxminddb==2.1.0 +mdurl==0.1.2 +mechanize==0.4.8 +minidump==0.0.21 +minikerberos==0.4.0 +mistune0==0.8.4 +mitmproxy==9.0.1 +mnemonic==0.19 +more-itertools==8.10.0 +mpmath==0.0.0 +msgpack==1.0.3 +msldap==0.4.7 +multidict==6.0.4 +mysqlclient==1.4.6 +nassl==5.0.1 +neo4j==5.2.dev0 +neobolt==1.7.17 +neotime==1.7.4 +netaddr==0.8.0 +netifaces==0.11.0 +networkx==2.8.8 +notus-scanner==22.4.4 +nplusone==1.0.0 +ntpsec==1.2.2 +numba==0.56.4 +numexpr==2.8.4 +numpy==1.24.2 +odfpy==1.4.2 +olefile==0.46 +onboard==1.4.1 +openpyxl==3.0.9 +ordered-set==4.1.0 +oscrypto==1.3.0 +ospd-openvas==22.4.6 +packaging==23.0 +paho-mqtt==1.6.1 +pandas==1.5.3 +paramiko==2.12.0 +parso==0.8.3 +passlib==1.7.4 +Paste==3.5.2 +PasteDeploy==3.0.1 +PasteScript==3.2.1 +patator==0.9 +pcapy==0.11.5.dev0 +pefile==2023.2.7 +pendulum==2.1.2 +pexpect==4.8.0 +pgcli==3.5.0 +pgspecial==2.0.1 +phonenumbers==8.12.57 +pickleshare==0.7.5 +Pillow==9.4.0 +plaster==1.0 +plaster-pastedeploy==0.5 +platformdirs==2.6.0 +pluggy==1.0.0+repack +pluginbase==1.0.1 +ply==3.11 +portend==3.1.0 +prettytable==3.6.0 +promise==2.3 +prompt-toolkit==3.0.36 +protobuf==4.21.12 +psutil==5.9.4 +psycopg==3.1.7 +psycopg2==2.9.5 +ptyprocess==0.7.0 +publicsuffix2==2.20191221 +publicsuffixlist==0.9.3 +pure-eval==0.0.0 +py==1.11.0 +py-sneakers==1.0.1 +py-ubjson==0.16.1 +pyasn1==0.4.8 +pyasn1-modules==0.2.8 +pycairo==1.20.1 +pycares==4.3.0 +pycparser==2.21 +pycryptodomex==3.11.0 +pycurl==7.45.2 +pydantic==1.10.4 +PyDispatcher==2.0.5 +pydot==1.4.2 +pyee==9.0.4 +pyExploitDb==0.2.6 +pyfiglet==0.8.post0 +pygame==2.1.2 +pygexf==0.2.2 +Pygments==2.14.0 +PyGObject==3.42.2 +pygraphviz==1.7 +PyHamcrest==2.0.3 +pyinotify==0.9.6 +PyInstaller==3.5+498e6ee058 +PyJWT==2.6.0 +pylnk3==0.4.2 +pyminifier==2.1 +pymssql==2.2.2 +PyMySQL==1.0.2 +PyNaCl==1.5.0 +PyOpenGL==3.1.6 +pyOpenSSL==23.0.0 +pyotp==2.6.0 +pyparsing==3.0.9 +PyPDF2==2.12.1 +pyperclip==1.8.2 +pypng==0.20220715.0 +pyppeteer==1.0.1 +pypsrp==0.8.1 +pypykatz==0.6.6 +PyQRCode==1.2.1 +PyQt5==5.15.9 +PyQt5-sip==12.11.1 +PyQt6==6.4.2 +PyQt6-sip==13.4.1 +pyqtgraph==0.13.1 +pyramid==2.0 +pyrsistent==0.18.1 +PySecretSOCKS==0.9.1 +pyserial==3.5 +pyShodan==0.2.6 +pysmi==0.3.2 +pysnmp==4.4.12 +PySocks==1.7.1 +pyspnego==0.8.0 +pytest==7.2.1 +python-apt==2.5.3 +python-dateutil==2.8.2 +python-debian==0.1.49 +python-docx==0.8.11 +python-dotenv==0.21.0 +python-engineio==4.3.4 +python-gnupg==0.4.9 +python-gvm==23.2.0 +python-jose==3.3.0 +python-magic==0.4.26 +python-multipart==0.0.5 +python-owasp-zap-v2.4==0.0.20 +python-pam==2.0.2 +python-pptx==0.6.18 +python-slugify==4.0.0 +python-snappy==0.5.3 +python-socketio==5.7.2 +python-status==1.0.1 +pythran==0.11.0 +PyTrie==0.4.0 +pytz==2022.7.1 +pytz-deprecation-shim==0.1.0.post0 +pytzdata==2020.1 +pyVNC==0.1 +pywerview==0.3.3 +pyxdg==0.28 +PyYAML==6.0 +qrcode==7.4.2 +Quamash==0.6.1 +redis==4.3.4 +repoze.lru==0.7 +requests==2.28.1 +requests-file==1.5.1 +requests-toolbelt==0.10.1 +retrying==1.3.3 +rfc3986==1.5.0 +rfc3987==1.3.8 +rich==13.3.1 +Routes==2.5.1 +rq==1.13.0 +rsa==4.8 +ruamel.yaml==0.17.21 +ruamel.yaml.clib==0.2.7 +rule-engine==3.5.0 +Rx==3.2.0 +scapy==2.5.0 +scipy==1.10.1 +secure==0.3.0 +service-identity==18.1.0 +setproctitle==1.3.1 +sgmllib3k==1.0.0 +shodan==1.28.0 +simple-rest-client==1.1.3 +simplejson==3.18.3 +simplekv==0.14.1 +six==1.16.0 +slowapi==0.1.4 +smmap==5.0.0 +smoke-zephyr==2.0.1 +sniffio==1.2.0 +sortedcontainers==2.4.0 +soupsieve==2.3.2 +spake2==0.8 +spinners==0.0.24 +SQLAlchemy==1.4.46 +sqlalchemy-schemadisplay==1.3 +SQLAlchemy-Utc==0.14.0 +sqlparse==0.4.2 +sslyze==5.1.3 +stack-data==0.6.2 +starlette==0.26.1 +stone==3.3.1 +sympy==1.11.1 +syslog-rfc5424-formatter==1.2.3 +tables==3.7.0 +tabulate==0.8.9 +Tempita==0.5.2 +tempora==5.1.0 +termcolor==1.1.0 +terminaltables==3.1.10 +texttable==1.6.7 +theHarvester==4.2.0 +tinycss2==1.2.1 +tld==0.11.11 +tls-parser==1.2.2 +tomli==2.0.1 +tornado==6.2 +tqdm==4.64.1 +traitlets==5.5.0 +translationstring==1.4 +Twisted==22.4.0 +txaio==21.2.1 +txtorcon==23.5.0 +typing_extensions==4.4.0 +tzlocal==4.2 +u-msgpack-python==2.3.0 +ufoLib2==0.14.0 +ujson==5.7.0 +unicodecsv==0.14.1 +unicrypto==0.0.10 +Unidecode==1.3.6 +uritemplate==4.1.1 +urllib3==1.26.12 +urwid==2.1.2 +uvicorn==0.17.6 +uvloop==0.17.0 +validators==0.20.0 +venusian==3.0.0 +virtualenv==20.17.1+ds +wafw00f==2.2.0 +wapiti3==3.0.4 +wcwidth==0.2.5 +webargs==8.0.1 +webcolors==1.11.1 +webencodings==0.5.1 +WebOb==1.8.6 +websocket-client==1.2.3 +websockets==10.4 +websockify==0.10.0 +Werkzeug==2.2.2 +wfuzz==3.1.0 +whois==0.8 +wifite==2.6.6 +winacl==0.1.7 +wrapt==1.14.1 +wsaccel==0.6.3 +wsproto==1.2.0 +WTForms==3.0.1 +xdg==5 +xlrd==1.2.0 +XlsxWriter==3.0.2 +xlutils==2.0.0 +xlwt==1.3.0 +xmltodict==0.13.0 +yara-python==4.2.0 +yarl==1.8.2 +yaswfp==0.9.3 +zc.lockfile==2.0 +zipp==1.0.0 +zlib-wrapper==0.1.3 +zope.deprecation==4.4.0 +zope.interface==5.5.2 diff --git a/hdhdjshxh/task1/scapy_helloworld.py b/hdhdjshxh/task1/scapy_helloworld.py new file mode 100644 index 00000000..8de39a61 --- /dev/null +++ b/hdhdjshxh/task1/scapy_helloworld.py @@ -0,0 +1,52 @@ +from scapy.all import * + +packets = rdpcap('PCAP/ay2223_sasp_nmapcatured_1.pcap') + +scanned_ports = set() # Set to store unique scanned ports + +for pkt in packets: + if pkt.haslayer(TCP): + dst_port = pkt[TCP].dport # Destination port + scanned_ports.add(dst_port) + +print("Number of ports scanned:", len(scanned_ports)) + + +from scapy.all import * + +# Provide the path to your PCAP file +pcap_file = 'PCAP/ay2223_sasp_nmapcatured_1.pcap' + +# Read the PCAP file +packets = rdpcap(pcap_file) + +# Create an empty set to store unique destination ports +scanned_ports = set() + +for packet in packets: + # Check if it's a TCP packet with destination port information + if TCP in packet and packet[TCP].dport not in scanned_ports: + scanned_ports.add(packet[TCP].dport) + +print("Ports that have been scanned:") +for port in sorted(scanned_ports): + print(port) + + + + +# PCAP/ay2223_sasp_nmapcatured_1.pcap +from scapy.all import * + +# Provide the path to your PCAP file +pcap_file = 'PCAP/ay2223_sasp_nmapcatured_1.pcap' + +# Read the PCAP file +packets = rdpcap(pcap_file) + +# Retrieve the number of packets in the file +num_packets = len(packets) + +print(f"The number of packets in '{pcap_file}' is: {num_packets}") + + diff --git a/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_1.pcap b/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_1.pcap new file mode 100644 index 00000000..4392ef01 Binary files /dev/null and b/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_1.pcap differ diff --git a/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_2.pcap b/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_2.pcap new file mode 100644 index 00000000..e2935202 Binary files /dev/null and b/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_2.pcap differ diff --git a/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_3.pcap b/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_3.pcap new file mode 100644 index 00000000..ba1ede26 Binary files /dev/null and b/hdhdjshxh/task1/src/PCAP/ay2223_sasp_nmapcatured_3.pcap differ diff --git a/hdhdjshxh/task1/src/Pipfile b/hdhdjshxh/task1/src/Pipfile new file mode 100644 index 00000000..b05735c8 --- /dev/null +++ b/hdhdjshxh/task1/src/Pipfile @@ -0,0 +1,12 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +scapy = "*" + +[dev-packages] + +[requires] +python_version = "3.11" diff --git a/hdhdjshxh/task1/src/Pipfile.lock b/hdhdjshxh/task1/src/Pipfile.lock new file mode 100644 index 00000000..beee2cfb --- /dev/null +++ b/hdhdjshxh/task1/src/Pipfile.lock @@ -0,0 +1,28 @@ +{ + "_meta": { + "hash": { + "sha256": "48a942209e07edced25af57319fa326b1f119473fddb9cb78f4a1e53be218cdc" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "scapy": { + "hashes": [ + "sha256:5b260c2b754fd8d409ba83ee7aee294ecdbb2c235f9f78fe90bc11cb6e5debc2" + ], + "index": "pypi", + "version": "==2.5.0" + } + }, + "develop": {} +} diff --git a/hdhdjshxh/task1/src/README.md b/hdhdjshxh/task1/src/README.md new file mode 100644 index 00000000..921333d1 --- /dev/null +++ b/hdhdjshxh/task1/src/README.md @@ -0,0 +1,7 @@ +# README +```bash +$ pipenv shell + +# inside pipenv shell +$ python ./sasp-part-b-assignment-v1.py +``` diff --git a/hdhdjshxh/task1/src/package.json b/hdhdjshxh/task1/src/package.json new file mode 100644 index 00000000..a3f0e131 --- /dev/null +++ b/hdhdjshxh/task1/src/package.json @@ -0,0 +1,13 @@ +{ + "name": "src", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "npx nodemon --ext py --exec \"./test.sh\"" + }, + "keywords": [], + "author": "", + "license": "ISC" +} \ No newline at end of file diff --git a/hdhdjshxh/task1/src/sasp-part-b-assignment-v1.py b/hdhdjshxh/task1/src/sasp-part-b-assignment-v1.py new file mode 100644 index 00000000..c7bc9fce --- /dev/null +++ b/hdhdjshxh/task1/src/sasp-part-b-assignment-v1.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python3 + +import sqlite3 +from sqlite3 import Error +import tkinter as tk +from tkinter import ttk +from scapy.all import * +from datetime import datetime + +import os +import threading + +# NOTE: look into PCAP for pcap file +PCAP_DIRECTORY = "PCAP" + +# NOTE: global variables for threading +files = [] +pcap_files=[] +pcap_filename = '' + +# NOTE: global variables for result +num_of_packet = 0 +list_of_scanned_port = [] +num_of_scanned_port = 0 +pcap_process_status = 'start' + +# NOTE: initial get all files in the directory +files = os.listdir(PCAP_DIRECTORY) + +# NOTE: Filter files with '.pcap' extension +pcap_files = [file for file in files if file.endswith('.pcap')] + +def handle_pcap_file_select_update(event): + # NOTE: make analyse button when pcap file selected + analysebtn.config(state=tk.ACTIVE) + +def create_connection(db_file): + conn = None + try: + conn = sqlite3.connect(db_file) + except Error as e: + print(e) + return conn + +def select_all_pcaprecords(conn): + cur = conn.cursor() + cur.execute("SELECT * FROM pcap_records") + + rows = cur.fetchall() + return rows + +def open_popup(text_display): + top = tk.Toplevel(mainwindow) + top.geometry("550x250") + top.title("Analysis Results!") + popup_text = tk.Text(top, height=10, width=65,font=('Consolas',10)) + popup_text.grid(row=0,column=0,padx=5,pady=5,sticky=tk.W) + popup_text.insert(tk.END,text_display) + +def callback(event): + filepath = "./outputfiles/" + # get the index of the mouse click + index = event.widget.index("@%s,%s" % (event.x, event.y)) + + # get the indices of all "adj" tags + tag_indices = list(event.widget.tag_ranges('tag')) + + # iterate them pairwise (start and end index) + for start, end in zip(tag_indices[0::2], tag_indices[1::2]): + # check if the tag matches the mouse click index + if event.widget.compare(start, '<=', index) and event.widget.compare(index, '<', end): + # return string between tag start and end + filename = filepath + event.widget.get(start, end) + print(filename) + file1 = open(filename,'r') + lines = file1.readlines() + d = "" + for line in lines: + d += line.strip() + "\n" + + open_popup(d) + +def find_num_of_packet(pcap_filename): + global PCAP_DIRECTORY,num_of_packet + + # Provide the path to your PCAP file + pcap_file = f'{PCAP_DIRECTORY}/{pcap_filename}' + + # Read the PCAP file + packets = rdpcap(pcap_file) + + # return 'num_packets' + num_of_packet = len(packets) + pass + +def count_scanned_port(list_of_scanned_port): + return len(list_of_scanned_port) + +def find_scanned_port(pcap_filename): + global list_of_scanned_port + global num_of_scanned_port + global PCAP_DIRECTORY + + pcap_file = f'{PCAP_DIRECTORY}/{pcap_filename}' + + # Read the PCAP file + packets = rdpcap(pcap_file) + + # Create an empty set to store unique destination ports + scanned_ports = set() + + for packet in packets: + # Check if it's a TCP packet with destination port information + if TCP in packet and packet[TCP].dport not in scanned_ports: + scanned_ports.add(packet[TCP].dport) + + list_of_scanned_port = sorted(scanned_ports) + num_of_scanned_port = count_scanned_port(scanned_ports) + + pass + +def display_to_text(in_data): + displaytext.tag_config("tag",foreground="blue") + displaytext.tag_bind("tag","", callback) + displaytext.insert(tk.END, 'ID' + "\t" + "PCAP Filename" + " " + "Date" + "\t\t\t\t" + "Time" + "\t" + "Output File\n") + displaytext.insert(tk.END, '==' + "\t" + "==========================" + "\t" + "========" + "\t" + "====" + "\t" + "===========\n") + for row in in_data: + displaytext.insert(tk.END, str(row[0]) + "\t" + row[1] + " \t\t\t" + row[2] + "\t" + row[3] + " " + row[4] + "\t") + displaytext.insert(tk.END,row[4],"tag") + displaytext.insert(tk.END,"\n") + + +def clear_text(): + pcap_file_select_cb.set(DEFAULT_COMBOBOX_TEXT) + analysetext.delete(1.0, tk.END) + + clearbtn.config(state=tk.DISABLED) + analysebtn.config(state=tk.DISABLED) + storebtn.config(state=tk.DISABLED) + +def store_to_db(conn): + global pcap_filename + + print(pcap_filename) + + try: + current_date = get_current_date() + current_time = get_current_time() + output_filename = current_date+current_time+'.txt' + + cursor = conn.cursor() + + # cursor.execute("INSERT INTO pcap_records (pcafilename) VALUES (?)", (name)) + cursor.execute('INSERT INTO pcap_records (pcapfilename, date, time, outputfilename) VALUES (?, ?, ?, ?)', (pcap_filename,current_date, current_time, output_filename)) + + # Commit the changes and close the connection + conn.commit() + print('save to db done') + + except: + print('error found during saving to db') + +# TODO: relocate me +thread1 = 0 +thread2 = 0 + +def update_result(): + global pcap_filename + global thread1, thread2 + global num_of_scanned_port, list_of_scanned_port, num_of_packet + + thread1.join() + thread2.join() + + clear_text() + + analysetext.insert(tk.END, f"-- ANALYSIS RESULT --\n") + + analysetext.insert(tk.END, f"File analyzed: {pcap_filename}\n") + + # # NOTES: count number of packets + analysetext.insert(tk.END, f"The number of packets : {num_of_packet}\n") + + # # NOTES: find the ports scanned + analysetext.insert(tk.END, f"Scanned port : {list_of_scanned_port}\n") + + # NOTES: find_num_of_port_scanned + analysetext.insert(tk.END, f"Scanned port : {num_of_scanned_port}\n") + + analysetext.insert(tk.END, f"-- ANALYSIS END --\n") + + + + +def analyse_to_text(): + global num_of_packet + global thread1, thread2 + global pcap_filename + + pcap_filename = pcap_file_select_cb.get() + + # NOTE: seperate thread for process analysis of scanned port and number of packet + thread1 = threading.Thread(target=find_scanned_port, args=(pcap_filename,)) + thread2 = threading.Thread(target=find_num_of_packet, args=(pcap_filename,)) + + # NOTE: start thread + thread1.start() + thread2.start() + + # NOTE: prepare textbox for output + analysetext.tag_config("tag",foreground="blue") + analysetext.tag_bind("tag","", callback) + + # NOTE: show processing file and wait for finish + analysetext.insert(tk.END, f"processing file\n") + + update_result() + + clearbtn.config(state=tk.ACTIVE) + storebtn.config(state=tk.ACTIVE) + + +def get_current_date(): + now = datetime.now() + return now.strftime('%Y%m%d') + +def get_current_time(): + now = datetime.now() + return now.strftime('%H%M%S') + + +def analysispcap(): + pcapFile = getfiletextbox.get() + pcap = rdpcap(pcapFile) + numofpackets = len(pcap) + resultstextbox.insert(tk.END,numofpackets) + +def saveresult(): + pcapFile = getfiletextbox.get() + analysis_date = get_current_date() + analysis_time = get_current_time() + analysis_output = resultstextbox.get("1.0","end-1c") + output_filename = analysis_date + analysis_time + '.txt' + print(pcapFile) + print(analysis_date) + print(analysis_time) + print(analysis_output) + print(output_filename) + +def refresh_pcap_file_list(Noneevent): + global files + global pcap_files + + files = os.listdir(directory) + pcap_files = [file for file in files if file.endswith('.pcap')] +# ====================== Main Start Here ===================================================== + +database = r"saspdemo.db" +conn = create_connection(database) +rows = select_all_pcaprecords(conn) +data = [] + +for row in rows: + data.append([row[0], row[1], row[2], row[3], row[4]]) + +mainwindow = tk.Tk() +mainwindow.geometry("1620x600") +mainwindow.title("SASP Part B Assignment AY2223 - PCAP Analysis By Chan Tai Man") + +tabControl = ttk.Notebook(mainwindow) + +tab1 = ttk.Frame(tabControl) +tab2 = ttk.Frame(tabControl) + +tabControl.add(tab1, text ='Network Traffic Analysis') +tabControl.add(tab2, text ='History') +tabControl.pack(expand = 1, fill ="both") + +# # =================== tab 1 GUI Layout ======================================================== + +# # Options + +# NOTE: this is combobox for pcap file list +DEFAULT_COMBOBOX_TEXT = 'Select a pcap file' +pcap_file_select_cb = ttk.Combobox(tab1, width=30, textvariable=tk.StringVar()) +pcap_file_select_cb.set(DEFAULT_COMBOBOX_TEXT) +pcap_file_select_cb.grid(row=0,column=0, padx=5,pady=10,sticky=tk.W) +pcap_file_select_cb.bind('<>', handle_pcap_file_select_update) + +pcap_file_select_cb['values'] = pcap_files +pcap_file_select_cb['state'] = 'readonly' + +# NOTE: this is "REFRESH" button +refreshbtn = tk.Button(tab1, text="REFRESH", fg='blue', width=10, command=lambda:refresh_pcap_file_list(None)) +refreshbtn.grid(row=0,column=0, padx=500,pady=10,sticky=tk.W) + +# NOTE: this is "ANALYSE" button +analysebtn = tk.Button(tab1, text="ANALYSE", fg='blue', width=10, command=lambda:analyse_to_text()) +analysebtn.grid(row=0,column=0, padx=700,pady=10,sticky=tk.W) +analysebtn.config(state=tk.DISABLED) + +# NOTE: this is "CLEAR" button +clearbtn = tk.Button(tab1, text="CLEAR", fg='blue', width=10, command=lambda:clear_text()) +clearbtn.grid(row=0,column=0, padx=900,pady=10,sticky=tk.W) +clearbtn.config(state=tk.DISABLED) + +# NOTE: store to database +# NOTE: Store all the information +# NOTE: (e.g. date and time, PCAP filename, and the results of items) +# NOTE: related to analysing PCAP files in the SQLite database. +storebtn = tk.Button(tab1, text="STORE", fg='blue', width=10, command=lambda:store_to_db(conn)) +storebtn.grid(row=0,column=0, padx=1100,pady=10,sticky=tk.W) +storebtn.config(state=tk.DISABLED) + +# NOTE: result window +analysetext = tk.Text(tab1,height=10, width=100,font=('Consolas',10)) +analysetext.grid(row=2,column=0,padx=5,pady=20,sticky=tk.W) + +# # =================== tab 2 GUI Layout ======================================================== + +displaybtn = tk.Button(tab2, text="DISPLAY", fg='blue', width=20, command=lambda:display_to_text(data)) +displaybtn.grid(row=0,column=0, padx=5,pady=10,sticky=tk.W) + +displaytext = tk.Text(tab2,height=10, width=100,font=('Consolas',10)) +displaytext.grid(row=2,column=0,padx=5,pady=5,sticky=tk.W) + +# TODO: resume me +mainwindow.mainloop() + +print('program ended') diff --git a/hdhdjshxh/task1/src/saspdemo.db b/hdhdjshxh/task1/src/saspdemo.db new file mode 100644 index 00000000..7b799d34 Binary files /dev/null and b/hdhdjshxh/task1/src/saspdemo.db differ diff --git a/hdhdjshxh/task1/src/test.sh b/hdhdjshxh/task1/src/test.sh new file mode 100644 index 00000000..1b01e776 --- /dev/null +++ b/hdhdjshxh/task1/src/test.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -ex + +find . |entr -c -s "python ./sasp-part-b-assignment-v1.py" +# pipenv run python ./sasp-part-b-assignment-v1.py diff --git a/hdhdjshxh/task1/test_threading.py b/hdhdjshxh/task1/test_threading.py new file mode 100644 index 00000000..5568bcc8 --- /dev/null +++ b/hdhdjshxh/task1/test_threading.py @@ -0,0 +1,34 @@ +import threading + +helloworld = "start" + +def task1(name): + print(f"Task 1 executing with name: {name}") + return f"Hello, {name}!" + +def task2(age): + global helloworld + helloworld = 'done' + print(f"Task 2 executing with age: {age}") + return f"You are {age} years old." + +# Create thread objects for each task, passing arguments as a tuple +thread1 = threading.Thread(target=task1, args=("John",)) +thread2 = threading.Thread(target=task2, args=(25,)) + +# Start the threads +thread1.start() +thread2.start() + +# Wait for both threads to finish execution +thread1.join() +thread2.join() + +# Retrieve the return values from each thread +result_task1 = thread1.result if hasattr(thread1, 'result') else None +result_task2 = thread2.result if hasattr(thread2, 'result') else None + +print("All tasks completed") +print("Result from Task 1:", result_task1) +print("Result from Task 2:", result_task2) +print(helloworld) diff --git a/hdhdjshxh/task2/Assignment.pdf b/hdhdjshxh/task2/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/Assignment.pdf differ diff --git a/hdhdjshxh/task2/Assignment.py b/hdhdjshxh/task2/Assignment.py new file mode 100644 index 00000000..7328c897 --- /dev/null +++ b/hdhdjshxh/task2/Assignment.py @@ -0,0 +1,195 @@ +import tkinter +import tkinter.messagebox +import tkinter.scrolledtext + + +###class starts +class HDinfo(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + +class Applicant(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + #Set Personal Info Method + + #Set HD Info Method + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + + ### + + + def is_complete(self): + + ### + #Write your coding here + + ### + + return True + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + + ### + #Write your coding here + + ### + + def is_complete(self): + ### + #Write your coding here + + ### + return True + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + + ### + + def show(self): #Show Button method + pass#remove it when you complete the codings + ### + #Write your coding here + + ### + + + + + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0001-1/Assignment.pdf b/hdhdjshxh/task2/_backup/draft0001-1/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/_backup/draft0001-1/Assignment.pdf differ diff --git a/hdhdjshxh/task2/_backup/draft0001-1/src/Assignment.py b/hdhdjshxh/task2/_backup/draft0001-1/src/Assignment.py new file mode 100644 index 00000000..0dfa1230 --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0001-1/src/Assignment.py @@ -0,0 +1,202 @@ +import tkinter +import tkinter.messagebox +import tkinter.scrolledtext +from tkinter import * + +###class starts +class HDinfo(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + +class Applicant(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + #Set Personal Info Method + + #Set HD Info Method + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + + lbl_name = tkinter.Label(frm_content, text="Employee Name") + lbl_name.grid(row=0, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=0, column=1, columnspan=2, sticky="nsew") + + ### + + + def is_complete(self): + + ### + #Write your coding here + + ### + + return True + + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + + ### + #Write your coding here + + ### + + def is_complete(self): + ### + #Write your coding here + + ### + return True + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + + ### + + def show(self): #Show Button method + pass#remove it when you complete the codings + ### + #Write your coding here + + ### + + + + + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0001-1/src/test.bat b/hdhdjshxh/task2/_backup/draft0001-1/src/test.bat new file mode 100644 index 00000000..55fdd17f --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0001-1/src/test.bat @@ -0,0 +1,10 @@ + +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python ./Assignment.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/_backup/draft0001/Assignment.pdf b/hdhdjshxh/task2/_backup/draft0001/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/_backup/draft0001/Assignment.pdf differ diff --git a/hdhdjshxh/task2/_backup/draft0001/src/Assignment.py b/hdhdjshxh/task2/_backup/draft0001/src/Assignment.py new file mode 100644 index 00000000..7328c897 --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0001/src/Assignment.py @@ -0,0 +1,195 @@ +import tkinter +import tkinter.messagebox +import tkinter.scrolledtext + + +###class starts +class HDinfo(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + +class Applicant(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + #Set Personal Info Method + + #Set HD Info Method + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + + ### + + + def is_complete(self): + + ### + #Write your coding here + + ### + + return True + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + + ### + #Write your coding here + + ### + + def is_complete(self): + ### + #Write your coding here + + ### + return True + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + + ### + + def show(self): #Show Button method + pass#remove it when you complete the codings + ### + #Write your coding here + + ### + + + + + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0002/Assignment.pdf b/hdhdjshxh/task2/_backup/draft0002/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/_backup/draft0002/Assignment.pdf differ diff --git a/hdhdjshxh/task2/_backup/draft0002/src/Assignment.py b/hdhdjshxh/task2/_backup/draft0002/src/Assignment.py new file mode 100644 index 00000000..9005c1ea --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0002/src/Assignment.py @@ -0,0 +1,286 @@ +import tkinter +import tkinter.ttk + +import tkinter.messagebox +import tkinter.scrolledtext +from tkinter import * + +###class starts +class HDinfo(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + +class Applicant(): + pass#remove it when you complete the codings + + #constructor __init__ + + # __str__ method + + #Set Personal Info Method + + #Set HD Info Method + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + + lbl_name = tkinter.Label(frm_content, text="Applicant Name" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Applicant Email" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + + # ask genden with radio button, male or female + lbl_gender = tkinter.Label(frm_content, text="Gender" , anchor="w", justify="left", width=20) + lbl_gender.grid(row=row, column=0) + rad_male = tkinter.Radiobutton(frm_content, text="Male") + rad_male.grid(row=row, column=1) + rad_female = tkinter.Radiobutton(frm_content, text="Female") + rad_female.grid(row=row, column=2) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Date of Birth" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Apply Programme" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + + # combobox for apply programme + lst_programme=[] + monthchoosen = tkinter.ttk.Combobox(frm_content, textvariable=lst_programme, values=lst_programme, ) + monthchoosen.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + + + row += 1 + + + + ### + + + def is_complete(self): + + ### + #Write your coding here + + ### + + return True + + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Institution Name", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Programme Title", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="GPA", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Expected Graduation Year", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + ent_name = tkinter.Entry(frm_content) + ent_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + ### + + def is_complete(self): + ### + #Write your coding here + + ### + return True + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + # textbox for summary + txt_summary = tkinter.Text(frm_content, height=10) + txt_summary.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(1,1), padx=(1,1)) + row += 1 + + + # right justify button with text "show" + btn_show = tkinter.Button(frm_base, text="Show", anchor=tkinter.E) + btn_show.pack(side=tkinter.RIGHT) + + # btn_show = tkinter.Button(frm_content, text="Show", anchor=tkinter.E) + # btn_show.grid(row=row, column=2, pady=(10,10), padx=(10,10)) + + + + ### + + def show(self): #Show Button method + pass#remove it when you complete the codings + ### + #Write your coding here + + ### + + + + + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0002/src/test.bat b/hdhdjshxh/task2/_backup/draft0002/src/test.bat new file mode 100644 index 00000000..55fdd17f --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0002/src/test.bat @@ -0,0 +1,10 @@ + +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python ./Assignment.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/_backup/draft0003/Assignment.pdf b/hdhdjshxh/task2/_backup/draft0003/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/_backup/draft0003/Assignment.pdf differ diff --git a/hdhdjshxh/task2/_backup/draft0003/src/Assignment.py b/hdhdjshxh/task2/_backup/draft0003/src/Assignment.py new file mode 100644 index 00000000..ca73281a --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0003/src/Assignment.py @@ -0,0 +1,369 @@ +import tkinter +import tkinter.ttk + +import tkinter.messagebox +import tkinter.scrolledtext +from tkinter import * + +###class starts +class HDinfo(): + # Attributes: + # institutionName– a non-public string to store the HD institution name of the applicant. + # programmeTitle – a non-public string to store the HD programme name of the applicant. + # gpa – a non-public double to store the HD GPA of the applicant. + # expectedGradeYear– a non-public int to store the Expected HD Graduation Year of the applicant. + + # Methods: + # init – initialize all attributes in HDinfo object. It is a Parameterized constructor. + # str – return a string containing the Attributes of HDinfo object. This method is used to display in Summary ScrolledText. + + #constructor __init__ + def __init__(self, institutionName="",programmeTitle="", gpa="",expectedGraYear="" ): + pass + + # __str__ method + def __str__(): + print("helloworld string method") + pass + + +class Applicant(): + # Attributes: + # name – a non-public string to store the name of the applicant. + # email – a non-public string to store the email of the applicant. + # gender – a non-public string to store the gender of the applicant. + # dateOfBirth – a non-public string to store the applicant date of birth. + # applyDegreeProgramme – a non-public string to store the applicant selected + # degree programme + # hdInfo– a non-public HDinfo(self-defined class) to store the applicant Higher + # Diploma information + + # Methods: + # init – initialize all attributes in Applicant object. It is a Parameterized constructor. + # setPeronalInfo – setter method to set the name, email, gender, dateOfBirth, applyDegreeProgrmme into the Applicant object. + # setHDinfo – setter method to set the HDinfo object into the Applicant object. + # str – return a string containing the Attributes of this Applicant. This function is used to display in Summary ScrolledText. + + #constructor __init__ + def __init__( self, name="", email="",gender="", dateOfBirth="",applyDegreeProgramme="",hdInfo = HDinfo() ): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + pass + + # Set Personal Info Method + def setPeronalInfo(self, name, email, gender,dateOfBirth, applyDegreeProgramme ): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + # Set HD Info Method + def setHDInfo(self, hd): + pass + + # __str__ method + def __str__(self): + return "helloworld string method" + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + + + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Applicant Name" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_name = tkinter.Entry(frm_content) + self.ent_applicant_name.insert(0, "applicant name") + self.ent_applicant_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Applicant Email" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_email = tkinter.Entry(frm_content) + self.ent_applicant_email.insert(0, "123@123.com") + self.ent_applicant_email.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + # ask genden with radio button, male or female + self.gender_select = tkinter.StringVar(value="Male") + + lbl_gender = tkinter.Label(frm_content, text="Gender" , anchor="w", justify="left", width=20) + lbl_gender.grid(row=row, column=0) + + rad_male = tkinter.Radiobutton(frm_content, variable=self.gender_select,text="Male",value="Male") + rad_male.grid(row=row, column=1) + + rad_female = tkinter.Radiobutton(frm_content, variable=self.gender_select,text="Female",value="Female") + rad_female.grid(row=row, column=2) + + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Date of Birth" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_DOB = tkinter.Entry(frm_content) + self.ent_applicant_DOB.insert(0, "14/02/2024") + self.ent_applicant_DOB.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Apply Programme" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + + # combobox for apply programme + lst_programme=["Bachelor of Science in Cybersecurity" , "Bachelor of Science in Computer Science and AI"] + self.applicant_programme = tkinter.ttk.Combobox(frm_content, textvariable=lst_programme, values=lst_programme, ) + self.applicant_programme.current(0) + self.applicant_programme.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + + + ### + + + def is_complete(self): + + ### + #Write your coding here + + entry_valid = True + if self.ent_applicant_name.get() == "": + entry_valid = False + if self.ent_applicant_email.get() == "": + entry_valid = False + if self.ent_applicant_DOB.get() == "": + entry_valid = False + + if (entry_valid): + applicant.setPeronalInfo( + self.ent_applicant_name.get(), + self.ent_applicant_email.get(), + self.gender_select.get(), + self.ent_applicant_DOB.get(), + self.applicant_programme.get() + ) + return True + + return False + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Institution Name", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_institution_name = tkinter.Entry(frm_content) + self.ent_institution_name.insert(0, "TYIVE") + self.ent_institution_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Programme Title", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_programme_title = tkinter.Entry(frm_content) + self.ent_programme_title.insert(0, "HD") + self.ent_programme_title.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="GPA", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_GPA = tkinter.Entry(frm_content) + self.ent_GPA.insert(0, "1") + self.ent_GPA.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Expected Graduation Year", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.expected_grad_year = tkinter.Entry(frm_content) + self.expected_grad_year.insert(0, "2025") + self.expected_grad_year.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + ### + + def is_complete(self): + ### + #Write your coding here + + entry_valid = True + if self.ent_institution_name.get() == "": + entry_valid = False + if self.ent_programme_title.get() == "": + entry_valid = False + if self.ent_GPA.get() == "": + entry_valid = False + + hd = HDinfo( + self.ent_institution_name.get(), + self.ent_programme_title.get(), + self.ent_GPA.get(), + self.expected_grad_year.get() + ) + + if (entry_valid): + applicant.setHDInfo(hd) + return True + + return False + + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + # textbox for summary + self.txt_summary = tkinter.Text(frm_content, height=10) + self.txt_summary.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(1,1), padx=(1,1)) + row += 1 + + + # right justify button with text "show" + btn_show = tkinter.Button(frm_base, text="Show", anchor=tkinter.E) + btn_show.pack(side=tkinter.RIGHT) + + # tkinter bind button click + btn_show.bind("", self.show) + + ### + + def show(self, _ ): #Show Button method + ### + #Write your coding here + self.txt_summary.insert(tkinter.INSERT, str(applicant)) + ### + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0003/src/test.bat b/hdhdjshxh/task2/_backup/draft0003/src/test.bat new file mode 100644 index 00000000..55fdd17f --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0003/src/test.bat @@ -0,0 +1,10 @@ + +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python ./Assignment.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/_backup/draft0004/Assignment.pdf b/hdhdjshxh/task2/_backup/draft0004/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/_backup/draft0004/Assignment.pdf differ diff --git a/hdhdjshxh/task2/_backup/draft0004/src/Assignment.py b/hdhdjshxh/task2/_backup/draft0004/src/Assignment.py new file mode 100644 index 00000000..b2b8dd28 --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0004/src/Assignment.py @@ -0,0 +1,379 @@ +import tkinter +import tkinter.ttk + +import tkinter.messagebox +import tkinter.scrolledtext +from tkinter import * + +###class starts +class HDinfo(): + # Attributes: + # institutionName– a non-public string to store the HD institution name of the applicant. + # programmeTitle – a non-public string to store the HD programme name of the applicant. + # gpa – a non-public double to store the HD GPA of the applicant. + # expectedGradeYear– a non-public int to store the Expected HD Graduation Year of the applicant. + + # Methods: + # init – initialize all attributes in HDinfo object. It is a Parameterized constructor. + # str – return a string containing the Attributes of HDinfo object. This method is used to display in Summary ScrolledText. + + #constructor __init__ + def __init__(self, institutionName="",programmeTitle="", gpa="",expectedGraYear="" ): + pass + + # __str__ method + def __str__(): + print("helloworld string method") + pass + + +class Applicant(): + # Attributes: + # name – a non-public string to store the name of the applicant. + # email – a non-public string to store the email of the applicant. + # gender – a non-public string to store the gender of the applicant. + # dateOfBirth – a non-public string to store the applicant date of birth. + # applyDegreeProgramme – a non-public string to store the applicant selected + # degree programme + # hdInfo– a non-public HDinfo(self-defined class) to store the applicant Higher + # Diploma information + + # Methods: + # init – initialize all attributes in Applicant object. It is a Parameterized constructor. + # setPeronalInfo – setter method to set the name, email, gender, dateOfBirth, applyDegreeProgrmme into the Applicant object. + # setHDinfo – setter method to set the HDinfo object into the Applicant object. + # str – return a string containing the Attributes of this Applicant. This function is used to display in Summary ScrolledText. + + #constructor __init__ + def __init__( self, name="", email="",gender="", dateOfBirth="",applyDegreeProgramme="",hdInfo = HDinfo() ): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + pass + + # Set Personal Info Method + def setPeronalInfo(self, name, email, gender,dateOfBirth, applyDegreeProgramme ): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + # Set HD Info Method + def setHDInfo(self, hd): + pass + + # __str__ method + def __str__(self): + return """ +Applicant Name: Ben +Applicant Email: ben@vtc.edu.hk +Gender: Male +Date of Birth: 2004/03/13 +Apply Degree Programme: Bachelor of Science in Computer Science and AI +Higher Diploma Information: +Institution Name: IVE(Chai Wan) +Programme Title: HD in AI and Smart Technology +GPA: 3.8 +Expected Graduation Year: 2025 +""".strip() + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + + + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Applicant Name" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_name = tkinter.Entry(frm_content) + self.ent_applicant_name.insert(0, "Ben") + self.ent_applicant_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Applicant Email" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_email = tkinter.Entry(frm_content) + self.ent_applicant_email.insert(0, "ben@vtc.edu.hk") + self.ent_applicant_email.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + # ask genden with radio button, male or female + self.gender_select = tkinter.StringVar(value="Male") + + lbl_gender = tkinter.Label(frm_content, text="Gender" , anchor="w", justify="left", width=20) + lbl_gender.grid(row=row, column=0) + + rad_male = tkinter.Radiobutton(frm_content, variable=self.gender_select,text="Male",value="Male") + rad_male.grid(row=row, column=1) + + rad_female = tkinter.Radiobutton(frm_content, variable=self.gender_select,text="Female",value="Female") + rad_female.grid(row=row, column=2) + + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Date of Birth" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_DOB = tkinter.Entry(frm_content) + self.ent_applicant_DOB.insert(0, "2004/03/13") + self.ent_applicant_DOB.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Apply Programme" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + + # combobox for apply programme + lst_programme=["Bachelor of Science in Cybersecurity" , "Bachelor of Science in Computer Science and AI"] + self.applicant_programme = tkinter.ttk.Combobox(frm_content, textvariable=lst_programme, values=lst_programme, ) + self.applicant_programme.current(0) + self.applicant_programme.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + + + ### + + + def is_complete(self): + + ### + #Write your coding here + + entry_valid = True + if self.ent_applicant_name.get() == "": + entry_valid = False + if self.ent_applicant_email.get() == "": + entry_valid = False + if self.ent_applicant_DOB.get() == "": + entry_valid = False + + if (entry_valid): + applicant.setPeronalInfo( + self.ent_applicant_name.get(), + self.ent_applicant_email.get(), + self.gender_select.get(), + self.ent_applicant_DOB.get(), + self.applicant_programme.get() + ) + return True + + return False + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Institution Name", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_institution_name = tkinter.Entry(frm_content) + self.ent_institution_name.insert(0, "IVE(Chai Wan)") + self.ent_institution_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Programme Title", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_programme_title = tkinter.Entry(frm_content) + self.ent_programme_title.insert(0, "HD in AI and Smart Technology") + self.ent_programme_title.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="GPA", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_GPA = tkinter.Entry(frm_content) + self.ent_GPA.insert(0, "3.8") + self.ent_GPA.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Expected Graduation Year", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.expected_grad_year = tkinter.Entry(frm_content) + self.expected_grad_year.insert(0, "2025") + self.expected_grad_year.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + ### + + def is_complete(self): + ### + #Write your coding here + + entry_valid = True + if self.ent_institution_name.get() == "": + entry_valid = False + if self.ent_programme_title.get() == "": + entry_valid = False + if self.ent_GPA.get() == "": + entry_valid = False + + hd = HDinfo( + self.ent_institution_name.get(), + self.ent_programme_title.get(), + self.ent_GPA.get(), + self.expected_grad_year.get() + ) + + if (entry_valid): + applicant.setHDInfo(hd) + return True + + return False + + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + # textbox for summary + self.txt_summary = tkinter.Text(frm_content, height=12) + self.txt_summary.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(1,1), padx=(1,1)) + row += 1 + + # right justify button with text "show" + btn_show = tkinter.Button(frm_base, text="Show", anchor=tkinter.E) + btn_show.pack(side=tkinter.RIGHT) + + # tkinter bind button click + btn_show.bind("", self.show) + + ### + + def show(self, _ ): #Show Button method + ### + #Write your coding here + self.txt_summary.insert(tkinter.INSERT, str(applicant)) + ### + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0004/src/test.bat b/hdhdjshxh/task2/_backup/draft0004/src/test.bat new file mode 100644 index 00000000..55fdd17f --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0004/src/test.bat @@ -0,0 +1,10 @@ + +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python ./Assignment.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/_backup/draft0005/Assignment.pdf b/hdhdjshxh/task2/_backup/draft0005/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/_backup/draft0005/Assignment.pdf differ diff --git a/hdhdjshxh/task2/_backup/draft0005/src/Assignment.py b/hdhdjshxh/task2/_backup/draft0005/src/Assignment.py new file mode 100644 index 00000000..553f8c4d --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0005/src/Assignment.py @@ -0,0 +1,395 @@ +import tkinter +import tkinter.ttk + +import tkinter.messagebox +import tkinter.scrolledtext +from tkinter import * + +###class starts +class HDinfo(): + # Attributes: + # institutionName– a non-public string to store the HD institution name of the applicant. + # programmeTitle – a non-public string to store the HD programme name of the applicant. + # gpa – a non-public double to store the HD GPA of the applicant. + # expectedGradeYear– a non-public int to store the Expected HD Graduation Year of the applicant. + + # Methods: + # init – initialize all attributes in HDinfo object. It is a Parameterized constructor. + # str – return a string containing the Attributes of HDinfo object. This method is used to display in Summary ScrolledText. + + #constructor __init__ + def __init__(self, institutionName="",programmeTitle="", gpa="",expectedGraYear="" ): + self.institutionName = institutionName + self.programmeTitle = programmeTitle + self.gpa = gpa + self.expectedGraYear = expectedGraYear + pass + + # __str__ method + def __str__(self): + return """ +Higher Diploma Information: +Institution Name: {hd_institution_name} +Programme Title: {hd_programme_title} +GPA: {hd_gpa} +Expected Graduation Year: {expectedGraYear} +""".strip().format( + hd_institution_name=self.institutionName, + hd_programme_title=self.programmeTitle, + hd_gpa=self.gpa, + expectedGraYear=self.expectedGraYear, +) + + +class Applicant(): + # Attributes: + # name – a non-public string to store the name of the applicant. + # email – a non-public string to store the email of the applicant. + # gender – a non-public string to store the gender of the applicant. + # dateOfBirth – a non-public string to store the applicant date of birth. + # applyDegreeProgramme – a non-public string to store the applicant selected + # degree programme + # hdInfo– a non-public HDinfo(self-defined class) to store the applicant Higher + # Diploma information + + # Methods: + # init – initialize all attributes in Applicant object. It is a Parameterized constructor. + # setPeronalInfo – setter method to set the name, email, gender, dateOfBirth, applyDegreeProgrmme into the Applicant object. + # setHDinfo – setter method to set the HDinfo object into the Applicant object. + # str – return a string containing the Attributes of this Applicant. This function is used to display in Summary ScrolledText. + + #constructor __init__ + def __init__( self, name="", email="",gender="", dateOfBirth="",applyDegreeProgramme="",hdInfo = HDinfo() ): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + pass + + # Set Personal Info Method + def setPeronalInfo(self, name, email, gender,dateOfBirth, applyDegreeProgramme ): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + # Set HD Info Method + def setHDInfo(self, hd): + self.hd = hd + pass + + # __str__ method + def __str__(self): + return """ +Applicant Name: {applicant_name} +Applicant Email: {applicant_email} +Gender: {gender} +Date of Birth: {DOB} +Apply Degree Programme: {applyDegreeProgramme} +""".strip().format( + applicant_name=self.name, + applicant_email=self.email, + gender=self.gender, + DOB=self.dateOfBirth, + applyDegreeProgramme=self.applyDegreeProgramme, +) +'\n'+ self.hd.__str__() + + +applicant = Applicant() +###class ends + + +###Tkinter starts + + +#Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + + + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Applicant Name" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_name = tkinter.Entry(frm_content) + self.ent_applicant_name.insert(0, "Ben") + self.ent_applicant_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Applicant Email" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_email = tkinter.Entry(frm_content) + self.ent_applicant_email.insert(0, "ben@vtc.edu.hk") + self.ent_applicant_email.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + # ask genden with radio button, male or female + self.gender_select = tkinter.StringVar(value="Male") + + lbl_gender = tkinter.Label(frm_content, text="Gender" , anchor="w", justify="left", width=20) + lbl_gender.grid(row=row, column=0) + + rad_male = tkinter.Radiobutton(frm_content, variable=self.gender_select,text="Male",value="Male") + rad_male.grid(row=row, column=1) + + rad_female = tkinter.Radiobutton(frm_content, variable=self.gender_select,text="Female",value="Female") + rad_female.grid(row=row, column=2) + + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Date of Birth" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_applicant_DOB = tkinter.Entry(frm_content) + self.ent_applicant_DOB.insert(0, "2004/03/13") + self.ent_applicant_DOB.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Apply Programme" , anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + + # combobox for apply programme + lst_programme=["Bachelor of Science in Cybersecurity" , "Bachelor of Science in Computer Science and AI"] + self.applicant_programme = tkinter.ttk.Combobox(frm_content, textvariable=lst_programme, values=lst_programme, ) + self.applicant_programme.current(0) + self.applicant_programme.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + + + ### + + + def is_complete(self): + + ### + #Write your coding here + + entry_valid = True + if self.ent_applicant_name.get() == "": + entry_valid = False + if self.ent_applicant_email.get() == "": + entry_valid = False + if self.ent_applicant_DOB.get() == "": + entry_valid = False + + if (entry_valid): + applicant.setPeronalInfo( + self.ent_applicant_name.get(), + self.ent_applicant_email.get(), + self.gender_select.get(), + self.ent_applicant_DOB.get(), + self.applicant_programme.get() + ) + return True + + return False + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + lbl_name = tkinter.Label(frm_content, text="Institution Name", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_institution_name = tkinter.Entry(frm_content) + self.ent_institution_name.insert(0, "IVE(Chai Wan)") + self.ent_institution_name.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Programme Title", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_programme_title = tkinter.Entry(frm_content) + self.ent_programme_title.insert(0, "HD in AI and Smart Technology") + self.ent_programme_title.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="GPA", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_GPA = tkinter.Entry(frm_content) + self.ent_GPA.insert(0, "3.8") + self.ent_GPA.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + + lbl_name = tkinter.Label(frm_content, text="Expected Graduation Year", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.expected_grad_year = tkinter.Entry(frm_content) + self.expected_grad_year.insert(0, "2025") + self.expected_grad_year.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(10,10), padx=(10,10)) + row += 1 + ### + + def is_complete(self): + ### + #Write your coding here + + entry_valid = True + if self.ent_institution_name.get() == "": + entry_valid = False + if self.ent_programme_title.get() == "": + entry_valid = False + if self.ent_GPA.get() == "": + entry_valid = False + + hd = HDinfo( + self.ent_institution_name.get(), + self.ent_programme_title.get(), + self.ent_GPA.get(), + self.expected_grad_year.get() + ) + + if (entry_valid): + applicant.setHDInfo(hd) + return True + + return False + + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + #Summary Output + ### + #Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2,weight=1) + + # textbox for summary + self.txt_summary = tkinter.Text(frm_content, height=12) + self.txt_summary.grid(row=row, column=1, columnspan=2, sticky="nsew", pady=(1,1), padx=(1,1)) + row += 1 + + # right justify button with text "show" + btn_show = tkinter.Button(frm_base, text="Show", anchor=tkinter.E) + btn_show.pack(side=tkinter.RIGHT) + + # tkinter bind button click + btn_show.bind("", self.show) + + ### + + def show(self, _ ): #Show Button method + ### + #Write your coding here + self.txt_summary.insert(tkinter.INSERT, str(applicant)) + ### + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button(frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button(frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +###Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/_backup/draft0005/src/test.bat b/hdhdjshxh/task2/_backup/draft0005/src/test.bat new file mode 100644 index 00000000..55fdd17f --- /dev/null +++ b/hdhdjshxh/task2/_backup/draft0005/src/test.bat @@ -0,0 +1,10 @@ + +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python ./Assignment.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/_poc/Switch Between Different Page Frames/test.py b/hdhdjshxh/task2/_poc/Switch Between Different Page Frames/test.py new file mode 100644 index 00000000..ababf49b --- /dev/null +++ b/hdhdjshxh/task2/_poc/Switch Between Different Page Frames/test.py @@ -0,0 +1,135 @@ +import tkinter as tk +from tkinter import ttk + + +LARGEFONT =("Verdana", 35) + +class tkinterApp(tk.Tk): + + # __init__ function for class tkinterApp + def __init__(self, *args, **kwargs): + + # __init__ function for class Tk + tk.Tk.__init__(self, *args, **kwargs) + + # creating a container + container = tk.Frame(self) + container.pack(side = "top", fill = "both", expand = True) + + container.grid_rowconfigure(0, weight = 1) + container.grid_columnconfigure(0, weight = 1) + + # initializing frames to an empty array + self.frames = {} + + # iterating through a tuple consisting + # of the different page layouts + for F in (StartPage, Page1, Page2): + + frame = F(container, self) + + # initializing frame of that object from + # startpage, page1, page2 respectively with + # for loop + self.frames[F] = frame + + frame.grid(row = 0, column = 0, sticky ="nsew") + + self.show_frame(StartPage) + + # to display the current frame passed as + # parameter + def show_frame(self, cont): + frame = self.frames[cont] + frame.tkraise() + +# first window frame startpage + +class StartPage(tk.Frame): + def __init__(self, parent, controller): + tk.Frame.__init__(self, parent) + + # label of frame Layout 2 + label = ttk.Label(self, text ="Startpage", font = LARGEFONT) + + # putting the grid in its place by using + # grid + label.grid(row = 0, column = 4, padx = 10, pady = 10) + + button1 = ttk.Button(self, text ="Page 1", + command = lambda : controller.show_frame(Page1)) + + # putting the button in its place by + # using grid + button1.grid(row = 1, column = 1, padx = 10, pady = 10) + + ## button to show frame 2 with text layout2 + button2 = ttk.Button(self, text ="Page 2", + command = lambda : controller.show_frame(Page2)) + + # putting the button in its place by + # using grid + button2.grid(row = 2, column = 1, padx = 10, pady = 10) + + + + +# second window frame page1 +class Page1(tk.Frame): + + def __init__(self, parent, controller): + + tk.Frame.__init__(self, parent) + label = ttk.Label(self, text ="Page 1", font = LARGEFONT) + label.grid(row = 0, column = 4, padx = 10, pady = 10) + + # button to show frame 2 with text + # layout2 + button1 = ttk.Button(self, text ="StartPage", + command = lambda : controller.show_frame(StartPage)) + + # putting the button in its place + # by using grid + button1.grid(row = 1, column = 1, padx = 10, pady = 10) + + # button to show frame 2 with text + # layout2 + button2 = ttk.Button(self, text ="Page 2", + command = lambda : controller.show_frame(Page2)) + + # putting the button in its place by + # using grid + button2.grid(row = 2, column = 1, padx = 10, pady = 10) + + + + +# third window frame page2 +class Page2(tk.Frame): + def __init__(self, parent, controller): + tk.Frame.__init__(self, parent) + label = ttk.Label(self, text ="Page 2", font = LARGEFONT) + label.grid(row = 0, column = 4, padx = 10, pady = 10) + + # button to show frame 2 with text + # layout2 + button1 = ttk.Button(self, text ="Page 1", + command = lambda : controller.show_frame(Page1)) + + # putting the button in its place by + # using grid + button1.grid(row = 1, column = 1, padx = 10, pady = 10) + + # button to show frame 3 with text + # layout3 + button2 = ttk.Button(self, text ="Startpage", + command = lambda : controller.show_frame(StartPage)) + + # putting the button in its place by + # using grid + button2.grid(row = 2, column = 1, padx = 10, pady = 10) + + +# Driver Code +app = tkinterApp() +app.mainloop() diff --git a/hdhdjshxh/task2/_poc/grid/looptest.bat b/hdhdjshxh/task2/_poc/grid/looptest.bat new file mode 100644 index 00000000..af1ec335 --- /dev/null +++ b/hdhdjshxh/task2/_poc/grid/looptest.bat @@ -0,0 +1,9 @@ +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python test.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/_poc/grid/test.py b/hdhdjshxh/task2/_poc/grid/test.py new file mode 100644 index 00000000..f469b26b --- /dev/null +++ b/hdhdjshxh/task2/_poc/grid/test.py @@ -0,0 +1,32 @@ +from tkinter import * +from tkinter import ttk + +root = Tk() + +content = ttk.Frame(root) +frame = ttk.Frame(content, borderwidth=5, relief="ridge", width=200, height=100) +namelbl = ttk.Label(content, text="Name") +name = ttk.Entry(content) + +onevar = BooleanVar(value=True) +twovar = BooleanVar(value=False) +threevar = BooleanVar(value=True) + +one = ttk.Checkbutton(content, text="One", variable=onevar, onvalue=True) +two = ttk.Checkbutton(content, text="Two", variable=twovar, onvalue=True) +three = ttk.Checkbutton(content, text="Three", variable=threevar, onvalue=True) +ok = ttk.Button(content, text="Okay") +cancel = ttk.Button(content, text="Cancel") + +content.grid(column=0, row=0) +frame.grid(column=0, row=0, columnspan=3, rowspan=2) +namelbl.grid(column=3, row=0, columnspan=2) + +name.grid(column=3, row=1, columnspan=2) +one.grid(column=0, row=3) +two.grid(column=1, row=3) +three.grid(column=2, row=3) +ok.grid(column=3, row=3) +cancel.grid(column=4, row=3) + +root.mainloop() diff --git a/hdhdjshxh/task2/backup.bat b/hdhdjshxh/task2/backup.bat new file mode 100644 index 00000000..d863548a --- /dev/null +++ b/hdhdjshxh/task2/backup.bat @@ -0,0 +1 @@ +node ./backup.js \ No newline at end of file diff --git a/hdhdjshxh/task2/backup.js b/hdhdjshxh/task2/backup.js new file mode 100644 index 00000000..08074612 --- /dev/null +++ b/hdhdjshxh/task2/backup.js @@ -0,0 +1,59 @@ +const execSync = require('child_process').execSync +const fs = require('fs') +const path = require('path') + +// Function to get all subdirectories of a given directory +function getDirectories(srcPath, excludeDirs) { + return fs + .readdirSync(srcPath) + .filter(file => !excludeDirs.includes(file) && fs.lstatSync(path.join(srcPath, file)).isDirectory()) + .map(name => path.join(srcPath, name)) +} + +// Get current working directory +const cwd = process.cwd() + +// Path to app-head directory +const appHeadDir = path.join(cwd, 'project') + +// Check if app-head exists +if (!fs.existsSync(appHeadDir)) { + console.error(`Error: ${appHeadDir} does not exist.`) + process.exit(1) +} + +// Execute reset.bat scripts +try { + // execSync(`cmd /c "cd ${appHeadDir} && scripts\\reset.bat"`, { stdio: 'inherit' }); +} catch (err) { + console.error(`Error executing reset.bat script: ${err.message}`) + process.exit(1) +} + +// Define excluded directories +const excludedDirs = ['.next', 'node_modules', '.git', 'volumes'] + +// Copy app-head directory and its contents to a new directory with an increasing number suffix +let maxNum = 0 +const directories = getDirectories(cwd, excludedDirs) +for (const dir of directories) { + const match = dir.match(/^.+draft(\d+)$/) + if (match) { + const num = parseInt(match[1], 10) + if (num > maxNum) { + maxNum = num + } + } +} + +var zerofilled = ('0000' + (maxNum + 1)).slice(-4) +const targetDir = path.join(cwd, `draft${zerofilled}`) +fs.mkdirSync(targetDir) + +// Copy app-head directory and its contents to targetDir, excluding specified directories +fs.cpSync(appHeadDir, targetDir, { + filter: src => !excludedDirs.includes(path.basename(src)), + recursive: true +}) + +console.log(`Successfully copied ${appHeadDir} to ${targetDir}.`) diff --git a/hdhdjshxh/task2/digest.md b/hdhdjshxh/task2/digest.md new file mode 100644 index 00000000..2dab2c76 --- /dev/null +++ b/hdhdjshxh/task2/digest.md @@ -0,0 +1,10 @@ +# Assignment + +## Objective + +This assignment is to implement the IT University Application System using Object Oriented Programming Techniques. Your coding must be able to show concepts such as Abstraction,Encapsulation, Inheritance and Polymorphism. Your program must be able to do the following: + +1. Add applicant personal information, selected degree programme, higher diploma information. +2. Preview the records. + +## Requirements of the Assignment diff --git a/hdhdjshxh/task2/meta.md b/hdhdjshxh/task2/meta.md new file mode 100644 index 00000000..fc3bb95e --- /dev/null +++ b/hdhdjshxh/task2/meta.md @@ -0,0 +1,26 @@ +--- +tags: [python, tkinter, ITP4459, windows, docker] +--- + +# task2 + +## Balance history + +### quotation + +- HKD1600 + +### payment history + +HKD 300 deposit paid + +## NOTES + +## Objective + +This assignment is to implement the IT University Application System using Object Oriented Programming Techniques. Your coding must be able to show concepts such as Abstraction,Encapsulation, Inheritance and Polymorphism. Your program must be able to do the following: + +1. Add applicant personal information, selected degree programme, higher diploma information. +2. Preview the records. + +## Requirements of the Assignment diff --git a/hdhdjshxh/task2/notes/4459_ass.docx b/hdhdjshxh/task2/notes/4459_ass.docx new file mode 100644 index 00000000..0f54cf14 Binary files /dev/null and b/hdhdjshxh/task2/notes/4459_ass.docx differ diff --git a/hdhdjshxh/task2/notes/Lab_01a - Object and Class_Answers.docx b/hdhdjshxh/task2/notes/Lab_01a - Object and Class_Answers.docx new file mode 100644 index 00000000..c1a4d823 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_01a - Object and Class_Answers.docx differ diff --git a/hdhdjshxh/task2/notes/Lab_01b - Object and Class_Answers.docx b/hdhdjshxh/task2/notes/Lab_01b - Object and Class_Answers.docx new file mode 100644 index 00000000..4a40fb98 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_01b - Object and Class_Answers.docx differ diff --git a/hdhdjshxh/task2/notes/Lab_02a - Initializer_Answers.doc b/hdhdjshxh/task2/notes/Lab_02a - Initializer_Answers.doc new file mode 100644 index 00000000..fd8e938d Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_02a - Initializer_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_02b - Initializer_Answers.doc b/hdhdjshxh/task2/notes/Lab_02b - Initializer_Answers.doc new file mode 100644 index 00000000..be9a0fa5 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_02b - Initializer_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_03a - Instance and Static Members_Answers.doc b/hdhdjshxh/task2/notes/Lab_03a - Instance and Static Members_Answers.doc new file mode 100644 index 00000000..ee797628 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_03a - Instance and Static Members_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_03b - Instance and Static Members_Answers.doc b/hdhdjshxh/task2/notes/Lab_03b - Instance and Static Members_Answers.doc new file mode 100644 index 00000000..eaf837ac Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_03b - Instance and Static Members_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_04a - Inheritance_Answers.doc b/hdhdjshxh/task2/notes/Lab_04a - Inheritance_Answers.doc new file mode 100644 index 00000000..816379a5 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_04a - Inheritance_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_04b - Inheritance_Answers.doc b/hdhdjshxh/task2/notes/Lab_04b - Inheritance_Answers.doc new file mode 100644 index 00000000..a6035d1a Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_04b - Inheritance_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_05a - Abstract Class_Answers (1).doc b/hdhdjshxh/task2/notes/Lab_05a - Abstract Class_Answers (1).doc new file mode 100644 index 00000000..ad923462 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_05a - Abstract Class_Answers (1).doc differ diff --git a/hdhdjshxh/task2/notes/Lab_05b - Abstract Class.doc b/hdhdjshxh/task2/notes/Lab_05b - Abstract Class.doc new file mode 100644 index 00000000..5e05ef9f Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_05b - Abstract Class.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_06a - Database Connection_Answers (1).doc b/hdhdjshxh/task2/notes/Lab_06a - Database Connection_Answers (1).doc new file mode 100644 index 00000000..96a805aa Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_06a - Database Connection_Answers (1).doc differ diff --git a/hdhdjshxh/task2/notes/Lab_06b - Database Connection_Answers.doc b/hdhdjshxh/task2/notes/Lab_06b - Database Connection_Answers.doc new file mode 100644 index 00000000..f6db3c73 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_06b - Database Connection_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_07a - Tkinter_Answers.doc b/hdhdjshxh/task2/notes/Lab_07a - Tkinter_Answers.doc new file mode 100644 index 00000000..46626d89 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_07a - Tkinter_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_07b - Tkinter_Answers.doc b/hdhdjshxh/task2/notes/Lab_07b - Tkinter_Answers.doc new file mode 100644 index 00000000..b850af6e Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_07b - Tkinter_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_07c - Tkinter_Answers.doc b/hdhdjshxh/task2/notes/Lab_07c - Tkinter_Answers.doc new file mode 100644 index 00000000..a05a9053 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_07c - Tkinter_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_08a - Web Scraping_Answers.doc b/hdhdjshxh/task2/notes/Lab_08a - Web Scraping_Answers.doc new file mode 100644 index 00000000..f6e589b7 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_08a - Web Scraping_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_08b - Web Scraping_Answers.doc b/hdhdjshxh/task2/notes/Lab_08b - Web Scraping_Answers.doc new file mode 100644 index 00000000..48f6c6fb Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_08b - Web Scraping_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_09a - Python Web Framework_Answers.doc b/hdhdjshxh/task2/notes/Lab_09a - Python Web Framework_Answers.doc new file mode 100644 index 00000000..40e5a21b Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_09a - Python Web Framework_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_09b - Python Web Framework_Answers.doc b/hdhdjshxh/task2/notes/Lab_09b - Python Web Framework_Answers.doc new file mode 100644 index 00000000..3ff01633 Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_09b - Python Web Framework_Answers.doc differ diff --git a/hdhdjshxh/task2/notes/Lab_09c - Python Web Framework_Answers.doc b/hdhdjshxh/task2/notes/Lab_09c - Python Web Framework_Answers.doc new file mode 100644 index 00000000..9d38115b Binary files /dev/null and b/hdhdjshxh/task2/notes/Lab_09c - Python Web Framework_Answers.doc differ diff --git a/hdhdjshxh/task2/package.json b/hdhdjshxh/task2/package.json new file mode 100644 index 00000000..d3b0cb65 --- /dev/null +++ b/hdhdjshxh/task2/package.json @@ -0,0 +1,13 @@ +{ + "name": "hdhdjshxh", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "gitUpdate": "git add . && git commit -m\"update hdhdjshxh, task2,\" && git push" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/hdhdjshxh/task2/project/Assignment.pdf b/hdhdjshxh/task2/project/Assignment.pdf new file mode 100644 index 00000000..f62bf228 Binary files /dev/null and b/hdhdjshxh/task2/project/Assignment.pdf differ diff --git a/hdhdjshxh/task2/project/doc/HD_information_window.png b/hdhdjshxh/task2/project/doc/HD_information_window.png new file mode 100644 index 00000000..e669a90f --- /dev/null +++ b/hdhdjshxh/task2/project/doc/HD_information_window.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d9707b00bda920c785db51dc80637ebbdad59a761093ca145a4b4d958eb1152 +size 8786 diff --git a/hdhdjshxh/task2/project/doc/Personal_info_window.png b/hdhdjshxh/task2/project/doc/Personal_info_window.png new file mode 100644 index 00000000..00b93771 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/Personal_info_window.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6983e9d4dde32887e21ad298dfe3a1593d3d0d96980fbdeb4515c2bb311bea96 +size 9514 diff --git a/hdhdjshxh/task2/project/doc/Pipfile b/hdhdjshxh/task2/project/doc/Pipfile new file mode 100644 index 00000000..22a2f354 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/Pipfile @@ -0,0 +1,12 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +markdown2docx = "*" + +[dev-packages] + +[requires] +python_version = "3.12" diff --git a/hdhdjshxh/task2/project/doc/Pipfile.lock b/hdhdjshxh/task2/project/doc/Pipfile.lock new file mode 100644 index 00000000..d7879425 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/Pipfile.lock @@ -0,0 +1,312 @@ +{ + "_meta": { + "hash": { + "sha256": "ce7bc21caf64cf9ad732d9869c89e2cf568c1b1d036c73753a58b09450611617" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.12" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "beautifulsoup4": { + "hashes": [ + "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", + "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed" + ], + "markers": "python_full_version >= '3.6.0'", + "version": "==4.12.3" + }, + "bs4": { + "hashes": [ + "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925", + "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc" + ], + "version": "==0.0.2" + }, + "lxml": { + "hashes": [ + "sha256:04ab5415bf6c86e0518d57240a96c4d1fcfc3cb370bb2ac2a732b67f579e5a04", + "sha256:057cdc6b86ab732cf361f8b4d8af87cf195a1f6dc5b0ff3de2dced242c2015e0", + "sha256:058a1308914f20784c9f4674036527e7c04f7be6fb60f5d61353545aa7fcb739", + "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a", + "sha256:0a15438253b34e6362b2dc41475e7f80de76320f335e70c5528b7148cac253a1", + "sha256:0c3f67e2aeda739d1cc0b1102c9a9129f7dc83901226cc24dd72ba275ced4218", + "sha256:0e7259016bc4345a31af861fdce942b77c99049d6c2107ca07dc2bba2435c1d9", + "sha256:0ed777c1e8c99b63037b91f9d73a6aad20fd035d77ac84afcc205225f8f41188", + "sha256:0f5d65c39f16717a47c36c756af0fb36144069c4718824b7533f803ecdf91138", + "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585", + "sha256:11a04306fcba10cd9637e669fd73aa274c1c09ca64af79c041aa820ea992b637", + "sha256:1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe", + "sha256:1c5bb205e9212d0ebddf946bc07e73fa245c864a5f90f341d11ce7b0b854475d", + "sha256:1f7785f4f789fdb522729ae465adcaa099e2a3441519df750ebdccc481d961a1", + "sha256:200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095", + "sha256:21c2e6b09565ba5b45ae161b438e033a86ad1736b8c838c766146eff8ceffff9", + "sha256:2213afee476546a7f37c7a9b4ad4d74b1e112a6fafffc9185d6d21f043128c81", + "sha256:27aa20d45c2e0b8cd05da6d4759649170e8dfc4f4e5ef33a34d06f2d79075d57", + "sha256:2a66bf12fbd4666dd023b6f51223aed3d9f3b40fef06ce404cb75bafd3d89536", + "sha256:2c9d147f754b1b0e723e6afb7ba1566ecb162fe4ea657f53d2139bbf894d050a", + "sha256:2ddfe41ddc81f29a4c44c8ce239eda5ade4e7fc305fb7311759dd6229a080052", + "sha256:31e9a882013c2f6bd2f2c974241bf4ba68c85eba943648ce88936d23209a2e01", + "sha256:3249cc2989d9090eeac5467e50e9ec2d40704fea9ab72f36b034ea34ee65ca98", + "sha256:3545039fa4779be2df51d6395e91a810f57122290864918b172d5dc7ca5bb433", + "sha256:394ed3924d7a01b5bd9a0d9d946136e1c2f7b3dc337196d99e61740ed4bc6fe1", + "sha256:3a6b45da02336895da82b9d472cd274b22dc27a5cea1d4b793874eead23dd14f", + "sha256:3a74c4f27167cb95c1d4af1c0b59e88b7f3e0182138db2501c353555f7ec57f4", + "sha256:3d0c3dd24bb4605439bf91068598d00c6370684f8de4a67c2992683f6c309d6b", + "sha256:3dbe858ee582cbb2c6294dc85f55b5f19c918c2597855e950f34b660f1a5ede6", + "sha256:3dc773b2861b37b41a6136e0b72a1a44689a9c4c101e0cddb6b854016acc0aa8", + "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5", + "sha256:3f7765e69bbce0906a7c74d5fe46d2c7a7596147318dbc08e4a2431f3060e306", + "sha256:417d14450f06d51f363e41cace6488519038f940676ce9664b34ebf5653433a5", + "sha256:44f6c7caff88d988db017b9b0e4ab04934f11e3e72d478031efc7edcac6c622f", + "sha256:491755202eb21a5e350dae00c6d9a17247769c64dcf62d8c788b5c135e179dc4", + "sha256:4951e4f7a5680a2db62f7f4ab2f84617674d36d2d76a729b9a8be4b59b3659be", + "sha256:52421b41ac99e9d91934e4d0d0fe7da9f02bfa7536bb4431b4c05c906c8c6919", + "sha256:530e7c04f72002d2f334d5257c8a51bf409db0316feee7c87e4385043be136af", + "sha256:533658f8fbf056b70e434dff7e7aa611bcacb33e01f75de7f821810e48d1bb66", + "sha256:5670fb70a828663cc37552a2a85bf2ac38475572b0e9b91283dc09efb52c41d1", + "sha256:56c22432809085b3f3ae04e6e7bdd36883d7258fcd90e53ba7b2e463efc7a6af", + "sha256:58278b29cb89f3e43ff3e0c756abbd1518f3ee6adad9e35b51fb101c1c1daaec", + "sha256:588008b8497667f1ddca7c99f2f85ce8511f8f7871b4a06ceede68ab62dff64b", + "sha256:59565f10607c244bc4c05c0c5fa0c190c990996e0c719d05deec7030c2aa8289", + "sha256:59689a75ba8d7ffca577aefd017d08d659d86ad4585ccc73e43edbfc7476781a", + "sha256:5aea8212fb823e006b995c4dda533edcf98a893d941f173f6c9506126188860d", + "sha256:5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102", + "sha256:5ca1e8188b26a819387b29c3895c47a5e618708fe6f787f3b1a471de2c4a94d9", + "sha256:5d077bc40a1fe984e1a9931e801e42959a1e6598edc8a3223b061d30fbd26bbc", + "sha256:5d5792e9b3fb8d16a19f46aa8208987cfeafe082363ee2745ea8b643d9cc5b45", + "sha256:5dd1537e7cc06efd81371f5d1a992bd5ab156b2b4f88834ca852de4a8ea523fa", + "sha256:5ea7b6766ac2dfe4bcac8b8595107665a18ef01f8c8343f00710b85096d1b53a", + "sha256:622020d4521e22fb371e15f580d153134bfb68d6a429d1342a25f051ec72df1c", + "sha256:627402ad8dea044dde2eccde4370560a2b750ef894c9578e1d4f8ffd54000461", + "sha256:644df54d729ef810dcd0f7732e50e5ad1bd0a135278ed8d6bcb06f33b6b6f708", + "sha256:64641a6068a16201366476731301441ce93457eb8452056f570133a6ceb15fca", + "sha256:64c2baa7774bc22dd4474248ba16fe1a7f611c13ac6123408694d4cc93d66dbd", + "sha256:6588c459c5627fefa30139be4d2e28a2c2a1d0d1c265aad2ba1935a7863a4913", + "sha256:66bc5eb8a323ed9894f8fa0ee6cb3e3fb2403d99aee635078fd19a8bc7a5a5da", + "sha256:68a2610dbe138fa8c5826b3f6d98a7cfc29707b850ddcc3e21910a6fe51f6ca0", + "sha256:6935bbf153f9a965f1e07c2649c0849d29832487c52bb4a5c5066031d8b44fd5", + "sha256:6992030d43b916407c9aa52e9673612ff39a575523c5f4cf72cdef75365709a5", + "sha256:6a014510830df1475176466b6087fc0c08b47a36714823e58d8b8d7709132a96", + "sha256:6ab833e4735a7e5533711a6ea2df26459b96f9eec36d23f74cafe03631647c41", + "sha256:6cc6ee342fb7fa2471bd9b6d6fdfc78925a697bf5c2bcd0a302e98b0d35bfad3", + "sha256:6cf58416653c5901e12624e4013708b6e11142956e7f35e7a83f1ab02f3fe456", + "sha256:70a9768e1b9d79edca17890175ba915654ee1725975d69ab64813dd785a2bd5c", + "sha256:70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867", + "sha256:71e97313406ccf55d32cc98a533ee05c61e15d11b99215b237346171c179c0b0", + "sha256:7221d49259aa1e5a8f00d3d28b1e0b76031655ca74bb287123ef56c3db92f213", + "sha256:74b28c6334cca4dd704e8004cba1955af0b778cf449142e581e404bd211fb619", + "sha256:764b521b75701f60683500d8621841bec41a65eb739b8466000c6fdbc256c240", + "sha256:78bfa756eab503673991bdcf464917ef7845a964903d3302c5f68417ecdc948c", + "sha256:794f04eec78f1d0e35d9e0c36cbbb22e42d370dda1609fb03bcd7aeb458c6377", + "sha256:79bd05260359170f78b181b59ce871673ed01ba048deef4bf49a36ab3e72e80b", + "sha256:7a7efd5b6d3e30d81ec68ab8a88252d7c7c6f13aaa875009fe3097eb4e30b84c", + "sha256:7c17b64b0a6ef4e5affae6a3724010a7a66bda48a62cfe0674dabd46642e8b54", + "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b", + "sha256:853e074d4931dbcba7480d4dcab23d5c56bd9607f92825ab80ee2bd916edea53", + "sha256:857500f88b17a6479202ff5fe5f580fc3404922cd02ab3716197adf1ef628029", + "sha256:865bad62df277c04beed9478fe665b9ef63eb28fe026d5dedcb89b537d2e2ea6", + "sha256:88e22fc0a6684337d25c994381ed8a1580a6f5ebebd5ad41f89f663ff4ec2885", + "sha256:8b9c07e7a45bb64e21df4b6aa623cb8ba214dfb47d2027d90eac197329bb5e94", + "sha256:8de8f9d6caa7f25b204fc861718815d41cbcf27ee8f028c89c882a0cf4ae4134", + "sha256:8e77c69d5892cb5ba71703c4057091e31ccf534bd7f129307a4d084d90d014b8", + "sha256:9123716666e25b7b71c4e1789ec829ed18663152008b58544d95b008ed9e21e9", + "sha256:958244ad566c3ffc385f47dddde4145088a0ab893504b54b52c041987a8c1863", + "sha256:96323338e6c14e958d775700ec8a88346014a85e5de73ac7967db0367582049b", + "sha256:9676bfc686fa6a3fa10cd4ae6b76cae8be26eb5ec6811d2a325636c460da1806", + "sha256:9b0ff53900566bc6325ecde9181d89afadc59c5ffa39bddf084aaedfe3b06a11", + "sha256:9b9ec9c9978b708d488bec36b9e4c94d88fd12ccac3e62134a9d17ddba910ea9", + "sha256:9c6ad0fbf105f6bcc9300c00010a2ffa44ea6f555df1a2ad95c88f5656104817", + "sha256:9ca66b8e90daca431b7ca1408cae085d025326570e57749695d6a01454790e95", + "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8", + "sha256:a0af35bd8ebf84888373630f73f24e86bf016642fb8576fba49d3d6b560b7cbc", + "sha256:a2b44bec7adf3e9305ce6cbfa47a4395667e744097faed97abb4728748ba7d47", + "sha256:a2dfe7e2473f9b59496247aad6e23b405ddf2e12ef0765677b0081c02d6c2c0b", + "sha256:a55ee573116ba208932e2d1a037cc4b10d2c1cb264ced2184d00b18ce585b2c0", + "sha256:a7baf9ffc238e4bf401299f50e971a45bfcc10a785522541a6e3179c83eabf0a", + "sha256:a8d5c70e04aac1eda5c829a26d1f75c6e5286c74743133d9f742cda8e53b9c2f", + "sha256:a91481dbcddf1736c98a80b122afa0f7296eeb80b72344d7f45dc9f781551f56", + "sha256:ab31a88a651039a07a3ae327d68ebdd8bc589b16938c09ef3f32a4b809dc96ef", + "sha256:abc25c3cab9ec7fcd299b9bcb3b8d4a1231877e425c650fa1c7576c5107ab851", + "sha256:adfb84ca6b87e06bc6b146dc7da7623395db1e31621c4785ad0658c5028b37d7", + "sha256:afbbdb120d1e78d2ba8064a68058001b871154cc57787031b645c9142b937a62", + "sha256:afd5562927cdef7c4f5550374acbc117fd4ecc05b5007bdfa57cc5355864e0a4", + "sha256:b070bbe8d3f0f6147689bed981d19bbb33070225373338df755a46893528104a", + "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c", + "sha256:b560e3aa4b1d49e0e6c847d72665384db35b2f5d45f8e6a5c0072e0283430533", + "sha256:b6241d4eee5f89453307c2f2bfa03b50362052ca0af1efecf9fef9a41a22bb4f", + "sha256:b6787b643356111dfd4032b5bffe26d2f8331556ecb79e15dacb9275da02866e", + "sha256:bcbf4af004f98793a95355980764b3d80d47117678118a44a80b721c9913436a", + "sha256:beb72935a941965c52990f3a32d7f07ce869fe21c6af8b34bf6a277b33a345d3", + "sha256:bf2e2458345d9bffb0d9ec16557d8858c9c88d2d11fed53998512504cd9df49b", + "sha256:c2d35a1d047efd68027817b32ab1586c1169e60ca02c65d428ae815b593e65d4", + "sha256:c38d7b9a690b090de999835f0443d8aa93ce5f2064035dfc48f27f02b4afc3d0", + "sha256:c6f2c8372b98208ce609c9e1d707f6918cc118fea4e2c754c9f0812c04ca116d", + "sha256:c817d420c60a5183953c783b0547d9eb43b7b344a2c46f69513d5952a78cddf3", + "sha256:c8ba129e6d3b0136a0f50345b2cb3db53f6bda5dd8c7f5d83fbccba97fb5dcb5", + "sha256:c94e75445b00319c1fad60f3c98b09cd63fe1134a8a953dcd48989ef42318534", + "sha256:cc4691d60512798304acb9207987e7b2b7c44627ea88b9d77489bbe3e6cc3bd4", + "sha256:cc518cea79fd1e2f6c90baafa28906d4309d24f3a63e801d855e7424c5b34144", + "sha256:cd53553ddad4a9c2f1f022756ae64abe16da1feb497edf4d9f87f99ec7cf86bd", + "sha256:cf22b41fdae514ee2f1691b6c3cdeae666d8b7fa9434de445f12bbeee0cf48dd", + "sha256:d38c8f50ecf57f0463399569aa388b232cf1a2ffb8f0a9a5412d0db57e054860", + "sha256:d3be9b2076112e51b323bdf6d5a7f8a798de55fb8d95fcb64bd179460cdc0704", + "sha256:d4f2cc7060dc3646632d7f15fe68e2fa98f58e35dd5666cd525f3b35d3fed7f8", + "sha256:d7520db34088c96cc0e0a3ad51a4fd5b401f279ee112aa2b7f8f976d8582606d", + "sha256:d793bebb202a6000390a5390078e945bbb49855c29c7e4d56a85901326c3b5d9", + "sha256:da052e7962ea2d5e5ef5bc0355d55007407087392cf465b7ad84ce5f3e25fe0f", + "sha256:dae0ed02f6b075426accbf6b2863c3d0a7eacc1b41fb40f2251d931e50188dad", + "sha256:ddc678fb4c7e30cf830a2b5a8d869538bc55b28d6c68544d09c7d0d8f17694dc", + "sha256:df2e6f546c4df14bc81f9498bbc007fbb87669f1bb707c6138878c46b06f6510", + "sha256:e02c5175f63effbd7c5e590399c118d5db6183bbfe8e0d118bdb5c2d1b48d937", + "sha256:e196a4ff48310ba62e53a8e0f97ca2bca83cdd2fe2934d8b5cb0df0a841b193a", + "sha256:e233db59c8f76630c512ab4a4daf5a5986da5c3d5b44b8e9fc742f2a24dbd460", + "sha256:e32be23d538753a8adb6c85bd539f5fd3b15cb987404327c569dfc5fd8366e85", + "sha256:e3d30321949861404323c50aebeb1943461a67cd51d4200ab02babc58bd06a86", + "sha256:e89580a581bf478d8dcb97d9cd011d567768e8bc4095f8557b21c4d4c5fea7d0", + "sha256:e998e304036198b4f6914e6a1e2b6f925208a20e2042563d9734881150c6c246", + "sha256:ec42088248c596dbd61d4ae8a5b004f97a4d91a9fd286f632e42e60b706718d7", + "sha256:efa7b51824aa0ee957ccd5a741c73e6851de55f40d807f08069eb4c5a26b2baa", + "sha256:f0a1bc63a465b6d72569a9bba9f2ef0334c4e03958e043da1920299100bc7c08", + "sha256:f18a5a84e16886898e51ab4b1d43acb3083c39b14c8caeb3589aabff0ee0b270", + "sha256:f2a9efc53d5b714b8df2b4b3e992accf8ce5bbdfe544d74d5c6766c9e1146a3a", + "sha256:f3bbbc998d42f8e561f347e798b85513ba4da324c2b3f9b7969e9c45b10f6169", + "sha256:f42038016852ae51b4088b2862126535cc4fc85802bfe30dea3500fdfaf1864e", + "sha256:f443cdef978430887ed55112b491f670bba6462cea7a7742ff8f14b7abb98d75", + "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd", + "sha256:f8aca2e3a72f37bfc7b14ba96d4056244001ddcc18382bd0daa087fd2e68a354", + "sha256:f9737bf36262046213a28e789cc82d82c6ef19c85a0cf05e75c670a33342ac2c", + "sha256:fd6037392f2d57793ab98d9e26798f44b8b4da2f2464388588f48ac52c489ea1", + "sha256:feaa45c0eae424d3e90d78823f3828e7dc42a42f21ed420db98da2c4ecf0a2cb", + "sha256:ff097ae562e637409b429a7ac958a20aab237a0378c42dabaa1e3abf2f896e5f", + "sha256:ff46d772d5f6f73564979cd77a4fffe55c916a05f3cb70e7c9c0590059fb29ef" + ], + "markers": "python_version >= '3.6'", + "version": "==5.2.1" + }, + "markdown2": { + "hashes": [ + "sha256:18ceb56590da77f2c22382e55be48c15b3c8f0c71d6398def387275e6c347a9f", + "sha256:855bde5cbcceb9beda7c80efdf7f406c23e6079172c497fcfce22fdce998e892" + ], + "markers": "python_version >= '3.5' and python_version < '4'", + "version": "==2.4.13" + }, + "markdown2docx": { + "hashes": [ + "sha256:026504ec82b59b9de2641366157fe11d5f3c4781b28cf6422460126dbbec7472", + "sha256:a3a54f75be046e662630c7f2eb570d45cc98ada9892f17e84583db24c10a7510" + ], + "index": "pypi", + "version": "==0.1.0" + }, + "pillow": { + "hashes": [ + "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c", + "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2", + "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb", + "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d", + "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa", + "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3", + "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1", + "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a", + "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd", + "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8", + "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999", + "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599", + "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936", + "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375", + "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d", + "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b", + "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60", + "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572", + "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3", + "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced", + "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f", + "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b", + "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19", + "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f", + "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d", + "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383", + "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795", + "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355", + "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57", + "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09", + "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b", + "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462", + "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf", + "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f", + "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a", + "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad", + "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9", + "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d", + "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45", + "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994", + "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d", + "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338", + "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463", + "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451", + "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591", + "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c", + "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd", + "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32", + "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9", + "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf", + "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5", + "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828", + "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3", + "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5", + "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2", + "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b", + "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2", + "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475", + "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3", + "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb", + "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef", + "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015", + "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002", + "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170", + "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84", + "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57", + "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f", + "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27", + "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a" + ], + "markers": "python_version >= '3.8'", + "version": "==10.3.0" + }, + "python-docx": { + "hashes": [ + "sha256:5829b722141cf1ab79aedf0c34d9fe9924b29764584c0f2164eb2b02dcdf17c9", + "sha256:bac9773278098a1ddc43a52d84e22f5909c4a3080a624530b3ecb3771b07c6cd" + ], + "markers": "python_version >= '3.7'", + "version": "==1.1.0" + }, + "soupsieve": { + "hashes": [ + "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", + "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5" + }, + "typing-extensions": { + "hashes": [ + "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", + "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + ], + "markers": "python_version >= '3.8'", + "version": "==4.11.0" + } + }, + "develop": {} +} diff --git a/hdhdjshxh/task2/project/doc/conv.bat b/hdhdjshxh/task2/project/doc/conv.bat new file mode 100644 index 00000000..a003aab7 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/conv.bat @@ -0,0 +1 @@ +python ./to_docx.py diff --git a/hdhdjshxh/task2/project/doc/result_1.png b/hdhdjshxh/task2/project/doc/result_1.png new file mode 100644 index 00000000..fd57afdd --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efdc9090336c988b4d39c0f31873a5b8ce84563758cef44bc0bbb823b1d7b521 +size 14052 diff --git a/hdhdjshxh/task2/project/doc/result_10.png b/hdhdjshxh/task2/project/doc/result_10.png new file mode 100644 index 00000000..112b468a --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1b8be86463e34ed658720beb1a36eb87c3df18e43097d292beb114f411f0949 +size 13358 diff --git a/hdhdjshxh/task2/project/doc/result_10_1.png b/hdhdjshxh/task2/project/doc/result_10_1.png new file mode 100644 index 00000000..54d94589 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_10_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9303220c2902fe992682b3891302ee64b3214c75ac61187c9103c2ceb159c865 +size 13712 diff --git a/hdhdjshxh/task2/project/doc/result_11.png b/hdhdjshxh/task2/project/doc/result_11.png new file mode 100644 index 00000000..b0e1c688 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_11.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85f3eaee242bbc46e9913bc69e70f1e148de60c9fb3b733d915dbfa9526db24a +size 12886 diff --git a/hdhdjshxh/task2/project/doc/result_11_1.png b/hdhdjshxh/task2/project/doc/result_11_1.png new file mode 100644 index 00000000..53c9d10f --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_11_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19599ff085725a3de518022f1ca9687be6cde8184de1dd2ca03b4c842f48b277 +size 13533 diff --git a/hdhdjshxh/task2/project/doc/result_12.png b/hdhdjshxh/task2/project/doc/result_12.png new file mode 100644 index 00000000..e39add20 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_12.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7b383571763bcf80725a5d930e083fb45163e819bb9d81a223fdd328083acd0 +size 12081 diff --git a/hdhdjshxh/task2/project/doc/result_12_1.png b/hdhdjshxh/task2/project/doc/result_12_1.png new file mode 100644 index 00000000..ef5f6177 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_12_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0644d18c1e2ae6ed6ed989da7e8d05e98a361147317477d42ffc55e04bc29e5f +size 12995 diff --git a/hdhdjshxh/task2/project/doc/result_13.png b/hdhdjshxh/task2/project/doc/result_13.png new file mode 100644 index 00000000..34bb480a --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_13.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c29c56b398e7b4238c6dfbed9bc56896556e5b9dffae8777acd4a0a5ee43bfa2 +size 9234 diff --git a/hdhdjshxh/task2/project/doc/result_13_1.png b/hdhdjshxh/task2/project/doc/result_13_1.png new file mode 100644 index 00000000..1808fa69 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_13_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b3c05e0361e662722a3cebf9473199d1976eeff9520d0d873d8ec213aa984ff +size 8477 diff --git a/hdhdjshxh/task2/project/doc/result_13_2.png b/hdhdjshxh/task2/project/doc/result_13_2.png new file mode 100644 index 00000000..e471292b --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_13_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:330d07353dfc5824cb98076a9c211fb23089d26d862fe946b90c0ffd81b6707a +size 13186 diff --git a/hdhdjshxh/task2/project/doc/result_14.png b/hdhdjshxh/task2/project/doc/result_14.png new file mode 100644 index 00000000..3b0fda21 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_14.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d71c109183bf1608e3f8ed66aaf691af85381cbae5bb8d5b1b5849ad3e524e04 +size 9692 diff --git a/hdhdjshxh/task2/project/doc/result_14_1.png b/hdhdjshxh/task2/project/doc/result_14_1.png new file mode 100644 index 00000000..14dc2dc0 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_14_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7016443f33ad88a99f9480910d47fe163908b8850d767541def09e18633ee9b5 +size 8914 diff --git a/hdhdjshxh/task2/project/doc/result_14_2.png b/hdhdjshxh/task2/project/doc/result_14_2.png new file mode 100644 index 00000000..6a8a1f0b --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_14_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f3d54fbaf36125bd4bc3d68293717eebd6221bfe51f6d7e528084a808a7bffd +size 13579 diff --git a/hdhdjshxh/task2/project/doc/result_1_1.png b/hdhdjshxh/task2/project/doc/result_1_1.png new file mode 100644 index 00000000..b813fb35 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_1_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:183a393240e9fa13699376450e6c447b37088d538e9f4d9f6e30313458655d1a +size 13744 diff --git a/hdhdjshxh/task2/project/doc/result_2.png b/hdhdjshxh/task2/project/doc/result_2.png new file mode 100644 index 00000000..55d4548a --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:717694351b561ba6ee0961c5b85c2f7ad374b72454bcad22895511dad696de7c +size 13415 diff --git a/hdhdjshxh/task2/project/doc/result_2_1.png b/hdhdjshxh/task2/project/doc/result_2_1.png new file mode 100644 index 00000000..9d2dbf3a --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_2_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9cde0e1e28b2592a67fdac5ab4059d4ea609ea28b15abbd4d0ff27648f20f68 +size 13028 diff --git a/hdhdjshxh/task2/project/doc/result_3.png b/hdhdjshxh/task2/project/doc/result_3.png new file mode 100644 index 00000000..7c45d006 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25867422b73e5a38d613be9e28bda258a331ede7345f1e398c19954e8b64792e +size 14202 diff --git a/hdhdjshxh/task2/project/doc/result_3_1.png b/hdhdjshxh/task2/project/doc/result_3_1.png new file mode 100644 index 00000000..7673ee28 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_3_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c52743cbdae31802000d7d6006410d1160a57a6b563c88798bb1e73cb01ee37e +size 14565 diff --git a/hdhdjshxh/task2/project/doc/result_4.png b/hdhdjshxh/task2/project/doc/result_4.png new file mode 100644 index 00000000..20bfe632 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:daebccfb44af99507d0de3f1726272b11e728db7855d3214c798878abe115f4b +size 12971 diff --git a/hdhdjshxh/task2/project/doc/result_4_1.png b/hdhdjshxh/task2/project/doc/result_4_1.png new file mode 100644 index 00000000..3b3c9036 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_4_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f561836adae8385b9887d088bff5adcca2723d5c16a734ce63cbc00c9cf6de1e +size 12847 diff --git a/hdhdjshxh/task2/project/doc/result_5.png b/hdhdjshxh/task2/project/doc/result_5.png new file mode 100644 index 00000000..e9adcccb --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8db4d52dcd1fe5639c7c46b7d12156f5773f9fbd22152c9795547d2494ac5aca +size 12800 diff --git a/hdhdjshxh/task2/project/doc/result_5_1.png b/hdhdjshxh/task2/project/doc/result_5_1.png new file mode 100644 index 00000000..00f6855a --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_5_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa4721bd6f44e139f58c5264dfe413405d76e1796d47b64de8adb6e1a02c3499 +size 12841 diff --git a/hdhdjshxh/task2/project/doc/result_6.png b/hdhdjshxh/task2/project/doc/result_6.png new file mode 100644 index 00000000..5a775392 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_6.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e69f3641e52af518a2aaddeb195dbc1cfe2b49f12c4dee6414a3a0a34c1801b6 +size 13137 diff --git a/hdhdjshxh/task2/project/doc/result_6_1.png b/hdhdjshxh/task2/project/doc/result_6_1.png new file mode 100644 index 00000000..ebf9384d --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_6_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e9e89009c2efcbed8b6b18d582d8ecb59ddd75e17b7b5d6239b435fa0f4cf81 +size 12258 diff --git a/hdhdjshxh/task2/project/doc/result_7.png b/hdhdjshxh/task2/project/doc/result_7.png new file mode 100644 index 00000000..27bc6bd8 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_7.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:050333546d838d4009047a08ffc5c949f8cb4f698c0aca5f87852e67664f09b7 +size 12278 diff --git a/hdhdjshxh/task2/project/doc/result_7_1.png b/hdhdjshxh/task2/project/doc/result_7_1.png new file mode 100644 index 00000000..39203e4e --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_7_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ebf32c0aa1a8e9bc75883150215a23b8bb51fda87f59a0333f11faab0ab38dc +size 12264 diff --git a/hdhdjshxh/task2/project/doc/result_8_1.png b/hdhdjshxh/task2/project/doc/result_8_1.png new file mode 100644 index 00000000..289536b0 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_8_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9daaf23bb351a23ce9ab22b42376ed898c1dd447120bed73e1aa1f9eb185987 +size 9449 diff --git a/hdhdjshxh/task2/project/doc/result_8_2.png b/hdhdjshxh/task2/project/doc/result_8_2.png new file mode 100644 index 00000000..eec2626c --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_8_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9b98d6f09784502988e307160db6b6ae69a5c90644dd41da3f9651851d1993c +size 8816 diff --git a/hdhdjshxh/task2/project/doc/result_8_3.png b/hdhdjshxh/task2/project/doc/result_8_3.png new file mode 100644 index 00000000..d4990a70 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_8_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ab2d594bf8f36d2e7749a17a500fbe2993e790d2be2c33b6cd67045454c2c22 +size 4780 diff --git a/hdhdjshxh/task2/project/doc/result_8_4.png b/hdhdjshxh/task2/project/doc/result_8_4.png new file mode 100644 index 00000000..50e4420d --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_8_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea922f941df0380fed1c8832cfae4efc04795c073011f4f72aa70aec9c9bb2dd +size 13505 diff --git a/hdhdjshxh/task2/project/doc/result_9.png b/hdhdjshxh/task2/project/doc/result_9.png new file mode 100644 index 00000000..30fbc966 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_9.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6493fbac098a473714bdf274982479dd985d185a7701a2f6c5377fbe64b63bae +size 13953 diff --git a/hdhdjshxh/task2/project/doc/result_9_1.png b/hdhdjshxh/task2/project/doc/result_9_1.png new file mode 100644 index 00000000..42f7febb --- /dev/null +++ b/hdhdjshxh/task2/project/doc/result_9_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:501176dbfc8da6d0d8791dc823fdd0f04efec7ee8199199f1bb9dea03b158557 +size 15177 diff --git a/hdhdjshxh/task2/project/doc/summary_window.png b/hdhdjshxh/task2/project/doc/summary_window.png new file mode 100644 index 00000000..bcaa9869 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/summary_window.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb4ac26445233eb12f43f29135e5716240a9fff5aae0682aaf6442f0d39c7d65 +size 13333 diff --git a/hdhdjshxh/task2/project/doc/test - Copy.docx b/hdhdjshxh/task2/project/doc/test - Copy.docx new file mode 100644 index 00000000..ad363263 Binary files /dev/null and b/hdhdjshxh/task2/project/doc/test - Copy.docx differ diff --git a/hdhdjshxh/task2/project/doc/test copy.md b/hdhdjshxh/task2/project/doc/test copy.md new file mode 100644 index 00000000..f138e97e --- /dev/null +++ b/hdhdjshxh/task2/project/doc/test copy.md @@ -0,0 +1,24 @@ +# TEST plan + +### Gui + +1. Validation on the input data and display appropriate error messages + +1. Test Plan with test cases and test results. + +| ID | Test Case Name | Procedure | Expected Output | Result | screen capture | +| --- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------- | +| 1 | Missing "Applicant Name" | 1. leave "applicant name" field empty.
1. Click "Next" button | The error MessageBox appears "name cannot empty."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_1.png)
![](../doc/result_1_1.png) | +| 2 | Missing "Applicant Email" | 1. leave "applicant email" field empty.
1. Click "Next" button | The error MessageBox appears "email field cannot empty."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_2.png)
![](../doc/result_2_1.png) | +| 3 | Missing "Date of Birth" | 1. leave "date of birth" field empty.
1. Click "Next" button | The error MessageBox appears "dob field cannot empty."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_3.png)
![](../doc/result_3_1.png) | +| 4 | Missing Institution Name | 1. leave "Institution Name" field empty
1. Click "Next" button | The error MessageBox appears "Please enter all required information."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_4.png)
![](../doc/result_4_1.png) | +| 5 | Missing Programme Title | 1. leave "Programme Title" field empty
1. Click "Next" button | The error MessageBox appears "Please enter all required information."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_5.png)
![](../doc/result_5_1.png) | +| 6 | Missing GPA | 1. leave "GPA" field empty
1. Click "Next" button | The error MessageBox appears "Please enter all required information."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_6.png)
![](../doc/result_6_1.png) | +| 7 | Missing Expected Graduation Year | 1. leave "Expected Graduation Year" field empty
1. Click "Next" button | The error MessageBox appears "Please enter all required information."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_7.png)
![](../doc/result_7_1.png) | +| 8 | Showing summary if all input field fullfilled | 1. filling all required information in "Personal Information"
1. clici "Next" button
1. Filling all required information in"Higher Diploma Information" windows.
1. Click "Next" button
1. click "show" button to show summary | finally the summary window showing information in the page inputted before | Pass/Fail | ![](../doc/result_8_1.png)
![](../doc/result_8_2.png)
![](../doc/result_8_3.png)
![](../doc/result_8_4.png) | +| 9 | Date of birth should be in the past | 1. enter a day after today to the "date of birth" field
1. click next button | The error MessageBox appears "DOB: the day entered is latter than today."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_9.png)
![](../doc/result_9_1.png) | +| 10 | email entered should be valid | 1. enter an invalid email e.g. "ankitrai326.com"
1. click "next" button | The error MessageBox appears "email format error, it should be email."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_10.png)
![](../doc/result_10_1.png) | +| 11 | GPA should be a number / decimal | 1. enter a non numeric value into "GPA" field
1. Click "Next" button | The error MessageBox appears "GPA field should be a number."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_11.png)
![](../doc/result_11_1.png) | +| 12 | Expected graduation year should be in future | 1. enter a day in the past in "Graduation year" field
1. Click "Next" button | The error MessageBox appears "Expected graduation year should be after current year."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_12.png)
![](../doc/result_12_1.png) | +| 13 | female appliciant | 1. select female in applicant gender field
1. Click "Next" button | The error MessageBox appears "Expected graduation year should be after current year."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_13.png)
![](../doc/result_13_1.png)
![](../doc/result_13_2.png) | +| 14 | "Bachelor of Science in Computer Science and AI" in apply programme | 1. select female in applicant gender field
1. Click "Next" button | The error MessageBox appears "Expected graduation year should be after current year."
The error MessageBox appears "Please enter all required information." | Pass/Fail | ![](../doc/result_14.png)
![](../doc/result_14_1.png)
![](../doc/result_14_2.png) | diff --git a/hdhdjshxh/task2/project/doc/test.csv b/hdhdjshxh/task2/project/doc/test.csv new file mode 100644 index 00000000..e03b6842 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/test.csv @@ -0,0 +1,15 @@ +ID , Test Case Name , Procedure , Expected Output , Result , screen capture , +1," Missing ""Applicant Name"" "," 1. leave ""applicant name"" field empty.
1. Click ""Next"" button "," The error MessageBox appears ""name cannot empty.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_1.png)
![](../doc/result_1_1.png) , +2," Missing ""Applicant Email"" "," 1. leave ""applicant email"" field empty.
1. Click ""Next"" button "," The error MessageBox appears ""email field cannot empty.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_2.png)
![](../doc/result_2_1.png) , +3," Missing ""Date of Birth"" "," 1. leave ""date of birth"" field empty.
1. Click ""Next"" button "," The error MessageBox appears ""dob field cannot empty.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_3.png)
![](../doc/result_3_1.png) , +4, Missing Institution Name ," 1. leave ""Institution Name"" field empty
1. Click ""Next"" button "," The error MessageBox appears ""Please enter all required information.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_4.png)
![](../doc/result_4_1.png) , +5, Missing Programme Title ," 1. leave ""Programme Title"" field empty
1. Click ""Next"" button "," The error MessageBox appears ""Please enter all required information.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_5.png)
![](../doc/result_5_1.png) , +6, Missing GPA ," 1. leave ""GPA"" field empty
1. Click ""Next"" button "," The error MessageBox appears ""Please enter all required information.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_6.png)
![](../doc/result_6_1.png) , +7, Missing Expected Graduation Year ," 1. leave ""Expected Graduation Year"" field empty
1. Click ""Next"" button "," The error MessageBox appears ""Please enter all required information.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_7.png)
![](../doc/result_7_1.png) , +8, Showing summary if all input field fullfilled ," 1. filling all required information in ""Personal Information""
1. clici ""Next"" button
1. Filling all required information in""Higher Diploma Information"" windows.
1. Click ""Next"" button
1. click ""show"" button to show summary ", finally the summary window showing information in the page inputted before , Pass/Fail , ![](../doc/result_8_1.png)
![](../doc/result_8_2.png)
![](../doc/result_8_3.png)
![](../doc/result_8_4.png), +9, Date of birth should be in the past ," 1. enter a day after today to the ""date of birth"" field
1. click next button "," The error MessageBox appears ""DOB: the day entered is latter than today.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_9.png)
![](../doc/result_9_1.png) , +10, email entered should be valid ," 1. enter an invalid email e.g. ""ankitrai326.com""
1. click ""next"" button "," The error MessageBox appears ""email format error"," it should be email.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_10.png)
![](../doc/result_10_1.png) +11, GPA should be a number / decimal ," 1. enter a non numeric value into ""GPA"" field
1. Click ""Next"" button "," The error MessageBox appears ""GPA field should be a number.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_11.png)
![](../doc/result_11_1.png) , +12, Expected graduation year should be in future ," 1. enter a day in the past in ""Graduation year"" field
1. Click ""Next"" button "," The error MessageBox appears ""Expected graduation year should be after current year.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_12.png)
![](../doc/result_12_1.png) , +13, female appliciant ," 1. select female in applicant gender field
1. Click ""Next"" button "," The error MessageBox appears ""Expected graduation year should be after current year.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_13.png)
![](../doc/result_13_1.png)
![](../doc/result_13_2.png) , +14," ""Bachelor of Science in Computer Science and AI"" in apply programme "," 1. select female in applicant gender field
1. Click ""Next"" button "," The error MessageBox appears ""Expected graduation year should be after current year.""
The error MessageBox appears ""Please enter all required information."" ", Pass/Fail , ![](../doc/result_14.png)
![](../doc/result_14_1.png)
![](../doc/result_14_2.png), diff --git a/hdhdjshxh/task2/project/doc/test.docx b/hdhdjshxh/task2/project/doc/test.docx new file mode 100644 index 00000000..0b8d027f Binary files /dev/null and b/hdhdjshxh/task2/project/doc/test.docx differ diff --git a/hdhdjshxh/task2/project/doc/test.md b/hdhdjshxh/task2/project/doc/test.md new file mode 100644 index 00000000..bd110cb4 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/test.md @@ -0,0 +1,285 @@ +# TEST plan + +### Test purpose + +1. Validation on the input data and display appropriate error messages + +1. Test Plan with test cases and test results. + +### Test #1 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------------------------------------ | +| Test Case Name | Missing "Applicant Name" | +| Procedure | 1. leave "applicant name" field empty.\n1. Click "Next" button | +| Expected Output | The error MessageBox appears "name cannot empty."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_1.png) + +#### step 2 screenshot + +![](../doc/result_1_1.png) + +### Test #2 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Missing "Applicant Email" | +| Procedure | 1. leave "applicant email" field empty.\n1. Click "Next" button | +| Expected Output | The error MessageBox appears "email field cannot empty."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_2.png) + +#### step 2 screenshot + +![](../doc/result_2_1.png) + +### Test #3 + +| del me | del me | +| --------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Missing "Date of Birth" | +| Procedure | 1. leave "date of birth" field empty. \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "dob field cannot empty."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_3.png) + +#### step 2 screenshot + +![](../doc/result_3_1.png) + +### Test #4 + +| del me | del me | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Missing Institution Name | +| Procedure | 1. leave "Institution Name" field empty \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Please enter all required information."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_4.png) + +#### step 2 screenshot + +![](../doc/result_4_1.png) + +### Test #5 + +| del me | del me | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Missing Programme Title | +| Procedure | 1. leave "Programme Title" field empty \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Please enter all required information."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_5.png) + +#### step 2 screenshot + +![](../doc/result_5_1.png) + +### Test #6 + +| del me | del me | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Missing GPA | +| Procedure | 1. leave "GPA" field empty \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Please enter all required information."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_6.png) + +#### step 2 screenshot + +![](../doc/result_6_1.png) + +### Test #7 + +| del me | del me | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Missing Expected Graduation Year | +| Procedure | 1. leave "Expected Graduation Year" field empty \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Please enter all required information."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_7.png) + +#### step 2 screenshot + +![](../doc/result_7_1.png) + +### Test #8 + +| del me | del me | +| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | Showing summary if all input field fullfilled | +| Procedure | 1. filling all required information in "Personal Information" \n1. clici "Next" button \n 1. Filling all required information in"Higher Diploma Information" windows. \n1. Click "Next" button\n 1. click "show" button to show summary | +| Expected Output | finally the summary window showing information in the page inputted before | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_8_1.png) + +#### step 2 screenshot + +![](../doc/result_8_2.png) + +#### step 3 screenshot + +![](../doc/result_8_3.png) + +#### step 4 screenshot + +![](../doc/result_8_4.png) + +### Test #9 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| Test Case Name | Date of birth should be in the past | +| Procedure | 1. enter a day after today to the "date of birth" field \n 1. click next button | +| Expected Output | The error MessageBox appears "DOB: the day entered is latter than today."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_9.png) + +#### step 2 screenshot + +![](../doc/result_9_1.png) + +### Test #10 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------- | +| Test Case Name | email entered should be valid | +| Procedure | 1. enter an invalid email e.g. "ankitrai326.com" \n 1. click "next" button | +| Expected Output | The error MessageBox appears "email format error | +| Result | it should be email."\nThe error MessageBox appears "Please enter all required information." | + +### Screen capture + +#### step 1 screenshot + +Pass/Fail + +### Test #11 + +| del me | del me | +| --------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| Test Case Name | GPA should be a number / decimal | +| Procedure | 1. enter a non numeric value into "GPA" field \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "GPA field should be a number."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_11.png) + +#### step 2 screenshot + +![](../doc/result_11_1.png) + +### Test #12 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Test Case Name | Expected graduation year should be in future | +| Procedure | 1. enter a day in the past in "Graduation year" field \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Expected graduation year should be after current year."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_12.png) + +#### step 2 screenshot + +![](../doc/result_12_1.png) + +### Test #13 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Test Case Name | female appliciant | +| Procedure | 1. select female in applicant gender field \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Expected graduation year should be after current year."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_13.png) + +#### step 2 screenshot + +![](../doc/result_13_1.png) + +#### step 3 screenshot + +![](../doc/result_13_2.png) + +### Test #14 + +| del me | del me | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Test Case Name | "Bachelor of Science in Computer Science and AI" in apply programme | +| Procedure | 1. select female in applicant gender field \n1. Click "Next" button | +| Expected Output | The error MessageBox appears "Expected graduation year should be after current year."\nThe error MessageBox appears "Please enter all required information." | +| Result | Pass/Fail | + +### Screen capture + +#### step 1 screenshot + +![](../doc/result_14.png) + +#### step 2 screenshot + +![](../doc/result_14_1.png) + +#### step 3 screenshot + +![](../doc/result_14_2.png) diff --git a/hdhdjshxh/task2/project/doc/to_docx.py b/hdhdjshxh/task2/project/doc/to_docx.py new file mode 100644 index 00000000..f294fcac --- /dev/null +++ b/hdhdjshxh/task2/project/doc/to_docx.py @@ -0,0 +1,6 @@ +from Markdown2docx import Markdown2docx + +print("writing Q9950_GetDocx") +project = Markdown2docx('test') +project.eat_soup() +project.save() diff --git a/hdhdjshxh/task2/project/doc/transpose.py b/hdhdjshxh/task2/project/doc/transpose.py new file mode 100644 index 00000000..9a24d8b1 --- /dev/null +++ b/hdhdjshxh/task2/project/doc/transpose.py @@ -0,0 +1,38 @@ +import csv + + + +print('''# TEST plan + +### Test purpose + +1. Validation on the input data and display appropriate error messages + +1. Test Plan with test cases and test results.''') +print('\n') +print('\n') +print('\n') + +# read a csv file named test.csv +with open('test.csv', 'r') as f: + + # creating a csv reader object + csvreader = csv.reader(f) + + # extracting each data row one by one + for row in csvreader: + + print(f'### Test #{row[0]}') + print('\n') + print(f'| del me | del me |') + print(f'| ----- | ----- |') + print(f'| Test Case Name | {row[1]} |') + print(f'| Procedure | {row[2].replace("
",'\\n')} |') + print(f'| Expected Output | {row[3].replace("
",'\\n')} |') + print(f'| Result | {row[4].replace("
",'\\n')} |') + print('\n') + print("### Screen capture") + print( '\n'.join([ (f'\n#### step {i+1} screenshot\n'+x.strip()) for i, x in enumerate(row[5].split("
"))]) ) + print('\n') + print('\n') + diff --git a/hdhdjshxh/task2/project/src/Assignment.py b/hdhdjshxh/task2/project/src/Assignment.py new file mode 100644 index 00000000..aaa4dd82 --- /dev/null +++ b/hdhdjshxh/task2/project/src/Assignment.py @@ -0,0 +1,508 @@ +import os +import sys +import re +import datetime + +import tkinter +import tkinter.ttk + +import tkinter.messagebox +import tkinter.scrolledtext +from tkinter import * + +# class starts + + +class HDinfo(): + # Attributes: + # institutionName– a non-public string to store the HD institution name of the applicant. + # programmeTitle – a non-public string to store the HD programme name of the applicant. + # gpa – a non-public double to store the HD GPA of the applicant. + # expectedGradeYear– a non-public int to store the Expected HD Graduation Year of the applicant. + + # Methods: + # init – initialize all attributes in HDinfo object. It is a Parameterized constructor. + # str – return a string containing the Attributes of HDinfo object. This method is used to display in Summary ScrolledText. + + # constructor __init__ + def __init__(self, institutionName="", programmeTitle="", gpa="", expectedGraYear=""): + self.institutionName = institutionName + self.programmeTitle = programmeTitle + self.gpa = gpa + self.expectedGraYear = expectedGraYear + pass + + # __str__ method + def __str__(self): + return """ +Higher Diploma Information: +Institution Name: {hd_institution_name} +Programme Title: {hd_programme_title} +GPA: {hd_gpa} +Expected Graduation Year: {expectedGraYear} +""".strip().format( + hd_institution_name=self.institutionName, + hd_programme_title=self.programmeTitle, + hd_gpa=self.gpa, + expectedGraYear=self.expectedGraYear, + ) + + +class Applicant(): + # Attributes: + # name – a non-public string to store the name of the applicant. + # email – a non-public string to store the email of the applicant. + # gender – a non-public string to store the gender of the applicant. + # dateOfBirth – a non-public string to store the applicant date of birth. + # applyDegreeProgramme – a non-public string to store the applicant selected + # degree programme + # hdInfo– a non-public HDinfo(self-defined class) to store the applicant Higher + # Diploma information + + # Methods: + # init – initialize all attributes in Applicant object. It is a Parameterized constructor. + # setPeronalInfo – setter method to set the name, email, gender, dateOfBirth, applyDegreeProgrmme into the Applicant object. + # setHDinfo – setter method to set the HDinfo object into the Applicant object. + # str – return a string containing the Attributes of this Applicant. This function is used to display in Summary ScrolledText. + + # constructor __init__ + def __init__(self, name="", email="", gender="", dateOfBirth="", applyDegreeProgramme="", hdInfo=HDinfo()): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + pass + + # Set Personal Info Method + def setPeronalInfo(self, name, email, gender, dateOfBirth, applyDegreeProgramme): + self.name = name + self.email = email + self.gender = gender + self.dateOfBirth = dateOfBirth + self.applyDegreeProgramme = applyDegreeProgramme + + # Set HD Info Method + def setHDInfo(self, hd): + self.hd = hd + pass + + # __str__ method + def __str__(self): + """ + Returns a string representation of the Applicant object. + + Returns: + str: A formatted string containing the applicant's name, email, gender, date of birth, and applied degree programme. + Also includes a string representation of the Higher Diploma object. + """ + return """ +Applicant Name: {applicant_name} +Applicant Email: {applicant_email} +Gender: {gender} +Date of Birth: {DOB} +Apply Degree Programme: {applyDegreeProgramme} +""".strip().format( + applicant_name=self.name, + applicant_email=self.email, + gender=self.gender, + DOB=self.dateOfBirth, + applyDegreeProgramme=self.applyDegreeProgramme, + ) + '\n' + self.hd.__str__() + + +applicant = Applicant() +# class ends + + +# Tkinter starts + + +# Parent class for Personal and HighDiploma +class ApplicationPage(tkinter.Frame): + """Base class for managed pages. Provides methods to be overridden by subclasses.""" + + def __init__(self, master): + super().__init__(master) + + def is_complete(self) -> bool: + """Check if the current page is complete.""" + return True + + +class Personal(ApplicationPage): + + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label( + frm_title, text="Personal Infromation", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + # Write your coding here + # Frame for the content + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.grid_columnconfigure(2, weight=1) + + # Row counter, to advance row in screen + row = 0 + + # Label for applicant name + lbl_name = tkinter.Label( + frm_content, text="Applicant Name", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + # Entry box for applicant name + self.ent_applicant_name = tkinter.Entry(frm_content) + self.ent_applicant_name.insert(0, "") + self.ent_applicant_name.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + # Label for applicant email + lbl_name = tkinter.Label( + frm_content, text="Applicant Email", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + # Entry box for applicant email + self.ent_applicant_email = tkinter.Entry(frm_content) + self.ent_applicant_email.insert(0, "") + self.ent_applicant_email.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + # String variable to store the selected gender + self.gender_select = tkinter.StringVar(value="Male") + + # Label for gender + lbl_gender = tkinter.Label( + frm_content, text="Gender", anchor="w", justify="left", width=20) + lbl_gender.grid(row=row, column=0) + + # Radio buttons for gender selection + rad_male = tkinter.Radiobutton( + frm_content, variable=self.gender_select, text="Male", value="Male") + rad_male.grid(row=row, column=1) + + rad_female = tkinter.Radiobutton( + frm_content, variable=self.gender_select, text="Female", value="Female") + rad_female.grid(row=row, column=2) + + row += 1 + + # Label for date of birth + lbl_name = tkinter.Label( + frm_content, text="Date of Birth", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + + # Entry box for date of birth + self.ent_applicant_DOB = tkinter.Entry(frm_content) + self.ent_applicant_DOB.insert(0, "") + self.ent_applicant_DOB.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + # Label for apply programme + lbl_name = tkinter.Label( + frm_content, text="Apply Programme", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + + # List of programme options and combobox for apply programme + lst_programme = ["Bachelor of Science in Cybersecurity", + "Bachelor of Science in Computer Science and AI"] + self.applicant_programme = tkinter.ttk.Combobox( + frm_content, textvariable=lst_programme, values=lst_programme, state="readonly",) + self.applicant_programme.current(0) + self.applicant_programme.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + def is_complete(self): + + ### + # Write your coding here + entry_valid = True + if self.ent_applicant_name.get() == "": + tkinter.messagebox.showinfo("Information", "name cannot empty.") + entry_valid = False + + if self.ent_applicant_email.get() == "": + tkinter.messagebox.showinfo( + "Information", "email field cannot empty.") + entry_valid = False + else: + # check if email field valid + # https://www.geeksforgeeks.org/check-if-email-address-valid-or-not-in-python/ + if not re.match(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b', self.ent_applicant_email.get()): + tkinter.messagebox.showinfo( + "Information", "email: format error, it should be email.") + entry_valid = False + + if self.ent_applicant_DOB.get() == "": + tkinter.messagebox.showinfo( + "Information", "dob field cannot empty.") + entry_valid = False + else: + # python re to check if yyyy/mm/dd + if not re.match(r'^\d{4}/\d{2}/\d{2}$', self.ent_applicant_DOB.get()): + tkinter.messagebox.showinfo( + "Information", "DOB format error, it should be yyyy/mm/dd.") + entry_valid = False + + # ptyhon to check if the day entered is latter than today + today = datetime.date.today() + if datetime.datetime.strptime(self.ent_applicant_DOB.get(), '%Y/%m/%d').date() > today: + tkinter.messagebox.showinfo( + "Information", "DOB the day enter is latter than today.") + entry_valid = False + + if (entry_valid): + applicant.setPeronalInfo( + self.ent_applicant_name.get(), + self.ent_applicant_email.get(), + self.gender_select.get(), + self.ent_applicant_DOB.get(), + self.applicant_programme.get() + ) + return True + + return False + + +class HighDiploma(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label( + frm_title, text="Higher Diploma Information", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + ### + # Write your coding here + # Content frame for the form entries + row = 0 # row counter for the form + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2, weight=1) + + # Label and entry for Institution name + lbl_name = tkinter.Label( + frm_content, text="Institution Name", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_institution_name = tkinter.Entry(frm_content) + self.ent_institution_name.insert(0, "") + self.ent_institution_name.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + # Label and entry for Programme Title + lbl_name = tkinter.Label( + frm_content, text="Programme Title", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_programme_title = tkinter.Entry(frm_content) + self.ent_programme_title.insert(0, "") + self.ent_programme_title.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + # Label and entry for GPA + lbl_name = tkinter.Label( + frm_content, text="GPA", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.ent_GPA = tkinter.Entry(frm_content) + self.ent_GPA.insert(0, "") + self.ent_GPA.grid(row=row, column=1, columnspan=2, + sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + # Label and entry for Expected Graduation Year + lbl_name = tkinter.Label( + frm_content, text="Expected Graduation Year", anchor="w", justify="left", width=20) + lbl_name.grid(row=row, column=0) + self.expected_grad_year = tkinter.Entry(frm_content) + self.expected_grad_year.insert(0, "") + self.expected_grad_year.grid( + row=row, column=1, columnspan=2, sticky="nsew", pady=(10, 10), padx=(10, 10)) + row += 1 + + ### + + def is_complete(self): + ### + # Write your coding here + + entry_valid = True + if self.ent_institution_name.get() == "": + tkinter.messagebox.showinfo( + "Information", "institution name field cannot empty.") + entry_valid = False + if self.ent_programme_title.get() == "": + tkinter.messagebox.showinfo( + "Information", "programme title field cannot empty.") + entry_valid = False + + if self.ent_GPA.get() == "": + tkinter.messagebox.showinfo( + "Information", "GPA field cannot empty.") + entry_valid = False + else: + + # check if gpa field is a number + try: + float(self.ent_GPA.get()) + except ValueError: + tkinter.messagebox.showinfo( + "Information", "GPA field should be a number.") + entry_valid = False + + if self.expected_grad_year.get() == "": + tkinter.messagebox.showinfo( + "Information", "Expected graduation year field cannot empty.") + entry_valid = False + else: + + # check if gpa field is a number + try: + int(self.expected_grad_year.get()) + + # check if expected grad year is after current year + today = datetime.date.today() + if int(self.expected_grad_year.get()) < today.year: + tkinter.messagebox.showinfo( + "Information", "Expected graduation year should be after current year.") + entry_valid = False + + except ValueError: + tkinter.messagebox.showinfo( + "Information", "Expected graduation year field should be a number.") + entry_valid = False + + hd = HDinfo( + self.ent_institution_name.get(), + self.ent_programme_title.get(), + self.ent_GPA.get(), + self.expected_grad_year.get() + ) + + if (entry_valid): + applicant.setHDInfo(hd) + return True + + return False + + +class Result(ApplicationPage): + def __init__(self, master): + super().__init__(master) + + frm_base = tkinter.Frame(self) + frm_base.pack(fill=tkinter.BOTH, expand=True) + + frm_title = tkinter.Frame(frm_base) + frm_title.pack(fill=tkinter.BOTH) + + lbl_title = tkinter.Label(frm_base, text="Summary", font=("bold", 15)) + lbl_title.pack(anchor=tkinter.W) + + # Summary Output + ### + # Write your coding here + row = 0 + frm_content = tkinter.Frame(frm_base) + frm_content.pack(fill=tkinter.BOTH) + frm_content.grid_columnconfigure(2, weight=1) + + # textbox for summary + self.txt_summary = tkinter.Text(frm_content, height=12) + self.txt_summary.grid(row=row, column=1, columnspan=2, + sticky="nsew", pady=(1, 1), padx=(1, 1)) + row += 1 + + # right justify button with text "show" + btn_show = tkinter.Button(frm_base, text="Show", anchor=tkinter.E) + btn_show.pack(side=tkinter.RIGHT) + + # tkinter bind button click + btn_show.bind("", self.show) + + ### + + def show(self, _): # Show Button method + ### + # Write your coding here + self.txt_summary.insert(tkinter.INSERT, str(applicant)) + ### + + +class Application(tkinter.Tk): + def __init__(self): + super().__init__() + + # Configure GUI + self.title("Undergraduate Application Form") + self.geometry("450x300") + + # Content Frame + frm_content = tkinter.Frame(self, relief=tkinter.RIDGE, borderwidth=1) + frm_content.pack(fill=tkinter.BOTH, expand=True) + frm_content.rowconfigure(0, weight=1) + frm_content.columnconfigure(0, weight=1) + + # Application Pages + self.__frames: list[ApplicationPage] = [ + Personal(frm_content), + HighDiploma(frm_content), + Result(frm_content), + ] + for i in self.__frames: + i.grid(row=0, column=0, sticky=tkinter.NSEW) + self.__current_page = 0 + self.__frames[self.__current_page].tkraise() + + # Bottom Frame + frm_button = tkinter.Frame(self, padx=4, pady=4) + frm_button.pack(side=tkinter.BOTTOM, fill=tkinter.X) + + # Next Button + self.btn_next = tkinter.Button( + frm_button, text="Next", command=self.next_page) + self.btn_next.pack(side=tkinter.RIGHT) + + # Quit Button + self.btn_quit = tkinter.Button( + frm_button, text="Quit", command=self.destroy) + + def next_page(self): + # Check if the current page is complete + if not self.__frames[self.__current_page].is_complete(): + tkinter.messagebox.showinfo( + "Information", "Please fill the missing fields." + ) + return + + # Navigate to next page + self.__current_page += 1 + self.__frames[self.__current_page].tkraise() + + # If we reached the last page, replace the next button with quit button + if self.__current_page + 1 == len(self.__frames): + self.btn_next.pack_forget() + self.btn_quit.pack(side=tkinter.RIGHT) +# Tkinter ends + + +if __name__ == "__main__": + app = Application() + app.mainloop() diff --git a/hdhdjshxh/task2/project/src/test.bat b/hdhdjshxh/task2/project/src/test.bat new file mode 100644 index 00000000..55fdd17f --- /dev/null +++ b/hdhdjshxh/task2/project/src/test.bat @@ -0,0 +1,10 @@ + +@REM rm *.bas +@REM rm *.frm +@REM rm *.frx +@REM timeout 1 + +:loop + python ./Assignment.py + timeout /t 1 +goto loop diff --git a/hdhdjshxh/task2/project/test_report.docx b/hdhdjshxh/task2/project/test_report.docx new file mode 100644 index 00000000..e16c8c8f Binary files /dev/null and b/hdhdjshxh/task2/project/test_report.docx differ