class RedisForCourse: """ 封装有关课程的数据库操作 key format: STATUS:COURSE:COURSE_ID:xxx 存储的是一个lesson_id 表示当前课程最近一堂课的lesson_id """ __PRIMARY_KEY = 'COURSE_ID' __TABLE_NAME = 'COURSE' __PREFIX = REDIS_DB_NAME + ':' + __TABLE_NAME + ':' + __PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def updateLesson(self, course_id, lesson_id): """ 插入一条课程状态记录 :param course_id: 课程唯一标识 :param lesson_id: 课程下课堂唯一标识 :return: """ # format: STATUS:COURSE:COURSE_ID:xxx key = self.__PREFIX + ':' + str(course_id) self.__conn.set(key, lesson_id) def getLastlyLessonID(self, course_id): """ 获取课程最近一堂课的lesson_id :param course_id: 课程唯一标识 :return: """ # format: STATUS:COURSE:COURSE_ID:xxx key = self.__PREFIX + ':' + str(course_id) return self.__conn.get(key)
class RedisForOnlineList: """ 封装有关课堂在线列表的数据库操作 key format: STATUS:ONLINE_LIST:ID:(lesson_id)_(uid) 存储的是一个uid 这个key的用法实际上并不是很好,但是能实现需求 """ # 主键是由lesson_id与uid组成,中间通过下划线连接 __PRIMARY_KEY = 'ID' __TABLE_NAME = 'ONLINE_LIST' __PREFIX = REDIS_DB_NAME + ':' + __TABLE_NAME + ':' + __PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def refresh(self, lesson_id, uid): """ 刷新用户状态,即重置key的存活时间 :param lesson_id: 课程下课堂唯一标识 :param uid: 用户唯一标识 :return: """ # format: STATUS:ONLINE_LIST:ID:(lesson_id)_(uid) key = self.__PREFIX + ':' + str(lesson_id) + '_' + str(uid) self.__conn.setex(name=key, value=uid, time=5) def getOnlineList(self, lesson_id): """ 获取该课堂在线的uid列表 :param lesson_id: 课程下课堂唯一标识 :return: """ online_list = [] key_list = self.__conn.keys(self.__PREFIX + ':' + str(lesson_id) + '_*') for key in key_list: online_list.append(self.__conn.get(key)) return online_list
class RedisForLessonStatus: """ 封装有关课堂的各种状态的数据库操作 key format: STATUS:LESSON_STATUS:LESSON_ID:xxx 存储的是一个map |- lesson_id |- chat_status """ __PRIMARY_KEY = 'LESSON_ID' __TABLE_NAME = 'LESSON_STATUS' __PREFIX = REDIS_DB_NAME + ':' + __TABLE_NAME + ':' + __PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def createLesson(self, lesson_id): """ 插入一条课堂状态记录 :param lesson_id: 课程下课堂唯一标识 :return: """ # format: STATUS:LESSON_STATUS:LESSON_ID:xxx key = self.__PREFIX + ':' + str(lesson_id) record_data = { 'lesson_id': lesson_id, 'course_status': CourseStatus.Waiting, 'chat_status': ChatStatus.Free } self.__conn.hmset(key, record_data) def endLesson(self, lesson_id): """ 删除课堂状态记录 :param lesson_id: 课程下课堂唯一标识 :return: """ # format: STATUS:LESSON_STATUS:LESSON_ID:xxx key = self.__PREFIX + ':' + str(lesson_id) self.__conn.delete(key)
class RedisForDetails: """ 封装有关每帧检测数据记录的数据库操作 每位用户的记录在redis中以list形式存储 一堂课的所有详细记录都将会存储在这个list中 key format: STATUS:CONC_DETAILS:ID:(lesson_id)_(uid) key format: STATUS:CONC_USEFUL_DETAILS:ID:(lesson_id)_(uid) 这个key的用法实际上并不是很好,但是能实现需求 """ __PRIMARY_KEY = 'ID' __DETAILS = 'CONC_DETAILS' __USEFUL_DETAILS = 'CONC_USEFUL_DETAILS' __DETAILS_PREFIX = REDIS_DB_NAME + ':' + __DETAILS + ':' + __PRIMARY_KEY __USEFUL_DETAILS_PREFIX = REDIS_DB_NAME + ':' + __USEFUL_DETAILS + ':' + __PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def addDetail(self, is_succeed, uid, course_id, lesson_id, timestamp, emotion, is_blinked, is_yawned, h_angle, v_angle): """ 插入一条详细记录 详细记录是生成最终专注度记录的依据 每10条详细记录可用于生成1条最终记录 :param is_succeed: 是否成功识别到图像中的人脸(该条记录是否有用) :param uid: 用户唯一标识 :param course_id: 课程唯一标识 :param lesson_id: 课程下课堂唯一标识 :param timestamp: 该条记录的时间戳(指的是图像截取的时间,而非记录生成的时间) :param emotion: 表情 :param is_blinked: 是否有眨眼 :param is_yawned: 是否有打哈欠 :param h_angle: 头部的水平转动角度 :param v_angle: 头部的垂直转动角度 :return: """ # format: STATUS:CONC_DETAILS:ID:(lesson_id)_(uid) key = self.__DETAILS_PREFIX + ':' + str(lesson_id) + '_' + str(uid) record_data = { 'is_succeed': is_succeed, 'uid': uid, 'course_id': course_id, 'lesson_id': lesson_id, 'timestamp': timestamp, 'emotion': emotion, 'is_blinked': is_blinked, 'is_yawned': is_yawned, 'h_angle': h_angle, 'v_angle': v_angle } # redis的list中不能直接存储data类型 # 需先data转换为str self.__conn.lpush(key, json.dumps(record_data)) def addUsefulDetail(self, is_succeed, uid, course_id, lesson_id, timestamp, emotion, is_blinked, is_yawned, h_angle, v_angle): """ 插入一条能用于生成最终记录的详细记录 :param is_succeed: 是否成功识别到图像中的人脸(该条记录是否有用) :param uid: 用户唯一标识 :param course_id: 课程唯一标识 :param lesson_id: 课程下课堂唯一标识 :param timestamp: 该条记录的时间戳(指的是图像截取的时间,而非记录生成的时间) :param emotion: 表情 :param is_blinked: 是否有眨眼 :param is_yawned: 是否有打哈欠 :param h_angle: 头部的水平转动角度 :param v_angle: 头部的垂直转动角度 :return: 满10条记录后会返回True,以及10条json格式数据列表 否则返回False,以及返回[] """ # format: STATUS:CONC_USEFUL_DETAILS:ID:(lesson_id)_(uid) key = self.__USEFUL_DETAILS_PREFIX + ':' + str(lesson_id) + '_' + str( uid) record_data = { 'is_succeed': is_succeed, 'uid': uid, 'course_id': course_id, 'lesson_id': lesson_id, 'timestamp': timestamp, 'emotion': emotion, 'is_blinked': is_blinked, 'is_yawned': is_yawned, 'h_angle': h_angle, 'v_angle': v_angle } # redis的list中不能直接存储data类型 # 需先data转换为str # # 满10条记录后会返回True if self.__conn.lpush(key, json.dumps(record_data)) >= 10: return True else: return False def getUsefulDetails(self, lesson_id, uid): """ 获取并清空可用的十条详细记录 :param lesson_id: 课程下课堂唯一标识 :param uid: 用户唯一标识 :return: json格式数据 """ # format: STATUS:CONC_USEFUL_DETAILS:ID:(lesson_id)_(uid) key = self.__USEFUL_DETAILS_PREFIX + ':' + str(lesson_id) + '_' + str( uid) data_list = [] str_list = self.__conn.lrange(key, 0, 9) for data_str in str_list: data_list.append(json.loads(data_str)) self.__conn.delete(key) return data_list def clear(self, lesson_id, uid): """ 清除用户有关key :param lesson_id: 课程下课堂唯一标识 :param uid: 用户唯一标识 :return: """ key_1 = self.__USEFUL_DETAILS_PREFIX + ':' + str( lesson_id) + '_' + str(uid) key_2 = self.__DETAILS_PREFIX + ':' + str(lesson_id) + '_' + str(uid) self.__conn.delete(key_1, key_2)
def __init__(self): self.__conn = Redis().conn
class RedisForConc: """ 封装有关专注度记录的数据库操作 每位用户的记录在redis中以list形式存储 一堂课的所有详细记录都将会存储在这个list中 仅通过一个key(format: STATUS:CONC:LESSON_ID:xxx)即可以访问到该课的所有记录 或通过一个key(format: STATUS:CONC:ID:(lesson_id)_(uid))即可以访问到该用户的记录 这个key的用法实际上并不是很好,但是能实现需求 """ __PRIMARY_KEY = 'LESSON_ID' __PRIMARY_KEY_ID = 'ID' __CONC = 'CONC' __PREFIX = REDIS_DB_NAME + ':' + __CONC + ':' + __PRIMARY_KEY __PREFIX_ID = REDIS_DB_NAME + ':' + __CONC + ':' + __PRIMARY_KEY_ID def __init__(self): self.__conn = Redis().conn def addConcRecord(self, uid, course_id, lesson_id, begin_timestamp, end_timestamp, conc_score): """ 插入一条最终记录 :param uid: 用户唯一标识 :param course_id: 课程唯一标识 :param lesson_id: 课程下课堂唯一标识 :param begin_timestamp: 该条记录生成依据的起始时间 :param end_timestamp: 该条记录生成依据的结束时间 :param conc_score: 专注度评分 :return: """ record_data = { 'uid': uid, 'course_id': course_id, 'lesson_id': lesson_id, 'begin_timestamp': begin_timestamp, 'end_timestamp': end_timestamp, 'conc_score': conc_score } # format: STATUS:CONC:LESSON_ID:xxx key = self.__PREFIX + ':' + str(lesson_id) # redis的list中不能直接存储data类型 # 需先data转换为str self.__conn.lpush(key, json.dumps(record_data)) # format: STATUS:CONC:ID:(lesson_id)_(uid) key = self.__PREFIX_ID + ':' + str(lesson_id) + '_' + str(uid) self.__conn.lpush(key, json.dumps(record_data)) def getConcRecords(self, lesson_id): """ 获取该课程下课堂(lesson)的专注度信息 :param lesson_id: 课程下课堂唯一标识 :return: json格式数据 """ # format: STATUS:CONC:LESSON_ID:xxx key = self.__PREFIX + ':' + str(lesson_id) data_list = [] str_list = self.__conn.lrange(key, 0, -1) for data_str in str_list: data_list.append(json.loads(data_str)) return data_list def getLastConcRecordByUid(self, lesson_id, uid): """ 获取该用户的最新一条专注度信息 :param lesson_id: 课程下课堂唯一标识 :param uid: 用户唯一标识 :return: json格式数据 """ # format: STATUS:CONC:ID:(lesson_id)_(uid) key = self.__PREFIX_ID + ':' + str(lesson_id) + '_' + str(uid) record = self.__conn.lindex(key, -1) if record is not None: return json.loads(self.__conn.lindex(key, 0)) else: return None
class RedisForCourseStatus: """ 封装有关课程的各种状态的数据库操作 key format: STATUS:COURSE_STATUS:COURSE_ID:xxx 存储的是一个值CourseStatus(参考edu.py) """ __PRIMARY_KEY = 'COURSE_ID' __TABLE_NAME = 'COURSE_STATUS' __PREFIX = REDIS_DB_NAME + ':' + __TABLE_NAME + ':' + __PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def createCourse(self, course_id): """ 插入一条课堂状态记录 :param course_id: 课程唯一标识 :return: """ # format: STATUS:COURSE_STATUS:COURSE_ID:xxx key = self.__PREFIX + ':' + str(course_id) self.__conn.set(key, CourseStatus.OffLine) def getCourseStatus(self, course_id): """ 获取当前课程状态 :param course_id: 课程唯一标识 :return: """ # format: STATUS:COURSE_STATUS:COURSE_ID:xxx key = self.__PREFIX + ':' + str(course_id) if not self.__conn.exists(key): self.createCourse(course_id=course_id) return int(self.__conn.get(key)) def offLine(self, course_id): """ 课堂结束 :return: """ # format: STATUS:LESSON_STATUS:ID:xxx key = self.__PREFIX + ':' + str(course_id) self.__conn.set(key, CourseStatus.OffLine) def onLine(self, course_id): """ 正在上课 :return: """ # format: STATUS:LESSON_STATUS:ID:xxx key = self.__PREFIX + ':' + str(course_id) self.__conn.set(key, CourseStatus.OnLine) def cantJoinIn(self, course_id): """ 课堂不可中途加入 :return: """ # format: STATUS:LESSON_STATUS:ID:xxx key = self.__PREFIX + ':' + str(course_id) self.__conn.set(key, CourseStatus.CantJoinIn) def waiting(self, course_id): """ 在房间等待中,未开始上课 :return: """ # format: STATUS:LESSON_STATUS:ID:xxx key = self.__PREFIX + ':' + str(course_id) self.__conn.set(key, CourseStatus.Waiting)
class RedisForInLesson: """ 封装有关用户上课情况的数据库操作 key format: STATUS:IN_LESSON:UID:xxx 存储的是一个map |- uid |- course_id |- lesson_id key format: STATUS:LESSON_USER:LESSON_ID:xxx 存储的是一个set,存储用户的uid """ __IN_LESSON_PRIMARY_KEY = 'UID' __IN_LESSON_TABLE_NAME = 'IN_LESSON' __IN_LESSON_PREFIX = REDIS_DB_NAME + ':' + __IN_LESSON_TABLE_NAME + ':' + __IN_LESSON_PRIMARY_KEY __LESSON_USER_PRIMARY_KEY = 'LESSON_ID' __LESSON_USER_TABLE_NAME = 'LESSON_USER' __LESSON_USER_PREFIX = REDIS_DB_NAME + ':' + __LESSON_USER_TABLE_NAME + ':' + __LESSON_USER_PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def joinLesson(self, uid, course_id, lesson_id): """ 插入一条用户上课记录 当用户退出该课堂的话 需要删除该条记录 :param uid: 用户唯一标识 :param course_id: 课程唯一标识 :param lesson_id: 课程下课堂唯一标识 :return: """ # format: STATUS:LESSON_STATUS:UID:xxx key = self.__IN_LESSON_PREFIX + ':' + str(uid) record_data = { 'uid': uid, 'course_id': course_id, 'lesson_id': lesson_id } self.__conn.hmset(key, record_data) # format: STATUS:LESSON_USER:LESSON_ID:xxx key = self.__LESSON_USER_PREFIX + ':' + str(lesson_id) self.__conn.sadd(key, str(uid)) def quitLesson(self, uid): """ 用户退出当前课堂 把该key删除 :param uid: 用户唯一标识 :return: """ # format: STATUS:LESSON_STATUS:UID:xxx key = self.__IN_LESSON_PREFIX + ':' + str(uid) lesson_id = self.getLessonID(uid=str(uid)) self.__conn.delete(key) # format: STATUS:LESSON_USER:LESSON_ID:xxx key = self.__LESSON_USER_PREFIX + ':' + str(lesson_id) self.__conn.srem(key, str(uid)) def getLessonUsersUID(self, lesson_id): """ 获取参与该课的所有用户ID :param lesson_id: 课程下课堂唯一标识 :return: """ # format: STATUS:LESSON_USER:LESSON_ID:xxx key = self.__LESSON_USER_PREFIX + ':' + str(lesson_id) uid_arr = self.__conn.smembers(key) return uid_arr def isInLesson(self, uid): """ 查询用户是否在上课 :param uid: 用户唯一标识 :return: True - 在课室中/正在上课(即Waiting或Online状态) False - 空闲状态 """ # format: STATUS:LESSON_STATUS:UID:xxx key = self.__IN_LESSON_PREFIX + ':' + str(uid) return self.__conn.hexists(key) def getLessonID(self, uid): """ 获取该用户当前课堂的id :param uid: 用户唯一标识 :return: id - 存在(在课室中/正在上课) None - 不存在(空闲状态) """ # format: STATUS:LESSON_STATUS:UID:xxx key = self.__IN_LESSON_PREFIX + ':' + str(uid) return self.__conn.hget(key, 'lesson_id')
class RedisForUserStatus: """ 封装有关用户的各种状态的数据库操作 key format: STATUS:USER_STATUS:UID:xxx 存储的是一个值UserStatus(参考edu.py) """ __PRIMARY_KEY = 'UID' __TABLE_NAME = 'USER_STATUS' __PREFIX = REDIS_DB_NAME + ':' + __TABLE_NAME + ':' + __PRIMARY_KEY def __init__(self): self.__conn = Redis().conn def signUp(self, uid): """ 用户注册 :param uid: 用户唯一标识 :return: """ # format: STATUS:USER_STATUS:UID:xxx key = self.__PREFIX + ':' + str(uid) self.__conn.set(key, UserStatus.Free) def getUserStatus(self, uid): """ 获取当前课程状态 :param uid: 用户唯一标识 :return: """ # format: STATUS:USER_STATUS:UID:xxx key = self.__PREFIX + ':' + str(uid) if not self.__conn.exists(key): self.signUp(uid=uid) return int(self.__conn.get(key)) def free(self, uid): """ 空闲 :param uid: 用户唯一标识 :return: """ # format: STATUS:User_STATUS:UID:xxx key = self.__PREFIX + ':' + str(uid) self.__conn.set(key, UserStatus.Free) def inRoom(self, uid): """ 在房间中 :param uid: 用户唯一标识 :return: """ # format: STATUS:LESSON_STATUS:UID:xxx key = self.__PREFIX + ':' + str(uid) self.__conn.set(key, UserStatus.InRoom) def inClass(self, uid): """ 在课堂中 :param uid: 用户唯一标识 :return: """ # format: STATUS:LESSON_STATUS:UID:xxx key = self.__PREFIX + ':' + str(uid) self.__conn.set(key, UserStatus.InClass)