This commit is contained in:
louiscklaw
2025-02-01 02:01:48 +08:00
parent 8bf2589af5
commit a14cfa137f
125 changed files with 4895 additions and 0 deletions

23
README.md Normal file
View 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
View File

@@ -0,0 +1,7 @@
git status .
@pause
git add .
git commit -m"update hdhdjshxh,"
start git push

12
history.md Normal file
View 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
View 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
View 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))
```

Binary file not shown.

9
task1/helloworld.py Normal file
View 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()

Binary file not shown.

Binary file not shown.

Binary file not shown.

12
task1/original/Pipfile Normal file
View 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"

View 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

Binary file not shown.

478
task1/requirements.txt Normal file
View 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
View 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}")

Binary file not shown.

Binary file not shown.

Binary file not shown.

12
task1/src/Pipfile Normal file
View 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
View 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
View 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
View 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"
}

View 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

Binary file not shown.

6
task1/src/test.sh Normal file
View 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
View 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

Binary file not shown.

195
task2/Assignment.py Normal file
View 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()

Binary file not shown.

View 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()

View 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

Binary file not shown.

View 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()

Binary file not shown.

View 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()

View 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

Binary file not shown.

View 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()

View 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

Binary file not shown.

View 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()

View 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

Binary file not shown.

View 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()

View 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

View 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()

View 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
View 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
View File

@@ -0,0 +1 @@
node ./backup.js

59
task2/backup.js Normal file
View 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
View 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
View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

13
task2/package.json Normal file
View 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"
}

Binary file not shown.

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

Binary file not shown.

12
task2/project/doc/Pipfile Normal file
View 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
View 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": {}
}

View File

@@ -0,0 +1 @@
python ./to_docx.py

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More