def handleCommandGetStudentConc(server, json_obj):
    """ 获取指定学生的专注度信息

    :param server: socket服务端
    :param json_obj:|- command
                    |- account_type
                    |- timestamp
                    |- course_id
                    |- lesson_id
                    |- uid
                    |- username
    :return:
    """
    # 全班专注度信息汇总
    if json_obj['checked_uid'] == 'lesson':
        return_data = None
    else:
        # json: uid、course_id、lesson_id、begin_timestamp、end_timestamp、conc_score
        record = RedisForConc().getLastConcRecordByUid(
            lesson_id=json_obj['lesson_id'], uid=json_obj['checked_uid'])
        if record is not None:
            return_data = {
                'command': TransportCmd.GetStudentConc,
                'course_id': record['course_id'],
                'lesson_id': record['lesson_id'],
                'checked_uid': record['uid'],
                'concentration_value': int(record['conc_score'] * 100),
                'concentration_timestamp': record['end_timestamp']
            }

            reply(server.request, return_data)
def raiseHand(server, json_obj):
    lesson_id = json_obj["lesson_id"]
    student_id = json_obj["uid"]

    speech_status = getSpeechStatus(
        connection_pool=server.lesson_connection_pool, uid=student_id)
    if speech_status == SpeechStatus.InSpeech:
        json_obj["raise_hand_err"] = RaiseHandError.InSpeechError
    elif speech_status == SpeechStatus.Applying:
        json_obj["raise_hand_err"] = RaiseHandError.ApplyingError
    else:
        json_obj["raise_hand_err"] = RaiseHandError.NoError
        # 修改服务器内存中的状态
        setSpeechStatus(connection_pool=server.lesson_connection_pool,
                        uid=student_id,
                        speech_status=SpeechStatus.Applying)
        # 转发给老师
        connection = findTeacherConnectionInLesson(
            connection_pool=server.lesson_connection_pool, lesson_id=lesson_id)
        send(connection_pool=server.paint_connection_pool,
             connection=connection,
             data=json_obj)

    # 回复请求
    reply(server.request, json_obj)
def handleCommandCreateLesson(server, json_obj):
    """ 创建课堂

    :param server: socket服务端
    :param json_obj:|- command
                    |- account_type
                    |- course_id
                    |- course_name
                    |- uid
                    |- username
    :return:
    """
    # 检查是否可以创建课堂
    # 条件为:当前课程未开课 且 教师当前未在上课状态中
    # 若符合条件,返回新建课堂的信息
    # 若不符合,则返回正在上课的课堂信息
    course_status = RedisForCourseStatus().getCourseStatus(
        course_id=json_obj['course_id'])
    user_status = RedisForUserStatus().getUserStatus(uid=json_obj['uid'])
    if course_status == CourseStatus.OffLine and user_status == UserStatus.Free:
        lesson = LessonService().createLesson(course_id=json_obj['course_id'],
                                              teacher_id=json_obj['uid'])
        RedisForLessonStatus().createLesson(lesson_id=str(lesson.id))
        RedisForCourse().updateLesson(course_id=json_obj['course_id'],
                                      lesson_id=str(lesson.id))
        RedisForCourseStatus().waiting(course_id=json_obj['course_id'])
        is_succeed = True
    else:
        lesson_id = RedisForInLesson().getLessonID(uid=json_obj['uid'])
        lesson = LessonService().getLessonByLessonId(lesson_id=lesson_id)
        is_succeed = False

    # 创建结果返回
    lesson_id = 'None'
    course_id = 'None'
    course_name = 'None'
    teacher_id = 'None'
    teacher_name = 'None'
    create_timestamp = -1
    # 若返回的lesson为None
    # 即说明了课堂创建失败
    if lesson is not None:
        lesson_id = lesson.id
        course_id = lesson.course.id
        course_name = lesson.course.name
        teacher_id = lesson.teacher.id
        teacher_name = lesson.teacher.name
        create_timestamp = lesson.create_timestamp
    return_data = {
        'command': TransportCmd.CreateLesson,
        'is_succeed': is_succeed,
        'lesson_id': str(lesson_id),
        'course_id': str(course_id),
        'course_name': course_name,
        'teacher_id': str(teacher_id),
        'teacher_name': teacher_name,
        'create_timestamp': create_timestamp,
    }
    reply(server.request, return_data)
def handleCommandRefreshOnlineList(server, json_obj):
    """ 处理在线列表的更新工作

    :param server: socket服务端
    :param json_obj:|- command
                    |- account_type
                    |- timestamp
                    |- course_id
                    |- lesson_id
                    |- uid
                    |- username
                    |- online_list
                    |- need_username_json
    """
    # 准备用户名列表
    username_json = dict()
    has_username_json = False
    if json_obj['need_username_json']:
        has_username_json = True
        tuple_list = CourseService().getAllUsername(
            course_id=json_obj['course_id'])
        for data in tuple_list:
            # data是一个元组(uid, username)
            username_json.setdefault(str(data[0]), data[1])

    # 计算在线列表
    old_online_list = json_obj['online_list']
    new_online_list = RedisForOnlineList().getOnlineList(
        lesson_id=json_obj['lesson_id'])

    # new_online_list中有而old_online_list中没有的
    add_list = list(set(new_online_list).difference(set(old_online_list)))
    # old_online_list中有而new_online_list中没有的
    remove_list = list(set(old_online_list).difference(set(new_online_list)))

    return_data = {
        'command': TransportCmd.RefreshOnlineList,
        'lesson_id': json_obj['lesson_id'],
        'course_id': json_obj['course_id'],
        'has_username_json': has_username_json,
        'username_json': username_json,
        'online_list': new_online_list,
        'add_list': add_list,
        'remove_list': remove_list
    }

    reply(server.request, return_data)
def handleCommandQuitLesson(server, json_obj):
    """ 退出课堂

    :param server: socket服务端
    :param json_obj:|- command
                    |- account_type
                    |- timestamp
                    |- course_id
                    |- lesson_id
                    |- uid
                    |- username
    :return:
    """
    # 更新用户状态
    RedisForUserStatus().free(uid=json_obj['uid'])
    # 清除redis缓存
    RedisForInLesson().quitLesson(uid=json_obj['uid'])

    # 给所有课堂中的人发送信息
    return_data = {
        'command': TransportCmd.QuitLesson,
    }
    reply(server.request, return_data)
def createPaintConnection(server, json_obj):
    course_id = json_obj["course_id"]
    lesson_id = json_obj["lesson_id"]
    uid = json_obj["uid"]
    account_type = json_obj["account_type"]

    # 长连接信息
    connection = {
        "uid": uid,
        "course_id": course_id,
        "lesson_id": lesson_id,
        "socket": server.request
    }

    # 信息保存到内存
    server.paint_connection_pool.append(connection)

    # 检测是否需要同步
    lesson = findLessonByLessonId(lessons=server.lessons, lesson_id=lesson_id)
    if lesson_id is not None:
        for paint_command in lesson["paint_command_pool"]:
            reply(request=server.request, data=paint_command)

    print(server.paint_connection_pool)
def handleCommandJoinInLesson(server, json_obj):
    """ 加入课堂

    :param server: socket服务端
    :param json_obj:|- command
                    |- account_type
                    |- course_id
                    |- course_name
                    |- uid
                    |- username
    :return:
    """
    lesson_id = 'None'
    course_id = 'None'
    course_name = 'None'
    teacher_id = 'None'
    teacher_name = 'None'
    create_timestamp = -1
    begin_timestamp = -1

    # 先判断课程状态看是该课程是否正在上课
    course_status = RedisForCourseStatus().getCourseStatus(
        course_id=json_obj['course_id'])
    if course_status != CourseStatus.OffLine:
        if course_status == CourseStatus.CantJoinIn and json_obj[
                'account_type'] == AccountType.Student:
            pass
        else:
            lesson_id = RedisForCourse().getLastlyLessonID(
                course_id=json_obj['course_id'])
            lesson = LessonService().getLessonByLessonId(lesson_id=lesson_id)
            RedisForInLesson().joinLesson(uid=json_obj['uid'],
                                          course_id=json_obj['course_id'],
                                          lesson_id=str(lesson_id))
            # 根据课堂状态调整用户当前状态
            if course_status == CourseStatus.Waiting:
                RedisForUserStatus().inRoom(uid=json_obj['uid'])
            elif course_status == CourseStatus.OnLine or course_status == CourseStatus.CantJoinIn:
                RedisForUserStatus().inClass(uid=json_obj['uid'])

            # 长连接信息存到内存连接池
            server.socket_type = 'lesson'
            conn = {
                'uid': json_obj['uid'],
                'account_type': json_obj['account_type'],
                'course_id': str(lesson.course.id),
                'lesson_id': str(lesson.id),
                'socket': server.request
            }
            # 如果该信息已经存在
            server.lesson_connection_pool.append(conn)

            lesson_id = lesson.id
            course_id = lesson.course.id
            course_name = lesson.course.name
            teacher_id = lesson.teacher.id
            teacher_name = lesson.teacher.name
            create_timestamp = lesson.create_timestamp
            begin_timestamp = lesson.begin_timestamp

    # 创建结果返回
    return_data = {
        'command': TransportCmd.JoinInLesson,
        'course_status': course_status,
        'course_id': str(course_id),
        'course_name': course_name,
        'lesson_id': str(lesson_id),
        'teacher_id': str(teacher_id),
        'teacher_name': teacher_name,
        'create_timestamp': create_timestamp,
        'begin_timestamp': begin_timestamp
    }
    reply(server.request, return_data)
def handleCommandTryToJoinIn(server, json_obj):
    """ 学生进入课堂前的检测

    :param server: socket服务端
    :param json_obj:|- command
                    |- account_type
                    |- uid
                    |- username
    :return:
    """
    # 当前是否在上课状态中
    # 若是,则返回正在上课的课堂的信息
    # 若不是,则直接进入选定的课堂
    user_status = RedisForUserStatus().getUserStatus(uid=json_obj['uid'])
    if user_status == UserStatus.Free:
        lesson_id = 'None'
        course_id = 'None'
        course_name = 'None'
        teacher_id = 'None'
        teacher_name = 'None'
        create_timestamp = -1
        begin_timestamp = -1

        course_status = RedisForCourseStatus().getCourseStatus(
            course_id=json_obj['course_id'])
        if course_status != CourseStatus.OffLine:
            course_status = RedisForCourseStatus().getCourseStatus(
                course_id=json_obj['course_id'])
            lesson_id = RedisForCourse().getLastlyLessonID(
                course_id=json_obj['course_id'])
            lesson = LessonService().getLessonByLessonId(lesson_id=lesson_id)
            RedisForInLesson().joinLesson(uid=json_obj['uid'],
                                          course_id=json_obj['course_id'],
                                          lesson_id=lesson_id)

            # 根据课堂状态调整用户当前状态
            if course_status == CourseStatus.Waiting:
                RedisForUserStatus().inRoom(uid=json_obj['uid'])
            elif course_status == CourseStatus.OnLine or course_status == CourseStatus.CantJoinIn:
                RedisForUserStatus().inClass(uid=json_obj['uid'])

            # 长连接信息存到内存连接池
            server.socket_type = 'lesson'
            conn = {
                'uid': json_obj['uid'],
                'account_type': json_obj['account_type'],
                'course_id': str(lesson.course.id),
                'lesson_id': str(lesson.id),
                'socket': server.request
            }
            # 如果该信息已经存在
            server.lesson_connection_pool.append(conn)

            lesson_id = lesson.id
            course_id = lesson.course.id
            course_name = lesson.course.name
            teacher_id = lesson.teacher.id
            teacher_name = lesson.teacher.id
            create_timestamp = lesson.create_timestamp
            begin_timestamp = lesson.begin_timestamp

        # 创建结果返回
        return_data = {
            'command': TransportCmd.JoinInLesson,
            'course_status': course_status,
            'course_id': str(course_id),
            'course_name': course_name,
            'lesson_id': str(lesson_id),
            'teacher_id': str(teacher_id),
            'teacher_name': teacher_name,
            'create_timestamp': create_timestamp,
            'begin_timestamp': begin_timestamp
        }
    else:
        # 返回正在上课的信息
        lesson_id = RedisForInLesson().getLessonID(uid=json_obj['uid'])
        lesson = LessonService().getLessonByLessonId(lesson_id=lesson_id)

        return_data = {
            'command': TransportCmd.TryToJoinIn,
            'lesson_id': str(lesson.id),
            'course_id': str(lesson.course.id),
            'course_name': lesson.course.name,
            'teacher_id': str(lesson.teacher.id),
            'teacher_name': lesson.teacher.name,
            'create_timestamp': lesson.create_timestamp,
        }

    reply(server.request, return_data)