본문 바로가기

자기계발/데이터사이언스

[파이썬] 줌(zoom) 수업 출석 체크 프로그램

반응형

(학교에서 수강하는 프로그래밍 과목의 과제를 일부 변형하였습니다.)

 

이번 글에서는 줌(zoom)으로 수업을 진행했을 때 수집되는 강의 접속 기록을 이용하여 출석체크를 하는 프로그램을 소개하고자 한다.  이 프로그램은 파이썬으로 만들었다.

 

 

 

요즘 코로나 19로 인해 대학교 수업은 물론 초, 중, 고등학교도 최근 온라인으로 개학을 했다. 

비대면 강의이므로 출석 체크를 보통의 대면 방식과는 다르게 해야할 것이다.

내가 수강하는 과목은 실시간으로 줌(zoom) 프로그램을 이용하여 수업을 진행한다.

이런 경우 출석체크는 전체 수업시간 중 얼마나 수업을 들었는지를 확인하여 그 기준을 넘기면 출석 인정을, 그 기준을 넘기지 못하면 결석 처리하는 방법으로 해야할 것이다.

 

 

강의 접속 기록

: 학생 ID, 접속 시작 시간, 접속 종료 시간이 csv 파일로 저장됨. 

 

출석 인정 조건

 : 75분 수업(11:00 ~ 12:15) 중 65분 이상 수업을 들었으면 출석한 것으로 처리

 

고려해야할 점

 - 한 학생이 여러 기계를 이용해서 수강한 경우, 강의 접속 기록에 각각 따로 저장되어 있음. 두 대의 기기에서 같은 시간에 접속했으면 하나의 기계만 수업시간으로 인정해야함.

 - 접속 기록 시간은 초 단위. 접속 시작 시간부터 접속 종료 시간 직전까지 접속했다고 가정. 예) 11:30:00 ~ 11:30:05 이면 접속시간이 4초임.

 

함수 입출력 조건

 - check_attendance( 파일 이름, (월, 일), 학생 ID)

 - 입력 : 파일 이름, 날짜, 학생 ID

 - 출력 : 출석/결석 (bool)

 

대략적인 알고리즘(목표)

  1) 파일 불러오기

  2) 입력값의 날짜, id와 맞는 데이터(시작 시간, 끝 시간)를 가져오기

  3) 수업시간(11:00:00 ~ 12:15:00)을 초단위로 쪼개서, 그 초 만큼의 빈 리스트를 생성.

  4) 2)의 시작 시간, 끝 시간을 초 단위로 바꾸어서 그걸 인덱싱이라 생각하고 3)의 리스트에 1을 넣음.

  5) 한 id당 여러 접속기록이 존재하면 그 데이터를 다 4)로 진행.

  6) 리스트 안의 1의 개수 >= 65 * 60  이면 True 반환, 아니면 False 반환. 

  즉, 11시부터 12시15분까지 1*3600 + 15*60 초 이므로, 그만큼의 빈 칸을 만들어서 입력 날짜, 아이디에 맞는 데이터(시작시간, 끝시간)에 맞게 빈 칸을 1로 채운다. 마지막으로 1의 개수를 새서 65*60개(65분) 이상이면 출석 인정!

 

 

코드(파이썬 python)

check_attendance 함수 정의. 파일 이름, 날짜(튜플 형태로), 아이디 입력.

def check_attendance(file_name, month_day, id):

 

time이랑 datetime module 불러오기.

    import time
    import datetime

 

파일 이름에 맞는 csv파일을 불러와서 csv_data에 리스트 형태로 저장.

    with open('각자 파일 저장된 주소/' + file_name) as file:
        csv_data = []
        for line in file.readlines():
            csv_data.append(line.split(','))

 

csv파일에는 행마다 id, begin, end가 ',' 로 구분되어 있음.

예) 10, 2020/03/23 10:45:57, 2020/03/23 12:13:57

이 행이 csv_data리스트에는 한 값으로 들어감.

리스트 각 값마다 아이디, 날짜, 시작시간, 종료시간을 뽑아냄.

    #id
    student_id = []
    for i in range(1, len(csv_data)):
        student_id.append(int(csv_data[i][0][:]))

    # month
    month = []
    b = ''
    for i in range(1, len(csv_data)):
        a = csv_data[i][1]
        month.append(int(a[5:7]))

    # day
    day = []
    b = ''
    for i in range(1, len(csv_data)):
        a = csv_data[i][1]
        day.append(int(a[8:10]))

    # begin
    t_begin = []
    for i in range(1, len(csv_data)):
        a = csv_data[i][1]
        b = datetime.datetime.strptime(a, '%Y/%m/%d %H:%M:%S')
        t_begin.append(b)


    # end
    t_end = []
    for i in range(1, len(csv_data)):
        a = csv_data[i][2][:-1]
        b = datetime.datetime.strptime(a, '%Y/%m/%d %H:%M:%S')
        t_end.append(b)

 

이제 입력값(날짜, 아이디)에 대한 데이터를 위에서 가져온다.

그 전에 입력 인자의 타입이 맞는지 확인하고, 입력 날짜가 수업을 진행한 날짜인지 확인한다.

    #입력 인자의 타입 확인하기
    if type(id) == int and type(month_day[0]) == int and type(month_day[1]) == int:
        pass
    else:
        raise TypeError


    #month, day 유효한지 확인하기
    if month_day[0] in month and month_day[1] in day:
        pass
    else:
        raise ValueError

 

입력값(날짜, 아이디)에 맞는 행을 인덱싱 해온다.

    #id에 맞는 id와 그 날짜에 맞는 index 가져오기
    index_id = []
    for i in range(len(student_id)):
        if student_id[i] == id and month[i] == month_day[0] and day[i] == month_day[1]:
            index_id.append(i)

 

수업들은 시간을 담을 빈 리스트를 생성한다. 리스트의 길이는 수업 시간 길이를 초로 환산한 만큼의 길이를 갖는다.

    #total 빈리스트 생성
    total = []
    for i in range(3600*1 + 60*15):
        total.append('')

 

시작 시간, 끝 시간을 초로 환산하고(11시 정각을 0초로 환산) 위에서 생성한 total 리스트에 맞는 자리에 1로 채워준다.

    #시간 시작 끝 넣기
    for i in index_id:
        #시작시간과 끝시간을 초로 바꾸기, 11시 정각을 0초로.
        a = t_begin[i]
        b = (a.hour-11)*3600 + a.minute*60 + a.second

        c = t_end[i]
        d = (c.hour-11)*3600 + c.minute*60 + c.second

        #11시 이전, 12시 15분 이후는 생각하지 않음.
        if b <= 0:
            b = 0

        if d <= 0:
            d = 0

        if b >= 3600+15*60:
            b = 3600+15*60

        if d >= 3600+15*60:
            d = 3600+15*60

        for j in range(b,d):
            total[j] = 1

한 아이디 별로 여러번 접속했을 수도 있으니깐 각각의 기록에 대해서 반복한다. 1이 이미 채워져있어도 그 위에 1을 덮어 씌우는 것이므로 중복을 걸러낼 수 있다.

 

마지막으로 total 리스트에 들어있는 1의 개수를 count해서 65*60개보다 많으면 True 반환.

    if total.count(1) >= 65*60:
        return True
    else:
        return False

 

 

 

위에서 말했듯이, 요즘 학교에서 듣는 파이썬 프로그래밍 과목의 과제였다. 생각해보니깐 조교님이 직접 출석체크 하려고 만들었다가 과제로 내버린 것 같은 느낌이 든다.

처음 문제를 보고 그냥 접속 시작~ 끝 사이의 길이 구해서 그게 65분보다 길면 True 반환하면 될 것 같았는데, 여러 기기에서 접속한 값들을 처리해야 해서 위와 같은 방법을 생각하게 되었다.

 

반응형