From 6c1037ea93594e5833759c0468adb05f914d6695 Mon Sep 17 00:00:00 2001 From: molaboon Date: Sat, 3 Jul 2021 23:34:10 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=87=89=E8=A9=B2=E6=98=AF=E9=80=99?= =?UTF-8?q?=E6=A8=A3=E3=84=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wins/MainWin.py | 26 +++++++-- wins/Moodle.py | 90 +++++++++++++++++++++++++++++ wins/Ncnu.py | 102 +++++++++++++++++++++++++++++++++ wins/NcnuMainWin.py | 36 ++++++++++++ wins/courseTable.py | 137 ++++++++++++++++++++++++++++++++++++++++++++ wins/firstpage.py | 109 +++++++++++++++++++++++++++++++++++ wins/rigestryWin.py | 103 +++++++++++++++++++++++++++++++++ 7 files changed, 599 insertions(+), 4 deletions(-) create mode 100644 wins/Moodle.py create mode 100644 wins/Ncnu.py create mode 100644 wins/NcnuMainWin.py create mode 100644 wins/courseTable.py create mode 100644 wins/firstpage.py create mode 100644 wins/rigestryWin.py diff --git a/wins/MainWin.py b/wins/MainWin.py index f39f85f..ceef27f 100644 --- a/wins/MainWin.py +++ b/wins/MainWin.py @@ -1,6 +1,12 @@ +from api.courseTable.courseTable import CourseTable from tkinter import * +from wins.Moodle import createMoodleWin as moodleWin +from wins.Ncnu import createNcnuWin as ncnuWin +from wins.NcnuMainWin import createNcnuMainWin as ncnuMainWin +from wins.courseTable import callTable +from wins.rigestryWin import createRigestryWin as rigestryWin -def createMainWin(): +def createMainWin(win,ncnu,moodle): ''' 用綠色校園作為基底色 以暨大的三大特色 @@ -9,18 +15,30 @@ def createMainWin(): 3.國際性-教務系統 去做三個網頁的底色 ''' - win=Tk() + + + win.configure(bg="#b2ffa6") createMoodleWin=Button(win,text="Moodle",font="Helvetica 30",bg="#888084",fg="white",relief=GROOVE) createNcnuMainWin=Button(win,text="暨大官網",font="Helvetica 30",bg="#ffcccc",fg="white",relief=GROOVE) createNcnuWin=Button(win,text="暨大教務系統",font="Helvetica 30",bg="#df99ff",fg="white",relief=GROOVE) + createTable=Button(win,text="自己課表自己排",font="Helvetica 30",bg="blue",fg="white",relief=GROOVE,command=lambda:callTable()) + createRigestryWin=Button(win,text="查詢活動報名資料",font="Helvetica 30",bg="black",fg="white",relief=GROOVE) + + createMoodleWin.config(command=lambda:moodleWin(moodle) ) + createNcnuMainWin.config(command=lambda:ncnuMainWin() ) + createNcnuWin.config(command=lambda:ncnuWin(ncnu) ) + createRigestryWin.config(command=lambda:rigestryWin()) + + createMoodleWin.pack(fill="x") createNcnuMainWin.pack(fill="x") createNcnuWin.pack(fill="x") - createMoodleWin.pack(fill="x") + createTable.pack(fill="x") + createRigestryWin.pack(fill="x") win.mainloop() -createMainWin() + diff --git a/wins/Moodle.py b/wins/Moodle.py new file mode 100644 index 0000000..a223ede --- /dev/null +++ b/wins/Moodle.py @@ -0,0 +1,90 @@ +from tkinter import * +from api.moodle import MoodleAPI +from config import CONFIG +from tkhtmlview import HTMLLabel + +def getIdAndName(course): + coursesId=[] + courseName=[] + for i in course: + coursesId.append(i.get("id")) + tmp=i.get("name").split(" ") + courseName.append(tmp[1]) + return coursesId ,courseName + + + +def createMoodleWin(moodle): + if moodle.status: + # ===== 取得課程ID與名稱 ===== + win=Tk() + + rightFrame=Frame(win,bg="red") + leftFrame=Frame(win) + #===== 右框 初始化 用html去印出所有資料===== + htmlLb=HTMLLabel(rightFrame,html="") + htmlScrollbar=Scrollbar(rightFrame) + htmlLb.configure(yscrollcommand=htmlScrollbar.set) + + htmlScrollbar.pack(fill=Y,side=RIGHT) + htmlLb.pack() + + leftFrame.pack(fill=BOTH,side=LEFT) + rightFrame.pack(fill=BOTH) + + #=====Leftframe 1.button ->show UpComingEvent 2.choose courses======= + + def showUpComingEvent(): #叫出未來事件 + ht='''
讀取中
''' + htmlLb.set_html(ht) + win.update() + + tmphtml='''''' + for e in moodle.getUpcomingEvents(): + tmphtml+='''
{}
時間:{}

'''.format(e.get("name"),e.get("time") ) + #tmphtml+='''''' + htmlLb.set_html(tmphtml) + + upComingEventBtn=Button(leftFrame,text="未來事件",font="Helvetica 10",command= lambda:showUpComingEvent() ) + coursesListBox=Listbox(leftFrame) + mylb=Label(leftFrame,text="我的課程",font="Helvetica 15") + + mylb.pack(fill=X) + coursesListBox.pack(fill=BOTH) + upComingEventBtn.pack(fill=BOTH,pady=10) + + #=======rightframe ->show everything which I click====== + def itemSelected(event): + obj = event.widget + Index = obj.curselection() + tmpId=coursesId[coursesName.index(str(obj.get(Index)))] + ht='''

讀取中
''' + htmlLb.set_html(ht) + win.update() + Html='''

本周作業

    ''' + for work in moodle.getWeekWorkInCourse(str(tmpId)): + Html+='''
  1. {}
  2. '''.format(work.get("link"),work.get("name") ) + Html+='''

最新公告

    ''' + for anno in moodle.getAnnoInCourse(str(tmpId)): + Html+='''
  1. {}
  2. '''.format(anno.get("title")) + Html+='''
''' + htmlLb.set_html(Html) + + + + coursesName=[] + coursesListBox.insert(END,*coursesName) + + win.update() + + coursesId,coursesName=getIdAndName(moodle.getCourses("1092")) + coursesListBox.insert(END,*coursesName) + print(coursesName) + coursesListBox.bind("<>", itemSelected) + win.mainloop() + + + + + else: + print("Moodle 登入失敗") diff --git a/wins/Ncnu.py b/wins/Ncnu.py new file mode 100644 index 0000000..2d00eef --- /dev/null +++ b/wins/Ncnu.py @@ -0,0 +1,102 @@ +from tkinter import * +from api.ncnu import NcnuAPI +from config import CONFIG +from tkinter import messagebox +from tkhtmlview import HTMLLabel + +def createNcnuWin(ncnu): + + if ncnu.status: + def dlCurriculum(sem): + if ncnu.getCourseTable(sem): + messagebox.showinfo(message="{} 課表已經儲存到 ./{}課表.pdf".format(sem,sem)) + else: + messagebox.showwarning(message="無法存取 {} 課表".format(sem)) + win=Tk() + leftframe=Frame(win) + leftframe.pack(fill=BOTH,side=LEFT) + rightframe=Frame(win) + rightframe.pack(side=RIGHT) + + textlb=Label(leftframe,text="我的學習紀錄",font="Helvetica 20") + options=["各學期成績總覽","指定學期的成績列表","缺曠課記錄","獎懲紀錄","加選課程狀態"] + optionsListbox=Listbox(leftframe) + optionsListbox.insert(END,*options) + chooseSemesterLb=Label(leftframe,text="指定學期",font="Helvetica 10") + + chooseSemesterEntry=Entry(leftframe) + chooseSemesterEntry.insert(0,"1092") + downloadBtn=Button(leftframe,text="下載課表",command=lambda:dlCurriculum(chooseSemesterEntry.get())) + + + textlb.pack(fill=BOTH,expand=True) + optionsListbox.pack(fill=BOTH) + chooseSemesterLb.pack(fill=BOTH) + chooseSemesterEntry.pack(fill=BOTH) + downloadBtn.pack() + + htmlLb=HTMLLabel(rightframe,html="") + htmlScrollbar=Scrollbar(rightframe) + htmlLb.configure(yscrollcommand=htmlScrollbar.set) + + htmlScrollbar.pack(fill=Y,side=RIGHT) + htmlLb.pack() + + def itemSelected(event): + obj = event.widget + Index = obj.curselection() + ht='''
讀取中
''' + htmlLb.set_html(ht) + win.update() + + + Html='''''' + if str( obj.get(Index) ) == options[0]: + scores = ncnu.getScoreSummary() + for c in scores['semesters']: + Html+=''' 學期:{} 修課數:{} 通過數:{} 學分數:{} 平均分數:{} 排名:{}

'''.format(c.get("semester"), + c.get("select_num"),c.get("pass_Num"),c.get("pass_credit"),c.get("average"),c.get("rank") ) + c=scores['sum'] + Html+=''' 學期{} 修課數:{} 通過數:{} 學分數:{} {} {}'''.format(c.get("semester"), + c.get("select_num"),c.get("pass_Num"),c.get("pass_credit"),c.get("average"),c.get("rank") ) + htmlLb.set_html(Html) + + elif str( obj.get(Index) ) == options[1]: + scores = ncnu.getScore(chooseSemesterEntry.get()) + for i in scores: + Html+="代號: {} 班號: {} 課程名稱: {} 學分數: {}老師: {} 時間: {} 地點: {} 學分: {} 分數: {} 是否為必修?: {}

".format(i.get("number"), + i.get("class"),i.get("name"),i.get("credit"),i.get("teacher"),i.get("time"),i.get("place"),i.get("credit"),i.get("score"),i.get("mandatary") ) + htmlLb.set_html(Html) + elif str( obj.get(Index) ) == options[2]: + absenceLogs = ncnu.getAbsenceLogs() + if absenceLogs: + for log in absenceLogs: + Html+=''' {} {} {} {} {}'''.format(log.get('id'), + log.get('semester'),log.get('classname'),log.get('date'),log.get('time')) + htmlLb.set_html(Html) + else: + Html+='''

沒有任何缺曠課記錄

''' + htmlLb.set_html(Html) + elif str( obj.get(Index) ) == options[3]: + awardLogs = ncnu.getAwardLogs() + if awardLogs: + for log in awardLogs: + Html+=''' {} {} {} {} {}'''.format(log.get('id'), + log.get('semester'),log.get('award'),log.get('count'),log.get('content')) + htmlLb.set_html(Html) + else: + Html+='''

沒有任何缺曠課記錄

''' + htmlLb.set_html(Html) + elif str( obj.get(Index) ) == options[4]: + logs = ncnu.getAddCourseLogs() + if logs: + for log in logs: + Html+=''' {} 學期: {}
課名: {} 班別: {} 加選狀態:{}

'''.format(log.get('id'), + log.get('semester'),log.get('classname'),log.get('class'),log.get('check')) + htmlLb.set_html(Html) + optionsListbox.bind("<>", itemSelected) + + win.mainloop() + + else: + print("NCNU 教務系統登入失敗") diff --git a/wins/NcnuMainWin.py b/wins/NcnuMainWin.py new file mode 100644 index 0000000..fb4fb8d --- /dev/null +++ b/wins/NcnuMainWin.py @@ -0,0 +1,36 @@ +from tkinter import * +from tkhtmlview import HTMLLabel +from api.ncnuMain import NcnuMainAPI + +def createNcnuMainWin(): + win=Tk() + win.title("暨大官網最新資訊!") + win.geometry("600x600") + textLb=Label(win,text="暨大校園最新資訊",font="Helvetica 20",bg="#ffcccc") + + sb=Scrollbar(win) + htmlLable=HTMLLabel(win) + htmlLable.configure(yscrollcommand=sb.set) + textLb.pack(fill="x") + + sb.pack(side=RIGHT,fill="y") + htmlLable.pack(fill="both",expand=True) + win.update() + #=====爬===== + ht='''

讀取中
''' + htmlLable.set_html(ht) + win.update() + + main = NcnuMainAPI() + Link='''
    ''' + for anno in main.getAnno(): + Link+='''
  • {}
  • '''.format(anno.get("link"),anno.get("title") ) + Link=Link+'''
''' + htmlLable.set_html(Link) + + + + + + win.mainloop() + diff --git a/wins/courseTable.py b/wins/courseTable.py new file mode 100644 index 0000000..2385a4b --- /dev/null +++ b/wins/courseTable.py @@ -0,0 +1,137 @@ +import requests +import json +from tkinter import * +from api.courseTable.courseTable import * +def callTable(): + url = 'https://raw.githubusercontent.com/snsd0805/NCNU_Course/master/%E6%AD%B7%E5%B9%B4%E8%AA%B2%E7%A8%8B%E8%B3%87%E6%96%99/1092_output.json' + response = requests.get(url) + + data = json.loads(response.text) + + class Choose(): + def __init__(self,root,name,typeS): + self.frame=Frame(root) + self.classname = Label(self.frame, font="10", width="10", text=name) + self.listbox = Listbox(self.frame) + self.scrollbar=Scrollbar(self.frame) + self.checkBtn = Button(self.frame, text="選取") + self.checkBtn.config( + command=lambda: self.setDepartment() if self.type=="department" else self.setCourse() + ) + self.type = typeS + + def setDepartment(self): + # print("set department") + # print(self.listbox.get(ACTIVE)) + self.update() + + def setCourse(self): + # print("set course") + # print(self.listbox.get(ACTIVE).split(' ')[0]) + courseTable.add( + self.listbox.get(ACTIVE).split(' ')[0] + ) + self.update() + + def update(self): + courses = courseTable.courseFilter(box[0].listbox.get(ACTIVE)) + courses = ["{} {}({})".format(course['number'], course['name'], course['time']) for course in courses] + box[1].listbox.delete(0, END) + box[1].insert(courses) + + # update table draw + for j in range(5): + for i in range(13): + if courseTable.table[str(j+1) + tmp[i]] != None: + table[18 + (13*j+i)].classname.config(text= + courseTable.table[str(j+1) + tmp[i]]['name'] + ) + table[18 + (13*j+i)].removeBtn.grid() + table[18 + (13*j+i)].id = courseTable.table[str(j+1) + tmp[i]]['number'] + else: + table[18 + (13*j+i)].classname.config(text="") + table[18 + (13*j+i)].removeBtn.grid_forget() + table[18 + (13*j+i)].id = None + + def insert(self,LIST): + self.listbox.insert(END,*LIST) + + def grid(self,Row,Column,span): + self.listbox.selection_set(15) + self.frame.grid(row=Row,column=Column,rowspan=span,padx=10,sticky="n"+"s") + self.classname.pack() + self.scrollbar.pack(fill=Y,side=RIGHT) + self.listbox.pack() + self.listbox.config(yscrollcommand=self.scrollbar.set) + self.checkBtn.pack() + + class Space(): + def __init__(self, root, name=None): + self.frame = Frame(root,relief=RIDGE,bd=1) + self.classname = Label(self.frame, font=("Curier New",10),padx=10, text=name,justify="right") + self.removeBtn = Button(self.frame, font=("Curier New",10), text="刪", command=self.removeCourse) + #self.frame.config(relief=RIDGE) + self.id = None + + def grid(self,Row,Column): + if Row==5: + self.frame.config(bg="green") + self.classname.config(bg="green") + self.frame.grid(row=Row,column=Column,padx=20,sticky="w"+"e") + self.classname.grid(row=0,column=0) + self.removeBtn.grid(row=0,column=1) + self.removeBtn.grid_forget() + + def removeCourse(self): + # print(self.id) + courseTable.remove(self.id) + box[0].update() + # courseTable.showTableStatus() + + root = Tk() + root.geometry('800x600') + + courseTable = CourseTable() + + box=[] + box.append(Choose(root,name="科系",typeS='department')) + departments = courseTable.getDepartmentList() + box[0].insert(departments) + box[0].listbox.select_set(0) + box[0].grid(0,0,7) + + box.append(Choose(root,name="課程",typeS='courses')) + courses = courseTable.courseFilter("21, 資工系") + + box[1].insert(["{} {}({})".format(course['number'], course['name'], course['time']) for course in courses]) + box[1].grid(7,0,6) + + + table = [] + k=0 + + tmp=list("abcdzefghijklm") + + for j in range(5): + table.append(Label(root,text=j+1,font=("Curier New",20))) + table[k].grid(row=0,column=j+3) + k+=1 + + for i in range(13): + table.append(Label(root,text=tmp[i])) + table[k].grid(row=i+1,column=1) + + k+=1 + + table[9].config(bg="green") + + # 18~ + for j in range(5): + for i in range(13): + table.append(Space(root)) + table[k].grid(i+1,j+3) + k+=1 + + + + root.mainloop() \ No newline at end of file diff --git a/wins/firstpage.py b/wins/firstpage.py new file mode 100644 index 0000000..0fc2695 --- /dev/null +++ b/wins/firstpage.py @@ -0,0 +1,109 @@ +from tkinter import * +from tkinter import ttk +from config import CONFIG +import json +from api.moodle import MoodleAPI +from tkinter import messagebox +from api.ncnu import NcnuAPI +from wins.MainWin import * + + +def firstWin(first): + #first=Tk() + #login.withdraw() + first.geometry("600x400") + first.minsize(400,400) + first.maxsize(600,600) + first.configure(background="skyblue") + + frame=Frame(first,bg="skyblue") + go_to_loginwin_btn=Button(first,text="開始進入暨管家",font="Helvetica 20",bg="yellow",command=lambda: [first.destroy()] ) + text_lb=Label(frame,text="歡迎來到暨管家",font=("Courier New Greek",40),bg="skyblue") + photo = PhotoImage(file="100_100.gif") + imgLabel =Label(frame,image=photo,bg="skyblue") + + frame.pack(expand=1) + imgLabel.pack() + text_lb.pack(padx=100) + go_to_loginwin_btn.pack(pady=50) + + first.mainloop() + +def loginwin(login): + #login=Tk() + login.geometry("300x200") + login.configure(bg="lightgreen") + login.resizable(width=0,height=0) + + frame=Frame(login,width=100,height=100,bg="lightgreen") + frame1=Frame(login,width=300,height=100,bg="lightgreen") + frame2=Frame(login,width=300,height=100,bg="lightgreen") + frame3=Frame(login,width=300,height=100,bg="lightgreen") + frame4=Frame(login,width=300,height=100,bg="lightgreen") + prompt_lb=Label(frame,text="請輸入你的學號與密碼",font="Helvetica 20",bg="lightgreen") + login_btn=Button(frame3,text="登入",command=lambda:Login() ) + + enter_name=Entry(frame1,bd=3) + enter_password=Entry(frame2,show="*",bd=3) + enter_ncnupw=Entry(frame4,show="*",bd=3) + + name_lb=Label(frame1,text="學號",font="Helvetica 12",bg="lightgreen") + + pw_lb=Label(frame2,text="Moodle密碼",font="Helvetica 12",bg="lightgreen") + ncnupw_lb=Label(frame4,text="教務系統密碼",font="Helvetica 12",bg="lightgreen") + + show_password=Button( frame3,text="透視moodle密碼") + show_ncnupw=Button( frame3,text="透視教務系統密碼") + + show_password.bind( '',lambda event:enter_password.config(show="")) + show_password.bind( '',lambda event : enter_password.config(show="*") ) + + show_ncnupw.bind( '',lambda event:enter_ncnupw.config(show="")) + show_ncnupw.bind( '',lambda event : enter_ncnupw.config(show="*") ) + + + #===== 輸入帳密===== + def Login(): + with open('config.json') as fp: + CON = json.load(fp) + CON["semester"]="1092" + CON["moodle"]["username"]=str(enter_name.get() ) + CON["moodle"]["password"]=str(enter_password.get()) + CON["NCNU"]["username"]=str(enter_name.get()) + CON["NCNU"]["password"]=str(enter_ncnupw.get()) + + json.dump(CON, open("config.json", "w")) + try: + moodle = MoodleAPI(CONFIG['moodle']['username'], CONFIG['moodle']['password']) + ncnu = NcnuAPI(CONFIG['NCNU']['username'], CONFIG['NCNU']['password']) + moodle.status + ncnu.status + except: + messagebox.showinfo(message="Error") + else: + login.destroy() + mainWin=Tk() + createMainWin(mainWin,ncnu,moodle) + + frame.pack() + frame1.pack() + frame2.pack() + frame4.pack() + frame3.pack() + prompt_lb.pack(pady=10,side="top") + name_lb.pack(side="left") + enter_name.pack(side="left") + pw_lb.pack(side="left") + enter_password.pack(side="left") + ncnupw_lb.pack(side="left") + enter_ncnupw.pack() + + show_password.pack(side="left",pady=10,padx=10) + show_ncnupw.pack(side="left",pady=10,padx=10) + login_btn.pack(side="left",pady=10) + + login.mainloop() + + + + diff --git a/wins/rigestryWin.py b/wins/rigestryWin.py new file mode 100644 index 0000000..29cbf94 --- /dev/null +++ b/wins/rigestryWin.py @@ -0,0 +1,103 @@ +from api.eventRigestry import EventRegistry +from config import CONFIG +from tkinter import * +from tkhtmlview import HTMLLabel + +class textBox(): + def __init__(self, root, key, value, Stype): + self.key = key + self.value = value + self.type = Stype + self.frame = Frame(root) + self.label = Label(self.frame, text=key) + self.entry = Entry(self.frame) + self.entry.insert(0, value) + + if Stype==False: + self.entry.config(state='disabled') + + def pack(self): + self.label.pack(side=LEFT) + self.entry.pack(side=RIGHT) + self.frame.pack() + + +def createRigestryWin(): + + root=Tk() + frame1=Frame(root) + frame2=Frame(root) + frame1.pack(side=LEFT) + frame2.pack() + winScrollBar=Scrollbar(frame1) + htmlLb=HTMLLabel(frame1,html="") + + + winScrollBar.pack(side=RIGHT,fill="y") + htmlLb.pack(fill=BOTH) + htmlLb.configure(yscrollcommand=winScrollBar.set) + + ht='''
讀取中
''' + htmlLb.set_html(ht) + root.update() + html='''''' + + root.update() + + + rigestry=EventRegistry(CONFIG['moodle']['username'], CONFIG['moodle']['password']) + tmpid=[] + tmpname=[] + events = rigestry.getEventsList() + if rigestry.status: + for i in events: + html+=''' 活動ID:{} 學期{}
活動報名狀態:{}
活動名稱:{}
活動開始時間: {}
報名方式:{}
時數: {}
講師: {}
申請為教師之能活動: {}

'''.format( + i.get("id"),i.get("semester"),i.get("status"),i.get("name"),i.get("time"),i.get("method"),i.get("hour"),i.get("speaker"),i.get("teacherEvevt") ) + tmpid.append(i.get("id")) + tmpname.append(i.get("name")) + htmlLb.set_html(html) + else: + print("NO") + + def signUpWin(event): + win=Tk() + data = rigestry.signUpPrepare(event.get('id')) + + idBox = textBox(win, "學號:", data['x_applicantID'], False) + idBox.pack() + + nameBox = textBox(win, "姓名:", data['x_applicantName'], False) + nameBox.pack() + + departmentBox = textBox(win, "科系:", data['x_applicantUabbrname'], False) + departmentBox.pack() + + authBox = textBox(win, "身份:", data['x_applicantTitle'], False) + authBox.pack() + + iphoneBox = textBox(win, "分機:", data['x_iphone'], True) + iphoneBox.pack() + + phoneBox = textBox(win, "電話:", data['x_phone'], True) + phoneBox.pack() + + mailBox = textBox(win, "mail:", data['x_zemail'], True) + mailBox.pack() + + markBox = textBox(win, "備註:", data['x_remark'], True) + markBox.pack() + + submit = Button(win, text="報名") + submit.pack() + + win.mainloop() + + + for i in events: + if i.get('status') == "B, 開放公告": + Button(frame2,text="我要報名 {}".format(i.get('name')),command=lambda:signUpWin(i) ).pack(anchor="w") + + root.update() + + root.mainloop() + From 535d2d6e0e6f593abdb0ce20c2bf4b56dc06d1b7 Mon Sep 17 00:00:00 2001 From: molaboon Date: Sat, 3 Jul 2021 23:35:14 +0800 Subject: [PATCH 2/2] main --- MainTkinter.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MainTkinter.py b/MainTkinter.py index 8edc463..01c5119 100644 --- a/MainTkinter.py +++ b/MainTkinter.py @@ -1,10 +1,10 @@ from tkinter import * -from firstpage import * -from MainWin import * -from config import CONFIG -from Ncnu import * -from Moodle import * -from NcnuMainWin import * +from wins.firstpage import * +from wins.MainWin import * +from config import CONFIG +from wins.Ncnu import * +from wins.Moodle import * +from wins.NcnuMainWin import * from api.moodle import MoodleAPI from api.ncnu import NcnuAPI import threading