update,
This commit is contained in:
23
README.md
Normal file
23
README.md
Normal file
@@ -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.
|
7
gitUpdate.bat
Normal file
7
gitUpdate.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
git status .
|
||||
|
||||
@pause
|
||||
|
||||
git add .
|
||||
git commit -m"update hdhdjshxh,"
|
||||
start git push
|
12
history.md
Normal file
12
history.md
Normal file
@@ -0,0 +1,12 @@
|
||||
### Quotation factor:
|
||||
|
||||
- setup
|
||||
|
||||
- setup fee 50
|
||||
|
||||
- difficulty
|
||||
|
||||
- 3 question HKD 150
|
||||
|
||||
HKD 150
|
||||
deposit 50
|
13
package.json
Normal file
13
package.json
Normal file
@@ -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"
|
||||
}
|
59
prompt.md
Normal file
59
prompt.md
Normal file
@@ -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))
|
||||
|
||||
```
|
||||
|
BIN
task1/SASP Assignment 1c Python Scripting 2023 (pcap info).doc
Normal file
BIN
task1/SASP Assignment 1c Python Scripting 2023 (pcap info).doc
Normal file
Binary file not shown.
BIN
task1/SASP Assignment 1c Python Scripting 2023 v3.doc
Normal file
BIN
task1/SASP Assignment 1c Python Scripting 2023 v3.doc
Normal file
Binary file not shown.
9
task1/helloworld.py
Normal file
9
task1/helloworld.py
Normal file
@@ -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()
|
BIN
task1/original/PCAP/ay2223_sasp_nmapcatured_1.pcap
Normal file
BIN
task1/original/PCAP/ay2223_sasp_nmapcatured_1.pcap
Normal file
Binary file not shown.
BIN
task1/original/PCAP/ay2223_sasp_nmapcatured_2.pcap
Normal file
BIN
task1/original/PCAP/ay2223_sasp_nmapcatured_2.pcap
Normal file
Binary file not shown.
BIN
task1/original/PCAP/ay2223_sasp_nmapcatured_3.pcap
Normal file
BIN
task1/original/PCAP/ay2223_sasp_nmapcatured_3.pcap
Normal file
Binary file not shown.
12
task1/original/Pipfile
Normal file
12
task1/original/Pipfile
Normal file
@@ -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"
|
Binary file not shown.
128
task1/original/sasp-part-b-assignment-v1.py
Normal file
128
task1/original/sasp-part-b-assignment-v1.py
Normal file
@@ -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","<Button-1>", 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()
|
BIN
task1/original/saspdemo.db
Normal file
BIN
task1/original/saspdemo.db
Normal file
Binary file not shown.
478
task1/requirements.txt
Normal file
478
task1/requirements.txt
Normal file
@@ -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
|
52
task1/scapy_helloworld.py
Normal file
52
task1/scapy_helloworld.py
Normal file
@@ -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}")
|
||||
|
||||
|
BIN
task1/src/PCAP/ay2223_sasp_nmapcatured_1.pcap
Normal file
BIN
task1/src/PCAP/ay2223_sasp_nmapcatured_1.pcap
Normal file
Binary file not shown.
BIN
task1/src/PCAP/ay2223_sasp_nmapcatured_2.pcap
Normal file
BIN
task1/src/PCAP/ay2223_sasp_nmapcatured_2.pcap
Normal file
Binary file not shown.
BIN
task1/src/PCAP/ay2223_sasp_nmapcatured_3.pcap
Normal file
BIN
task1/src/PCAP/ay2223_sasp_nmapcatured_3.pcap
Normal file
Binary file not shown.
12
task1/src/Pipfile
Normal file
12
task1/src/Pipfile
Normal file
@@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
scapy = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.11"
|
28
task1/src/Pipfile.lock
generated
Normal file
28
task1/src/Pipfile.lock
generated
Normal file
@@ -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": {}
|
||||
}
|
7
task1/src/README.md
Normal file
7
task1/src/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# README
|
||||
```bash
|
||||
$ pipenv shell
|
||||
|
||||
# inside pipenv shell
|
||||
$ python ./sasp-part-b-assignment-v1.py
|
||||
```
|
13
task1/src/package.json
Normal file
13
task1/src/package.json
Normal file
@@ -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"
|
||||
}
|
330
task1/src/sasp-part-b-assignment-v1.py
Normal file
330
task1/src/sasp-part-b-assignment-v1.py
Normal file
@@ -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","<Button-1>", 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","<Button-1>", 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('<<ComboboxSelected>>', 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')
|
BIN
task1/src/saspdemo.db
Normal file
BIN
task1/src/saspdemo.db
Normal file
Binary file not shown.
6
task1/src/test.sh
Normal file
6
task1/src/test.sh
Normal file
@@ -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
|
34
task1/test_threading.py
Normal file
34
task1/test_threading.py
Normal file
@@ -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)
|
BIN
task2/Assignment.pdf
Normal file
BIN
task2/Assignment.pdf
Normal file
Binary file not shown.
195
task2/Assignment.py
Normal file
195
task2/Assignment.py
Normal file
@@ -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()
|
BIN
task2/_backup/draft0001-1/Assignment.pdf
Normal file
BIN
task2/_backup/draft0001-1/Assignment.pdf
Normal file
Binary file not shown.
202
task2/_backup/draft0001-1/src/Assignment.py
Normal file
202
task2/_backup/draft0001-1/src/Assignment.py
Normal file
@@ -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()
|
10
task2/_backup/draft0001-1/src/test.bat
Normal file
10
task2/_backup/draft0001-1/src/test.bat
Normal file
@@ -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
|
BIN
task2/_backup/draft0001/Assignment.pdf
Normal file
BIN
task2/_backup/draft0001/Assignment.pdf
Normal file
Binary file not shown.
195
task2/_backup/draft0001/src/Assignment.py
Normal file
195
task2/_backup/draft0001/src/Assignment.py
Normal file
@@ -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()
|
BIN
task2/_backup/draft0002/Assignment.pdf
Normal file
BIN
task2/_backup/draft0002/Assignment.pdf
Normal file
Binary file not shown.
286
task2/_backup/draft0002/src/Assignment.py
Normal file
286
task2/_backup/draft0002/src/Assignment.py
Normal file
@@ -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()
|
10
task2/_backup/draft0002/src/test.bat
Normal file
10
task2/_backup/draft0002/src/test.bat
Normal file
@@ -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
|
BIN
task2/_backup/draft0003/Assignment.pdf
Normal file
BIN
task2/_backup/draft0003/Assignment.pdf
Normal file
Binary file not shown.
369
task2/_backup/draft0003/src/Assignment.py
Normal file
369
task2/_backup/draft0003/src/Assignment.py
Normal file
@@ -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("<Button-1>", 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()
|
10
task2/_backup/draft0003/src/test.bat
Normal file
10
task2/_backup/draft0003/src/test.bat
Normal file
@@ -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
|
BIN
task2/_backup/draft0004/Assignment.pdf
Normal file
BIN
task2/_backup/draft0004/Assignment.pdf
Normal file
Binary file not shown.
379
task2/_backup/draft0004/src/Assignment.py
Normal file
379
task2/_backup/draft0004/src/Assignment.py
Normal file
@@ -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("<Button-1>", 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()
|
10
task2/_backup/draft0004/src/test.bat
Normal file
10
task2/_backup/draft0004/src/test.bat
Normal file
@@ -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
|
BIN
task2/_backup/draft0005/Assignment.pdf
Normal file
BIN
task2/_backup/draft0005/Assignment.pdf
Normal file
Binary file not shown.
395
task2/_backup/draft0005/src/Assignment.py
Normal file
395
task2/_backup/draft0005/src/Assignment.py
Normal file
@@ -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("<Button-1>", 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()
|
10
task2/_backup/draft0005/src/test.bat
Normal file
10
task2/_backup/draft0005/src/test.bat
Normal file
@@ -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
|
135
task2/_poc/Switch Between Different Page Frames/test.py
Normal file
135
task2/_poc/Switch Between Different Page Frames/test.py
Normal file
@@ -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()
|
9
task2/_poc/grid/looptest.bat
Normal file
9
task2/_poc/grid/looptest.bat
Normal file
@@ -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
|
32
task2/_poc/grid/test.py
Normal file
32
task2/_poc/grid/test.py
Normal file
@@ -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()
|
1
task2/backup.bat
Normal file
1
task2/backup.bat
Normal file
@@ -0,0 +1 @@
|
||||
node ./backup.js
|
59
task2/backup.js
Normal file
59
task2/backup.js
Normal file
@@ -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}.`)
|
10
task2/digest.md
Normal file
10
task2/digest.md
Normal file
@@ -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
|
26
task2/meta.md
Normal file
26
task2/meta.md
Normal file
@@ -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
|
BIN
task2/notes/4459_ass.docx
Normal file
BIN
task2/notes/4459_ass.docx
Normal file
Binary file not shown.
BIN
task2/notes/Lab_01a - Object and Class_Answers.docx
Normal file
BIN
task2/notes/Lab_01a - Object and Class_Answers.docx
Normal file
Binary file not shown.
BIN
task2/notes/Lab_01b - Object and Class_Answers.docx
Normal file
BIN
task2/notes/Lab_01b - Object and Class_Answers.docx
Normal file
Binary file not shown.
BIN
task2/notes/Lab_02a - Initializer_Answers.doc
Normal file
BIN
task2/notes/Lab_02a - Initializer_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_02b - Initializer_Answers.doc
Normal file
BIN
task2/notes/Lab_02b - Initializer_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_03a - Instance and Static Members_Answers.doc
Normal file
BIN
task2/notes/Lab_03a - Instance and Static Members_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_03b - Instance and Static Members_Answers.doc
Normal file
BIN
task2/notes/Lab_03b - Instance and Static Members_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_04a - Inheritance_Answers.doc
Normal file
BIN
task2/notes/Lab_04a - Inheritance_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_04b - Inheritance_Answers.doc
Normal file
BIN
task2/notes/Lab_04b - Inheritance_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_05a - Abstract Class_Answers (1).doc
Normal file
BIN
task2/notes/Lab_05a - Abstract Class_Answers (1).doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_05b - Abstract Class.doc
Normal file
BIN
task2/notes/Lab_05b - Abstract Class.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_06a - Database Connection_Answers (1).doc
Normal file
BIN
task2/notes/Lab_06a - Database Connection_Answers (1).doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_06b - Database Connection_Answers.doc
Normal file
BIN
task2/notes/Lab_06b - Database Connection_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_07a - Tkinter_Answers.doc
Normal file
BIN
task2/notes/Lab_07a - Tkinter_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_07b - Tkinter_Answers.doc
Normal file
BIN
task2/notes/Lab_07b - Tkinter_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_07c - Tkinter_Answers.doc
Normal file
BIN
task2/notes/Lab_07c - Tkinter_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_08a - Web Scraping_Answers.doc
Normal file
BIN
task2/notes/Lab_08a - Web Scraping_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_08b - Web Scraping_Answers.doc
Normal file
BIN
task2/notes/Lab_08b - Web Scraping_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_09a - Python Web Framework_Answers.doc
Normal file
BIN
task2/notes/Lab_09a - Python Web Framework_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_09b - Python Web Framework_Answers.doc
Normal file
BIN
task2/notes/Lab_09b - Python Web Framework_Answers.doc
Normal file
Binary file not shown.
BIN
task2/notes/Lab_09c - Python Web Framework_Answers.doc
Normal file
BIN
task2/notes/Lab_09c - Python Web Framework_Answers.doc
Normal file
Binary file not shown.
13
task2/package.json
Normal file
13
task2/package.json
Normal file
@@ -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"
|
||||
}
|
BIN
task2/project/Assignment.pdf
Normal file
BIN
task2/project/Assignment.pdf
Normal file
Binary file not shown.
BIN
task2/project/doc/HD_information_window.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/HD_information_window.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/Personal_info_window.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/Personal_info_window.png
(Stored with Git LFS)
Normal file
Binary file not shown.
12
task2/project/doc/Pipfile
Normal file
12
task2/project/doc/Pipfile
Normal file
@@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
markdown2docx = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.12"
|
312
task2/project/doc/Pipfile.lock
generated
Normal file
312
task2/project/doc/Pipfile.lock
generated
Normal file
@@ -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": {}
|
||||
}
|
1
task2/project/doc/conv.bat
Normal file
1
task2/project/doc/conv.bat
Normal file
@@ -0,0 +1 @@
|
||||
python ./to_docx.py
|
BIN
task2/project/doc/result_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_10.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_10.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_10_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_10_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_11.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_11.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_11_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_11_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_12.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_12.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_12_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_12_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_13.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_13.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_13_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_13_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_13_2.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_13_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_14.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_14.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_14_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_14_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_14_2.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_14_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_1_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_1_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_2.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_2_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_2_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_3.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
task2/project/doc/result_3_1.png
(Stored with Git LFS)
Normal file
BIN
task2/project/doc/result_3_1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user