uw-course 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uw_course/ClassSchedule/SearchInfo.py +48 -0
- uw_course/ClassSchedule/runner.py +66 -0
- uw_course/DB/dbClass.py +25 -0
- uw_course/Utiles/colorMessage.py +9 -0
- uw_course/Utiles/manageDBClass.py +20 -0
- uw_course/Utiles/randomColor.py +16 -0
- uw_course/__init__.py +0 -0
- uw_course/main.py +78 -0
- uw_course/setting.py +5 -0
- uw_course-0.1.0.dist-info/LICENSE +21 -0
- uw_course-0.1.0.dist-info/METADATA +70 -0
- uw_course-0.1.0.dist-info/RECORD +15 -0
- uw_course-0.1.0.dist-info/WHEEL +5 -0
- uw_course-0.1.0.dist-info/entry_points.txt +2 -0
- uw_course-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from Utiles.colorMessage import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Course():
|
|
6
|
+
def __init__(self, outDir):
|
|
7
|
+
self.fileOut = open(outDir, "a")
|
|
8
|
+
# self.colorMes = bcolors()
|
|
9
|
+
|
|
10
|
+
def SearchCourse(self, CollectionData, courseIndex, color="#878787", classNum=None):
|
|
11
|
+
self.courseSelect = CollectionData.find({"ClassIndex": courseIndex})
|
|
12
|
+
self.color = color
|
|
13
|
+
|
|
14
|
+
for course in self.courseSelect:
|
|
15
|
+
if classNum != None:
|
|
16
|
+
if course['_id'] != classNum:
|
|
17
|
+
continue
|
|
18
|
+
self.time = course['time']
|
|
19
|
+
self.classNum = course['_id']
|
|
20
|
+
self.courseIndex = course['ClassIndex']
|
|
21
|
+
self.courseTitle = course['classTitle']
|
|
22
|
+
self.courseSeat = course['availableSeat']
|
|
23
|
+
if re.search("\d:\d*", self.time):
|
|
24
|
+
self.startTime = self.time[0:5]
|
|
25
|
+
self.endTime = self.time[6:11]
|
|
26
|
+
StartTimeFlag = False
|
|
27
|
+
EndTimeFlag = False
|
|
28
|
+
if (int(self.endTime[0:2]) < int(self.startTime[0:2])):
|
|
29
|
+
EndTimeFlag = True
|
|
30
|
+
if (int(self.startTime[0:2]) < 8):
|
|
31
|
+
StartTimeFlag = True
|
|
32
|
+
EndTimeFlag = True
|
|
33
|
+
if StartTimeFlag:
|
|
34
|
+
self.startTime = str(int(self.startTime[0:2]) + 12) + self.startTime[2:5]
|
|
35
|
+
if EndTimeFlag:
|
|
36
|
+
self.endTime = str(int(self.endTime[0:2]) + 12) + self.endTime[2:5]
|
|
37
|
+
self.weekDay = "H" if self.time[11:15] == "Th" else self.time[11:15]
|
|
38
|
+
self.writeSchedule()
|
|
39
|
+
else:
|
|
40
|
+
print(WARNING + "Z_Z For course %s in class %s, Time Data Error Z_Z" % (self.courseIndex, self.classNum)+ENDC)
|
|
41
|
+
|
|
42
|
+
def writeSchedule(self):
|
|
43
|
+
self.fileOut.write(
|
|
44
|
+
"- name: %s\n" % (str(self.classNum) + " " + self.courseIndex + " " + self.courseTitle + " Available Seat " + str(self.courseSeat)))
|
|
45
|
+
self.fileOut.write(" days: %s\n" % self.weekDay)
|
|
46
|
+
self.fileOut.write(" time: %s - %s\n" % (self.startTime, self.endTime))
|
|
47
|
+
self.fileOut.write(" color: \"%s\"\n" % self.color)
|
|
48
|
+
self.fileOut.write("\n\n")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from ClassSchedule.SearchInfo import Course
|
|
2
|
+
from os import remove
|
|
3
|
+
from Utiles.randomColor import randomColor, randomGray
|
|
4
|
+
from setting import Setting
|
|
5
|
+
from Utiles.colorMessage import *
|
|
6
|
+
|
|
7
|
+
setting = Setting()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def SearchCourse(dbClassUW, courseIndex):
|
|
11
|
+
CourseDescribe = dbClassUW.CourseDescribe
|
|
12
|
+
faculty = courseIndex.split(" ")[0]
|
|
13
|
+
courseNum = courseIndex.split(" ")[1]
|
|
14
|
+
FacultyList = CourseDescribe.find({"faculty": faculty})
|
|
15
|
+
for course in FacultyList:
|
|
16
|
+
if course["courseIndex"] == courseNum:
|
|
17
|
+
print("\n" + "$" * 50 + "\n\n")
|
|
18
|
+
print("Description: ", end="")
|
|
19
|
+
print(course["courseDescription"])
|
|
20
|
+
print("\ncourseCredit: ", end="")
|
|
21
|
+
print(course["courseCredit"])
|
|
22
|
+
print("\n\n" + "$" * 50)
|
|
23
|
+
break
|
|
24
|
+
print("\n\n")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def SearchAvalibleInTerm(dbClassUW, courseIndex, classNum=None):
|
|
28
|
+
ClassSchedule = dbClassUW.ClassSchedule
|
|
29
|
+
courseSelect = ClassSchedule.find({"ClassIndex": courseIndex})
|
|
30
|
+
if courseSelect == None:
|
|
31
|
+
print(FAIL + "@_@ Course %s Not Found in %s @_@" % (courseIndex, dbClassUW.ClassCollectionName) + ENDC)
|
|
32
|
+
return None
|
|
33
|
+
else:
|
|
34
|
+
print(OKGREEN + "!! Found Course %s in %s !!" % (courseIndex, dbClassUW.ClassCollectionName) + ENDC)
|
|
35
|
+
if classNum != None:
|
|
36
|
+
return [courseIndex, classNum]
|
|
37
|
+
return [courseIndex]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def makeSchedule(dbClassUW, courseWishList: list, gray: bool=False):
|
|
41
|
+
classSchedule = dbClassUW.ClassSchedule
|
|
42
|
+
if gray:
|
|
43
|
+
print(OKGREEN + "!! Make Schedule with Gray Color !!" + ENDC)
|
|
44
|
+
try:
|
|
45
|
+
remove(setting.outDir)
|
|
46
|
+
except:
|
|
47
|
+
pass
|
|
48
|
+
file = open(setting.outDir, 'w+')
|
|
49
|
+
file.close()
|
|
50
|
+
courseInfo = Course(outDir=setting.outDir)
|
|
51
|
+
|
|
52
|
+
### List Course Here
|
|
53
|
+
for course in courseWishList:
|
|
54
|
+
if len(course) == 2:
|
|
55
|
+
classNum = course[1]
|
|
56
|
+
course = course[0]
|
|
57
|
+
else:
|
|
58
|
+
classNum = None
|
|
59
|
+
course = course[0]
|
|
60
|
+
if gray:
|
|
61
|
+
courseInfo.SearchCourse(CollectionData=classSchedule, courseIndex=course, color=randomGray(),
|
|
62
|
+
classNum=classNum)
|
|
63
|
+
else:
|
|
64
|
+
courseInfo.SearchCourse(CollectionData=classSchedule, courseIndex=course, color=randomColor(),
|
|
65
|
+
classNum=classNum)
|
|
66
|
+
###
|
uw_course/DB/dbClass.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from Utiles.manageDBClass import connectDB
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class dbClass:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self.ClassCollectionName = "Class2024Winter"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
self.url = "mongodb+srv://user:hCk2I9rMak6dMKpf@uwdatabase.kcmy6ok.mongodb.net/?retryWrites=true&w=majority"
|
|
11
|
+
|
|
12
|
+
self.ClassDATABASE = connectDB(mongo_host=self.url)
|
|
13
|
+
self.ClassDATABASE.connectDataBase('UWRegistrationDB')
|
|
14
|
+
self.ClassDATABASE.selectCollection(self.ClassCollectionName)
|
|
15
|
+
self.ClassSchedule = self.ClassDATABASE.mongo_collection
|
|
16
|
+
|
|
17
|
+
self.CourseDetailDB = connectDB(mongo_host=self.url)
|
|
18
|
+
self.CourseDetailDB.connectDataBase("UWRegistrationDB")
|
|
19
|
+
self.CourseDetailDB.selectCollection("CourseDetail")
|
|
20
|
+
self.CourseDescribe = self.CourseDetailDB.mongo_collection
|
|
21
|
+
|
|
22
|
+
def switchCollection(self, collectionName):
|
|
23
|
+
self.ClassCollectionName = collectionName
|
|
24
|
+
self.ClassDATABASE.selectCollection(self.ClassCollectionName)
|
|
25
|
+
self.ClassSchedule = self.ClassDATABASE.mongo_collection
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pymongo import MongoClient
|
|
2
|
+
from pymongo.server_api import ServerApi
|
|
3
|
+
import certifi
|
|
4
|
+
|
|
5
|
+
class connectDB:
|
|
6
|
+
def __init__(self, mongo_host):
|
|
7
|
+
self.mongo_host = mongo_host
|
|
8
|
+
# self.mongo_port = mongo_port
|
|
9
|
+
self.client = MongoClient(self.mongo_host, server_api=ServerApi('1'),tlsCAFile=certifi.where())
|
|
10
|
+
self.mongo_db = None
|
|
11
|
+
self.mongo_collection = None
|
|
12
|
+
|
|
13
|
+
def connectDataBase(self, mongo_db):
|
|
14
|
+
self.mongo_db = self.client[mongo_db]
|
|
15
|
+
|
|
16
|
+
def selectCollection(self, collection_name):
|
|
17
|
+
self.mongo_collection = self.mongo_db[collection_name]
|
|
18
|
+
|
|
19
|
+
def closeDB(self):
|
|
20
|
+
self.client.close()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from random import randint
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def randomColor():
|
|
5
|
+
colorArr = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
|
|
6
|
+
color = ""
|
|
7
|
+
for i in range(6):
|
|
8
|
+
color += colorArr[randint(0, 14)]
|
|
9
|
+
return "#" + color
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def randomGray():
|
|
13
|
+
colorArr = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
|
|
14
|
+
color = colorArr[randint(2, 12)]
|
|
15
|
+
color += colorArr[randint(0, 14)]
|
|
16
|
+
return "#" + color + color + color
|
uw_course/__init__.py
ADDED
|
File without changes
|
uw_course/main.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from DB.dbClass import dbClass
|
|
2
|
+
from ClassSchedule.runner import SearchCourse, makeSchedule, SearchAvalibleInTerm
|
|
3
|
+
from Utiles.colorMessage import *
|
|
4
|
+
from os import system
|
|
5
|
+
from setting import Setting
|
|
6
|
+
import argparse
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
dbClassUW = dbClass()
|
|
10
|
+
setting = Setting()
|
|
11
|
+
courseWishList = []
|
|
12
|
+
|
|
13
|
+
url = "https://github.com/zangjiucheng/CourseExplorer/blob/Release/schema.txt"
|
|
14
|
+
|
|
15
|
+
def addCourse(course):
|
|
16
|
+
if course != None:
|
|
17
|
+
courseWishList.append(course)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def checkDetail(course):
|
|
21
|
+
SearchCourse(dbClassUW, course)
|
|
22
|
+
exit(0)
|
|
23
|
+
|
|
24
|
+
def parse_arguments():
|
|
25
|
+
"""Parse command-line arguments and validate them."""
|
|
26
|
+
parser = argparse.ArgumentParser(
|
|
27
|
+
description="Course Helper: A tool to manage course details and collections.",
|
|
28
|
+
epilog="""Hint: Use --course to specify a course
|
|
29
|
+
or --file to specify a file with courses using schema: {url}"""
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"-c", "--course", type=str, help="Specify the course to check details for."
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"-f", "--file", type=str, help="Specify a file with collection of courses."
|
|
36
|
+
)
|
|
37
|
+
parser.add_argument(
|
|
38
|
+
"-g", "--gray", action="store_true", help="Enable gray color mode for output."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
args = parser.parse_args()
|
|
42
|
+
|
|
43
|
+
# Ensure at least one of `--course` or `--file` is provided
|
|
44
|
+
if not args.course and not args.file:
|
|
45
|
+
print("\nError: You must specify at least one of --course or --file.\n")
|
|
46
|
+
parser.print_help()
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
|
|
49
|
+
return args
|
|
50
|
+
|
|
51
|
+
def main():
|
|
52
|
+
args = parse_arguments()
|
|
53
|
+
gray = args.gray
|
|
54
|
+
if args.course:
|
|
55
|
+
checkDetail(args.course)
|
|
56
|
+
elif args.file:
|
|
57
|
+
with open(args.file, "r") as f:
|
|
58
|
+
collection = f.readline().strip()
|
|
59
|
+
dbClassUW.switchCollection(collection)
|
|
60
|
+
next(f) # Skip the first line
|
|
61
|
+
for line in f:
|
|
62
|
+
try:
|
|
63
|
+
if line.startswith("#"):
|
|
64
|
+
continue
|
|
65
|
+
info = line.strip().split(",")
|
|
66
|
+
course = info[0].strip()
|
|
67
|
+
if len(info) > 1:
|
|
68
|
+
addCourse(SearchAvalibleInTerm(dbClassUW, course, int(info[1].strip())))
|
|
69
|
+
else:
|
|
70
|
+
addCourse(SearchAvalibleInTerm(dbClassUW, course))
|
|
71
|
+
except Exception as e:
|
|
72
|
+
print(FAIL + f"Error: {e}" + ENDC)
|
|
73
|
+
makeSchedule(dbClassUW, courseWishList=courseWishList, gray=gray)
|
|
74
|
+
system("pdfschedule " + setting.outDir)
|
|
75
|
+
print(OKGREEN + "\n\n ---------------- Done!!! ---------------- \n\n" + ENDC)
|
|
76
|
+
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
main()
|
uw_course/setting.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Jiucheng(Oliver)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: uw-course
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A course helper tool for managing UW courses schedule
|
|
5
|
+
Author-email: Jiucheng Zang <zangjiucheng@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/zangjiucheng/CourseExplorer
|
|
8
|
+
Project-URL: repository, https://github.com/zangjiucheng/CourseExplorer
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: attrs
|
|
13
|
+
Requires-Dist: certifi
|
|
14
|
+
Requires-Dist: click
|
|
15
|
+
Requires-Dist: dnspython
|
|
16
|
+
Requires-Dist: pdfschedule
|
|
17
|
+
Requires-Dist: Pillow
|
|
18
|
+
Requires-Dist: pymongo
|
|
19
|
+
Requires-Dist: PyYAML
|
|
20
|
+
Requires-Dist: reportlab
|
|
21
|
+
|
|
22
|
+
# UWaterlooCourseHelperEngine
|
|
23
|
+
|
|
24
|
+
MongoDB DashBoard: [LINK](https://charts.mongodb.com/charts-project-0-cbzai/public/dashboards/091bc68f-76df-48c0-aa69-b21af14c0a8a)
|
|
25
|
+
|
|
26
|
+
### Example Schedule:
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
## This Version Still on Test!
|
|
31
|
+
|
|
32
|
+
#### Install Steps:
|
|
33
|
+
1. Install Python3 (Developed on py3.11) [Python Website](https://www.python.org/downloads/)
|
|
34
|
+
2. Clone this Repository
|
|
35
|
+
3. Go into ```OnlineVersion``` Folder
|
|
36
|
+
4. Install Requirement With Command ```pip install -r requirement.txt ```
|
|
37
|
+
5. Edit main.py Code With following Command:
|
|
38
|
+
|
|
39
|
+
Choose Term To Attend Class: (It Deisides which Term it Will Looking For!)
|
|
40
|
+
#### Current Avalible: Class2023Fall Class2024Winter (Rest Will be Update Later...)
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
```
|
|
44
|
+
dbClassUW.switchCollection(collectionName="Class2023Fall") # Class2023Fall Class2024Winter
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### Add Course on to Print List
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
addCourse(SearchAvalibleInTerm(dbClassUW, COURSE_INDEX))
|
|
51
|
+
addCourse(SearchAvalibleInTerm(dbClassUW, COURSE_INDEX,CLASS_ID))
|
|
52
|
+
```
|
|
53
|
+
(If without CLASS_ID, it will print all the avalible class)
|
|
54
|
+
|
|
55
|
+
#### Example:
|
|
56
|
+
```
|
|
57
|
+
addCourse(SearchAvalibleInTerm(dbClassUW, "CS 145"))
|
|
58
|
+
addCourse(SearchAvalibleInTerm(dbClassUW, "CS 350",6583))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
6. Save main.py
|
|
62
|
+
7. Run ```pdfschedule schedule``` in CLI.
|
|
63
|
+
8. ```schedule.pdf``` will be create in the folder
|
|
64
|
+
|
|
65
|
+
#### Enjoy~
|
|
66
|
+
|
|
67
|
+
#### Any Idea or Question, welcome send me an email via: j7zang@uwaterloo.ca
|
|
68
|
+
|
|
69
|
+
Or you can open an issue, or just find me in school :)
|
|
70
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
uw_course/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
uw_course/main.py,sha256=qkH1FoPLZQRGaSrXVcFa94l_g462rUG4ApDvARCoYxI,2632
|
|
3
|
+
uw_course/setting.py,sha256=MSJVr85Kc3XMFKW-rFKx34TDJWtbK4axj7TpzO0mTqM,177
|
|
4
|
+
uw_course/ClassSchedule/SearchInfo.py,sha256=Us5LMFCn7CrWpGuatcGUIxznwvXyNIRe08Zo9EBnxs8,2166
|
|
5
|
+
uw_course/ClassSchedule/runner.py,sha256=3M6iR95ycqpq5sK46FlrA7zihfJTwLhvESkjf8GBx6E,2321
|
|
6
|
+
uw_course/DB/dbClass.py,sha256=VxzcZEwGnVZDAJnad_Z654Vwv6zSa4nGcPIw58GxMfE,1004
|
|
7
|
+
uw_course/Utiles/colorMessage.py,sha256=HlTn2saR96Sh5jRjBZ_P8EvHrzORxOR6-Zzu0ATHuw0,176
|
|
8
|
+
uw_course/Utiles/manageDBClass.py,sha256=0V721lervaRzJyiFHgQrUovNKNYba8uiD9WIEeQLAe4,641
|
|
9
|
+
uw_course/Utiles/randomColor.py,sha256=4zubPBcRxos5Rqb8O-ZmkYYKvzPP9NjSdzZwdTZOmy0,467
|
|
10
|
+
uw_course-0.1.0.dist-info/LICENSE,sha256=3gvYdtz3_nCjhGpKAbUQzU1CT9anApYNOrn-bF6ZhI8,1073
|
|
11
|
+
uw_course-0.1.0.dist-info/METADATA,sha256=3N2S8aEyrmWrXrYU7O9h9y9Ka638ROnrc5YZunMAXGI,2143
|
|
12
|
+
uw_course-0.1.0.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
|
13
|
+
uw_course-0.1.0.dist-info/entry_points.txt,sha256=jmijLKvAtiXIUz-KXwSo0roUlHhUuvYNXsfSIfvm-nk,64
|
|
14
|
+
uw_course-0.1.0.dist-info/top_level.txt,sha256=b760hy15dn_4qeUiKj9gQ8jnO9caaRoD-4ks28p81NY,10
|
|
15
|
+
uw_course-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uw_course
|