@Andream
2017-12-25T17:09:53.000000Z
字数 4433
阅读 769
课程表开发日志
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 : 1
sections : "5-6",
teacher : "杨向东",
code : "MATH20041",
note : "学分:3,总学时:48.0"
},
{
id : ObjectId("balabala"),
name : "线性代数",
classroom : "D1233",
weeks : "[1-9],[10,18]",
day : 2
sections : "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();