@Andream
2017-12-25T09:09:53.000000Z
字数 4433
阅读 910
课程表开发日志
api接口描述了客户端通过HTTP协议和服务端交互的协议。这里全部采用了POST方法,分为user , table, exam, grade, todo几个模块。返回的格式均为json格式,具体格式参见数据表的定义。
现在的想法是返回的数据就以数据库返回的数据为基础,然后加上status, error这两个参数,用于标识状态和错误信息,就ok了。
User
登录服务端 POST /user/login设置教务网密码 POST /user/setPassword注销 POST /user/logout
Table
获取自定义课程表 POST /table/getMyTable添加课程 POST /table/addCourse恢复教务网课程表 POST /table/resetMyTable检索课程 POST /table/search
Exam
获取考试信息 POST /exam/getExams添加考试 POST /exam/addExam编辑考试 POST /exam/setExam删除考试 POST /exam/deleteExam
Grade
获取成绩信息 POST /grade/getGrades
TODO
获取TODO信息 POST /todo/getTodos添加Todo POST /todo/addTodo编辑Todo POST /todo/setTodo删除Todo POST /todo/deleteTodo
在介绍数据库提供的接口之前,先介绍数据表的结构吧。
参考:http://www.mongoing.com/mongodb-advanced-pattern-design
合理的内嵌和冗余:http://www.jianshu.com/p/bb0caddff60a
哈希id保证不会重复添加:https://docs.mongodb.com/manual/core/index-hashed/
数据库采用的是MongoDB,设置四个表,分别为User, Table, Course, Exam。现在分别用json格式描述各表的键值。
User
{_id : ObjectId("4df08553188e444d001a763a"),stunum : "20151597",password : "123456",tel : "18216710629",academy : "软件学院",table : [{id : ObjectId("balabala"),course_name : "高等数学",classroom : "D1137",weeks : "[1-9],[10,18]",day : 1sections : "5-6",teacher : "杨向东",code : "MATH20041",note : "学分:3,总学时:48.0"},{id : ObjectId("balabala"),name : "线性代数",classroom : "D1233",weeks : "[1-9],[10,18]",day : 2sections : "1-2",teacher : "曾代敏",code : "MATH20001",note : "学分:3,总学时:48.0"}],mytable : [{id : ObjectId("balabala"),course_name : "一颗高树",classroom : "D1137",weeks : "[1-9],[10,18]",day : 1,sections : "5-6",teacher : "杨向东",code : "MATH20041",note : "学分:3,总学时:48.0"},{id : ObjectId("balabala"),course_name : "线性代数",classroom : "D1233",weeks : "[1-9],[10,18]",day : 2,sections : "1-2",teacher : "曾代敏",code : "MATH20001",note : "学分:3,总学时:48.0"}],exam : [{id : ObjectId("balabala"),code : "MATH20001",course_name : "概率论与数理统计",time_str : "2017-12-10(14周 星期日)09:00-11:00",start_time : "2017-12-10 09:00:00",end_time : "2017-12-10 11:00:00",classroom : "D区D一教学楼D1349",seat : "1-2",score : 3}],myexam : [{id : ObjectId("balabala"),code : "",course_name : "英语六级",time_str : "2017-12-10(14周 星期日)09:00-11:00",start_time : "2017-12-10 09:00:00",end_time : "2017-12-10 11:00:00",classroom : "D区D一教学楼D1349",seat : "1-2",score : 3}],grade : [[semester : "2015-2016学年 第一学期",gpa : 3.12,data : [{code : "MATH20001",course_name : "概率论与数理统计",score : 3.00,grade : 90,note : "类别:公共基础/必修\n考核方式:考试\n修读性质:初修\n辅修标记:主修"},{code : "MATH20002",course_name : "高等数学",score : 5.00,grade : 90,note : "类别:公共基础/必修\n考核方式:考试\n修读性质:初修\n辅修标记:主修"}]]]todo : []}
User
{_id : ObjectId("4df08553188e444d001a763a"),stunum : "20151597",password : "123456",tel : "18216710629",academy : "软件学院",table : ...mytable : ...exam : ...myexam : ...grade : ...todo : ...}
User是主要的数据表,大多数数据都采用了内嵌的形式。另外我还新建了Table、Exam两个子表,在User表中保留他们的引用和数据冗余。新建表是为了将来能开发课程检索和考试检索的功能。保留冗余是为了避免二次查询,提升查询效率。因为Table和Exam读写比很高,所以这种方案是合适的。
子表的格式和User表中内嵌的格式是一致的。
Table
{id : ObjectId("balabala"),course_name : "数据结构",classroom : "D1343",weeks : "[1-9],[10,18]",day : 1,sections : "5-6",teacher : "蔡斌",code : "MATH20041",note : "学分:3,总学时:48.0"}
Exam
{id : ObjectId("balabala"),code : "MATH20001",course_name : "概率论与数理统计",time_str : "2017-12-10(14周 星期日)09:00-11:00",start_time : "2017-12-10 09:00:00",end_time : "2017-12-10 11:00:00",classroom : "D区D一教学楼D1349",seat : "1-2",score : 3}
数据表的结构就大致如上面所述。
根据需求,为数据库提供了一些接口,方便api调用:
////////////////////////////////////////////// User/////////////////////////////////////////////** 检验用户名和密码是否正确,成功返回1,失败返回0* stunum : 学号* password : 密码* 异常:用户名或密码不完整* 该用户不存在(应该在调用过register之后才能调用login)* 密码错误*/login(stunum, password);/** 服务端在验证过密码可以登录教务网之后,调用该函数以在数据表中添加该用户的记录* stunum : 学号* password : 密码* 异常:用户名或密码不完整* 该用户已经存在*/register(stunum, password);/** 返回该用户的全部信息,包含课表考试和成绩* stunum : 学号* 异常:该用户不存在*/getUserInfo(stunum);////////////////////////////////////////////// Table/////////////////////////////////////////////** 返回该用户的课表信息* stunum : 学号* 异常:该用户不存在* 不存在课表信息*/getMyTable(stunum);/** 添加课程,并返回课表信息* stunum : 学号* course : 课程* 异常:该用户不存在*/addCourse(stunum, course);/** 重置课表为初始课表,并返回课表信息* stunum : 学号* 异常:该用户不存在* 不存在初始课表*/resetMyTable(stunum);////////////////////////////////////////////// Exam/////////////////////////////////////////////** 返回该用户的考试信息( 包括教务系统的和自定义的考试)* stunum : 学号* 异常:该用户不存在* 不存在考试信息*/getMyExam(stunum);/** 为该户用添加一个考试信息,并返回当前考试列表* stunum : 学号* exam : 要添加的考试信息* 异常:该用户不存在*/addExam(stunum, exam);/** 删除一条用户自定义的考试信息* stunum : 学号* exam : 要删除的考试信息* 异常:该用户不存在* 不存在考试信息*/removeExam(stunum, exam);////////////////////////////////////////////// Grade/////////////////////////////////////////////** 返回该用户的所有成绩信息* stunum : 学号* 异常:该用户不存在* 不存在成绩信息*/getGrade(stunum);
另外的还有crawler和parser接口,这两部分比较简单,于是从简,可以一边开发一边决定。
login();getTable();getExam();getGrade();getInfo();
parseLogin();parseTable();parseExam();parseGrade();parseInfo();