diff --git a/README.md b/README.md index a561ae5..39cb5c4 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# Bot_Upsolving \ No newline at end of file +# Bot_Upsolving + +Bot_Upsolving é um projeto para editar planilha de Upsolving da ime++ através de um bot do telegram, facilitando o acompanhamento dos contests feitos. + +## Como usar + +1- Crie uma aba para os meta dados na planilha, como a quantidade de usuários e de questões +2- Ajuste esses dados inicialmente, provavelmente ambos com o valor 0 +3- Ajuste as constantes no arquivo google_sheets_constants.py com os valores certos para essa nova planilha \ No newline at end of file diff --git a/google_sheets_constants.py b/google_sheets_constants.py index fc4a58b..fca9134 100644 --- a/google_sheets_constants.py +++ b/google_sheets_constants.py @@ -1,8 +1,13 @@ UPSOLVING_TAB_NAME = "Contests" +METADATA_TAB_NAME = "Meta Data" +USERS_COLUMN_SIZE = 35 +USERS_QUANTITY_ROW = 1 +USERS_QUANTITY_COLUMN_ID = 1 +PROBLEMS_QUANTITY_ROW = 2 +PROBLEMS_QUANTITY_COLUMN_ID = 1 USERS_ROW = 2 +PROBLEM_COUNTER_ROW = 3 USERS_START_COLUMN_ID = 7 -USERS_END_COLUMN_ID = 18 PROBLEMS_START_ROW = 4 -PROBLEMS_END_ROW = 900 CONTESTS_COLUMN = "A" PROBLEMS_COLUMN = "G" \ No newline at end of file diff --git a/google_sheets_utilities.py b/google_sheets_utilities.py index f5899fa..0e41bc2 100644 --- a/google_sheets_utilities.py +++ b/google_sheets_utilities.py @@ -3,30 +3,66 @@ def int_to_column(id): ''' Pega uma ID de coluna (começando por 0) Retorna a coluna na notação A1 (até ZZ) ''' + if id < 26: return chr(ord('A') + id) else: return chr(ord('A') + int(id / 26) - 1) + chr(ord('A') + id - int(id / 26) * 26) -def get_cells(sheet, sample_spread_sheet_id, range): - ''' Pega a ID da tabela e o range na notação "p1!A1:ZZ2" +def get_cells(sheet, spreadsheet_id, range): + ''' Pega a ID da planilha e o range na notação "p1!A1:ZZ2" Retorna uma matriz das células desse range ''' + request = sheet.values().get( - spreadsheetId = sample_spread_sheet_id, + spreadsheetId = spreadsheet_id, range = range ).execute() return request.get('values', []) -def get_user_column_id(sheet, sample_spread_sheet_id, user_name): - ''' Pega a ID da tabela e o nome do usuário +def get_users_end_column_id(sheet, spreadsheet_id): + ''' Pega a ID da planilha e retorna a ID da última coluna de usários ''' + + range = ( + METADATA_TAB_NAME + "!" + + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW) + ":" + + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW) + ) + users_quantity = get_cells(sheet, spreadsheet_id, range) + users_end_column_id = 0 + for i in users_quantity: + for j in i: + users_end_column_id = int(j) + USERS_START_COLUMN_ID - 1 + return users_end_column_id + + +def get_problems_end_row(sheet, spreadsheet_id): + ''' Pega a ID da planilha e retorna a última linha de problemas ''' + + range = ( + METADATA_TAB_NAME + "!" + + int_to_column(PROBLEMS_QUANTITY_COLUMN_ID) + str(PROBLEMS_QUANTITY_ROW) + ":" + + int_to_column(PROBLEMS_QUANTITY_COLUMN_ID) + str(PROBLEMS_QUANTITY_ROW) + ) + problems_quantity = get_cells(sheet, spreadsheet_id, range) + problems_end_row = 0 + for i in problems_quantity: + for j in i: + problems_end_row = int(j) + PROBLEMS_START_ROW - 1 + return problems_end_row + + +def get_user_column_id(sheet, spreadsheet_id, user_name): + ''' Pega a ID da planilha e o nome do usuário Retorna a ID da coluna do usuário ou None caso não seja encontrado ''' + + users_end_column_id = get_users_end_column_id(sheet, spreadsheet_id) range = (UPSOLVING_TAB_NAME + "!" + int_to_column(USERS_START_COLUMN_ID) + str(USERS_ROW) + ":" - + int_to_column(USERS_END_COLUMN_ID) + str(USERS_ROW)) + + int_to_column(users_end_column_id) + str(USERS_ROW)) users = get_cells(sheet, - sample_spread_sheet_id, + spreadsheet_id, range ) column = USERS_START_COLUMN_ID @@ -41,14 +77,16 @@ def get_user_column_id(sheet, sample_spread_sheet_id, user_name): return user_column -def get_contest_first_row(sheet, sample_spread_sheet_id, contest_name): - ''' Pega a ID da tabela e o nome da prova +def get_contest_first_row(sheet, spreadsheet_id, contest_name): + ''' Pega a ID da planilha e o nome da prova Retorna a primeira linha da prova ou None caso não seja encontrada ''' + + problems_end_row = get_problems_end_row(sheet, spreadsheet_id) range = (UPSOLVING_TAB_NAME + "!" + CONTESTS_COLUMN + str(PROBLEMS_START_ROW) + ":" - + CONTESTS_COLUMN + str(PROBLEMS_END_ROW)) + + CONTESTS_COLUMN + str(problems_end_row)) contests = get_cells(sheet, - sample_spread_sheet_id, + spreadsheet_id, range ) row = PROBLEMS_START_ROW @@ -63,14 +101,16 @@ def get_contest_first_row(sheet, sample_spread_sheet_id, contest_name): return contest_first_row -def get_contest_last_row(sheet, sample_spread_sheet_id, contest_name): - ''' Pega a ID da tabela e o nome da prova +def get_contest_last_row(sheet, spreadsheet_id, contest_name): + ''' Pega a ID da planilha e o nome da prova Retorna a última linha da prova ou None caso não seja encontrada ''' + + problems_end_row = get_problems_end_row(sheet, spreadsheet_id) range = (UPSOLVING_TAB_NAME + "!" + CONTESTS_COLUMN + str(PROBLEMS_START_ROW) + ":" - + CONTESTS_COLUMN + str(PROBLEMS_END_ROW)) + + CONTESTS_COLUMN + str(problems_end_row)) contests = get_cells(sheet, - sample_spread_sheet_id, + spreadsheet_id, range ) row = PROBLEMS_START_ROW @@ -89,19 +129,20 @@ def get_contest_last_row(sheet, sample_spread_sheet_id, contest_name): row = row + 1 if aux and (contest_last_row == None): - contest_last_row = PROBLEMS_END_ROW + contest_last_row = problems_end_row return contest_last_row -def get_problem_row(sheet, sample_spread_sheet_id, contest_first_row, contest_last_row, problem_name): - ''' Pega a ID da tabela, a primeira linha da prova, a última linha da prova e o nome da questão +def get_problem_row(sheet, spreadsheet_id, contest_first_row, contest_last_row, problem_name): + ''' Pega a ID da planilha, a primeira linha da prova, a última linha da prova e o nome da questão Retorna a linha da questão ou None caso não seja encontrada ''' + range = (UPSOLVING_TAB_NAME + "!" + PROBLEMS_COLUMN + str(contest_first_row) + ":" + PROBLEMS_COLUMN + str(contest_last_row)) problems = get_cells(sheet, - sample_spread_sheet_id, + spreadsheet_id, range ) row = contest_first_row @@ -113,4 +154,374 @@ def get_problem_row(sheet, sample_spread_sheet_id, contest_first_row, contest_la problem_row = row row = row + 1 - return problem_row \ No newline at end of file + return problem_row + + +def insert_columns(sheet, spreadsheet_id, tab_id , start_column_id , column_quantity): + ''' Pega a ID da planilha, a ID da aba da planilha, + a ID da coluna onde começará a inserção e a quantidade de colunas que quer-se inserir + A ID da aba esta no final do URL, logo depois do 'gid=' + Insere colunas vazias ''' + + request = { + "insertDimension": { + "range": { + "sheetId": tab_id , + "dimension": "COLUMNS", + "startIndex": start_column_id, + "endIndex": start_column_id + column_quantity + } + } + } + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def delete_columns(sheet, spreadsheet_id, tab_id , start_column_id , column_quantity): + ''' Pega a ID da planilha, a ID da aba da planilha, + a ID da coluna onde começará a deleção e a quantidade de colunas que quer-se deletar + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + request = { + "deleteDimension": { + "range": { + "sheetId": tab_id , + "dimension": "COLUMNS", + "startIndex": start_column_id, + "endIndex": start_column_id + column_quantity + } + } + } + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def format_problem_cells(sheet, spreadsheet_id, tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação no padrão dos problemas + Vermelho se tiver vazio, Verde se tiver preenchido por X e Branco caso contrário + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + request = [] + start_row = start_row - 1 + end_column_id = end_column_id + 1 + + # Deixa vermelho se a célula estiver vazia + request_body = { + "addConditionalFormatRule": { + "rule": { + "ranges":{ + "sheetId": tab_id, + "startRowIndex": start_row, + "endRowIndex": end_row, + "startColumnIndex": start_column_id, + "endColumnIndex": end_column_id + }, + "booleanRule": { + "condition": {"type": "BLANK"}, + "format": { + "backgroundColor": { + "red": 1, + "blue": 0.8, + "green": 0.8 + } + } + } + }, + "index": 0 + } + } + request.append(request_body) + + # Deixa verde quando estiver preenchido por X + request_body = { + "addConditionalFormatRule": { + "rule": { + "ranges":{ + "sheetId": tab_id, + "startRowIndex": start_row, + "endRowIndex": end_row, + "startColumnIndex": start_column_id, + "endColumnIndex": end_column_id + }, + "booleanRule": { + "condition": { + "type": "TEXT_CONTAINS", + "values": [{"userEnteredValue": "X"}] + }, + "format": { + "backgroundColor": { + "red": 0.72, + "blue": 0.81, + "green": 0.88 + } + } + } + }, + "index": 0 + } + } + request.append(request_body) + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def change_column_size(sheet, spreadsheet_id, tab_id, start_column_id, column_quantity, size): + ''' Pega a ID da planilha, a ID da aba da planilha, + a ID da coluna onde começará a formatação, a quantidade de colunas a serem formatadas + e o tamanho desejado para as colunas + Deixa as colunas selecionadas com o tamanho selecionado + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + end_column_id = start_column_id + column_quantity + request = [{ + "updateDimensionProperties": { + "range": { + "sheetId": tab_id, + "dimension": "COLUMNS", + "startIndex": start_column_id, + "endIndex": end_column_id + }, + "properties": { + "pixelSize": size + }, + "fields": "pixelSize" + } + }] + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def centralize_cells_request(tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + Retorna um pedido para centralizar o texto dessas células + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + start_row = start_row - 1 + end_column_id = end_column_id + 1 + request = { + "repeatCell": + { + "cell": + { + "userEnteredFormat": + { + "horizontalAlignment": "CENTER", + "verticalAlignment": "MIDDLE" + } + }, + "range": + { + "sheetId": tab_id, + "startRowIndex": start_row, + "endRowIndex": end_row, + "startColumnIndex": start_column_id, + "endColumnIndex": end_column_id + }, + "fields": "userEnteredFormat" + } + } + return request + + +def centralize_cells(sheet, spreadsheet_id, tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + O texto dessas células será centralizado + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + request = [centralize_cells_request(tab_id, start_row, start_column_id, end_row, end_column_id)] + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def bold_cells_request(tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + Retorna um pedido para colocar em negrito o texto dessas células + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + start_row = start_row - 1 + end_column_id = end_column_id + 1 + request = { + "repeatCell": { + "range":{ + "sheetId": tab_id, + "startRowIndex": start_row, + "endRowIndex": end_row, + "startColumnIndex": start_column_id, + "endColumnIndex": end_column_id + }, + "cell": { + "userEnteredFormat": { + "textFormat": { + "bold" : True + } + } + }, + "fields": "userEnteredFormat.textFormat" + } + } + return request + + +def bold_cells(sheet, spreadsheet_id, tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + O texto dessas células será colocado em negrito + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + request = [bold_cells_request(tab_id, start_row, start_column_id, end_row, end_column_id)] + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def external_border_request(tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + Retorna um pedido para tornar a borda externa do grupo de células escolhido realçada + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + start_row = start_row - 1 + end_column_id = end_column_id + 1 + request = { + "updateBorders": { + "range":{ + "sheetId": tab_id, + "startRowIndex": start_row, + "endRowIndex": end_row, + "startColumnIndex": start_column_id, + "endColumnIndex": end_column_id + }, + "top": {"style":"SOLID"}, + "bottom": {"style":"SOLID"}, + "left": {"style":"SOLID"}, + "right": {"style":"SOLID"} + } + } + return request + + +def external_border(sheet, spreadsheet_id, tab_id, start_row, start_column_id, end_row, end_column_id): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + A borda externa do grupo de células escolhido será realçada + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + start_row = start_row - 1 + end_column_id = end_column_id + 1 + request = [external_border_request(tab_id,start_row, start_column_id, end_row, end_column_id)] + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def set_text_rotation_request(tab_id, start_row, start_column_id, end_row, end_column_id, angle): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + e quantos graus se deseja rotacionar o Texto das células selecionadas + Retorna um pedido para rotacionar o Texto das células selecionadas nos graus selecionados + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + start_row = start_row - 1 + end_column_id = end_column_id + 1 + request = { + "repeatCell": { + "range":{ + "sheetId": tab_id, + "startRowIndex": start_row, + "endRowIndex": end_row, + "startColumnIndex": start_column_id, + "endColumnIndex": end_column_id + }, + "cell": { + "userEnteredFormat": { + "textRotation": { + "angle" : angle + } + } + }, + "fields": "userEnteredFormat" + } + } + return request + + +def set_text_rotation(sheet, spreadsheet_id, tab_id, start_row, start_column_id, end_row, end_column_id, angle): + ''' Pega a ID da planilha, a ID da aba da planilha, + a linha e a ID da coluna onde começará a formatação + e a linha e a ID da coluna onde terminará a formatação + e quantos graus se deseja rotacionar o Texto das células selecionadas + Rotaciona o Texto das células selecionadas nos graus selecionados + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + request = [set_text_rotation_request(tab_id, start_row, start_column_id, end_row, end_column_id, angle)] + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + +def write_request(tab_id, row, column_id, text): + ''' Pega a ID da aba da planilha, a linha e a ID da coluna onde se quer escrever + e o texto que se quer colocar nesta célula + Retorna um pedido para escrever o texto na célula escolhida + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + row = row - 1 + request = { + "updateCells": + { + "rows": + { + "values": { + "userEnteredValue": { + "stringValue": text + } + } + }, + "fields": "userEnteredValue", + "start": { + "sheetId": tab_id, + "rowIndex": row, + "columnIndex": column_id + } + } + } + return request + + +def format_user_cells(sheet, spreadsheet_id, tab_id, row, column_id): + ''' Pega a ID da aba da planilha, a linha e a ID da coluna que se quer formatar + Deixa no formato dos usuários, deitado em 45º e centralizado + A ID da aba esta no final do URL, logo depois do 'gid=' ''' + + request = [{ + "repeatCell": { + "range":{ + "sheetId": tab_id, + "startRowIndex": row - 1, + "endRowIndex": row, + "startColumnIndex": column_id, + "endColumnIndex": column_id + 1 + }, + "cell": { + "userEnteredFormat": { + "horizontalAlignment": "CENTER", + "verticalAlignment": "MIDDLE", + "textRotation": { + "angle" : 45 + } + } + }, + "fields": "userEnteredFormat" + } + }] + body = {"requests": request} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() \ No newline at end of file diff --git a/problem_marker.py b/problem_marker.py deleted file mode 100644 index ea669e8..0000000 --- a/problem_marker.py +++ /dev/null @@ -1,30 +0,0 @@ -from google_sheets_utilities import* - -def mark_problem(sheet, SAMPLE_SPREADSHEET_ID, user_name, contest_name, problem_name): - user_column = get_user_column_id(sheet, SAMPLE_SPREADSHEET_ID, user_name) - if user_column == None: - print("user not found") - - else: - contest_first_row = get_contest_first_row(sheet, SAMPLE_SPREADSHEET_ID, contest_name) - contest_last_row = get_contest_last_row(sheet, SAMPLE_SPREADSHEET_ID, contest_name) - if contest_first_row == None: - print("contest not found") - - else: - problem_row = get_problem_row(sheet, - SAMPLE_SPREADSHEET_ID, - contest_first_row, - contest_last_row, - problem_name - ) - if problem_row == None: - print("problem not found") - - else: - request_upd = sheet.values().update( - spreadsheetId = SAMPLE_SPREADSHEET_ID, - range = UPSOLVING_TAB_NAME + "!" + int_to_column(user_column) + str(problem_row), - valueInputOption = "USER_ENTERED", - body = {"values":[['X']]} - ).execute() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7270494 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +google-api-python-client==2.5.0 +google-auth-httplib2==0.1.0 +google-auth-oauthlib==0.4.4 +python-telegram-bot==13.5 \ No newline at end of file diff --git a/user_manager.py b/user_manager.py new file mode 100644 index 0000000..225cd09 --- /dev/null +++ b/user_manager.py @@ -0,0 +1,195 @@ +from google_sheets_utilities import* +from google_sheets_constants import* + +def change_problem_cell(sheet, spreadsheet_id, user_name, contest_name, problem_name, mark): + ''' Pega a ID da planilha, o nome do usuário, o nome da prova, o nome do problema e como se deseja marcar + Retorna uma string avisando que marcou a questão do jeito desejado no local desejado + ou avisa que o usuário, a prova ou a questão não foram encontrados ''' + + # Pegando a coluna do usuário + user_column = get_user_column_id(sheet, spreadsheet_id, user_name) + if user_column == None: + return "Usuário não encontrado" + + # Pegando as linhas da prova + contest_first_row = get_contest_first_row(sheet, spreadsheet_id, contest_name) + contest_last_row = get_contest_last_row(sheet, spreadsheet_id, contest_name) + if contest_first_row == None: + return "Prova não encontrada" + + # Pegando a linha do problema + problem_row = get_problem_row(sheet, + spreadsheet_id, + contest_first_row, + contest_last_row, + problem_name + ) + if problem_row == None: + return "Problema não encontrado" + + sheet.values().update( + spreadsheetId = spreadsheet_id, + range = UPSOLVING_TAB_NAME + "!" + int_to_column(user_column) + str(problem_row), + valueInputOption = "USER_ENTERED", + body = {"values":[[mark]]} + ).execute() + if mark == 'X': + return "Questão marcada!" + elif mark == 'N': + return "Questão marcada como 'por enquanto não'!" + else: + return "Questão desmarcada!" + + +def mark_problem(sheet, spreadsheet_id, user_name, contest_name, problem_name): + ''' Pega a ID da planilha, o nome do usuário, o nome da prova e o nome do problema + Retorna uma string avisando que marcou a questão feita no local desejado + ou avisa que o usuário, a prova ou a questão não foram encontrados ''' + + return change_problem_cell(sheet, spreadsheet_id, user_name, contest_name, problem_name, 'X') + + +def desmark_problem(sheet, spreadsheet_id, user_name, contest_name, problem_name): + ''' Pega a ID da planilha, o nome do usuário, o nome da prova e o nome do problema + Retorna uma string avisando que desmarcou a questão no local desejado + ou avisa que o usuário, a prova ou a questão não foram encontrados ''' + + return change_problem_cell(sheet, spreadsheet_id, user_name, contest_name, problem_name, '') + + +def not_for_now_problem(sheet, spreadsheet_id, user_name, contest_name, problem_name): + ''' Pega a ID da planilha, o nome do usuário, o nome da prova e o nome do problema + Retorna uma string avisando que marcou a questão com N no local desejado + ou avisa que o usuário, a prova ou a questão não foram encontrados ''' + + return change_problem_cell(sheet, spreadsheet_id, user_name, contest_name, problem_name, 'N') + + +def add_user(sheet, spreadsheet_id, tab_id, user_name): + ''' Pega a ID da planilha e o nome do novo usuário + Retorna uma string avisando que adcionou o usuário no início da aba de Upsolving + ou avisando que já tem um usuário com esse nome ''' + + user_exist = get_user_column_id(sheet, spreadsheet_id, user_name) + if(user_exist != None): + return "Já existe um usuário com esse nome" + + problems_end_row = get_problems_end_row(sheet, spreadsheet_id) + + # Pegando a quantidade de usuários + range = ( + METADATA_TAB_NAME + "!" + + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW) + ":" + + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW) + ) + users_quantity = 0 + cells = get_cells(sheet, spreadsheet_id, range) + for i in cells: + for j in i: + users_quantity = int(j) + + # Inserindo coluna no início + insert_columns(sheet, spreadsheet_id, tab_id, USERS_START_COLUMN_ID, 1) + + # Formatando a coluna caso seja o primeiro usuário a ser adicionado + if users_quantity == 0: + format_problem_cells( + sheet, spreadsheet_id, tab_id, + PROBLEMS_START_ROW, USERS_START_COLUMN_ID, + problems_end_row, USERS_START_COLUMN_ID + ) + change_column_size(sheet, spreadsheet_id, tab_id, USERS_START_COLUMN_ID, 1, USERS_COLUMN_SIZE) + format_user_cells(sheet, spreadsheet_id, tab_id, USERS_ROW, USERS_START_COLUMN_ID) + centralize_cells(sheet, spreadsheet_id, tab_id, USERS_ROW + 1, USERS_START_COLUMN_ID, problems_end_row, USERS_START_COLUMN_ID) + bold_cells(sheet, spreadsheet_id, tab_id, USERS_ROW, USERS_START_COLUMN_ID, PROBLEM_COUNTER_ROW, USERS_START_COLUMN_ID) + + # Colocando as bordas + range = ( + UPSOLVING_TAB_NAME + "!" + + CONTESTS_COLUMN + str(PROBLEMS_START_ROW + 1) + ":" + + CONTESTS_COLUMN + str(problems_end_row) + ) + cells = get_cells(sheet, spreadsheet_id, range) + start_row = PROBLEMS_START_ROW + end_row = PROBLEMS_START_ROW + requests = [] + for i in cells: + for j in i: + requests.append(external_border_request(tab_id, start_row, USERS_START_COLUMN_ID, end_row, USERS_START_COLUMN_ID)) + start_row = end_row + 1 + end_row = end_row + 1 + if problems_end_row >= PROBLEMS_START_ROW: + requests.append(external_border_request(tab_id, start_row, USERS_START_COLUMN_ID, problems_end_row, USERS_START_COLUMN_ID)) + requests.append(external_border_request(tab_id, USERS_ROW, USERS_START_COLUMN_ID, USERS_ROW, USERS_START_COLUMN_ID)) + body = {"requests": requests} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + # Inserindo o nome do usuário + sheet.values().update( + spreadsheetId = spreadsheet_id, + range = UPSOLVING_TAB_NAME + "!" + int_to_column(USERS_START_COLUMN_ID) + str(USERS_ROW), + valueInputOption = "USER_ENTERED", + body = {"values":[[user_name]]} + ).execute() + + # Inserindo lógica de contar questão + logica = ("=SE(ÉCÉL.VAZIA(" + int_to_column(USERS_START_COLUMN_ID) + str(USERS_ROW) + + "); ""; CONTAR.VAZIO(" + int_to_column(USERS_START_COLUMN_ID) + str(PROBLEMS_START_ROW) + ":" + + int_to_column(USERS_START_COLUMN_ID) + str(problems_end_row) +"))") + sheet.values().update( + spreadsheetId = spreadsheet_id, + range = UPSOLVING_TAB_NAME + "!" + int_to_column(USERS_START_COLUMN_ID) + str(PROBLEM_COUNTER_ROW), + valueInputOption = "USER_ENTERED", + body = {"values":[[logica]]} + ).execute() + + # Colocando N em todas as questões que existiam antes de adicionar este usuário + row = PROBLEMS_START_ROW + requests = [] + while row <= problems_end_row: + requests.append(write_request(tab_id,row,USERS_START_COLUMN_ID,"N")) + row = row + 1 + body = {"requests": requests} + sheet.batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute() + + # Atualizando a quantidade de usuários + new_users_quantity = users_quantity + 1 + sheet.values().update( + spreadsheetId = spreadsheet_id, + range = METADATA_TAB_NAME + "!" + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW), + valueInputOption = "USER_ENTERED", + body = {"values":[[new_users_quantity]]} + ).execute() + return "Adicionado!" + + +def delete_user(sheet, spreadsheet_id, tab_id, user_name): + ''' Pega a ID da planilha e o nome do usuário que quer deletar + Retorna uma string avisando que deletou a coluna do usuário + ou avisa que o usuário não foi encontrado ''' + + #deletando a coluna do usuário + user_column_id = get_user_column_id(sheet, spreadsheet_id, user_name) + if(user_column_id == None): + return "Usuário não encontrado" + + delete_columns(sheet, spreadsheet_id, tab_id, user_column_id, 1) + + # Atualizando a quantidade de usuários + range = ( + METADATA_TAB_NAME + "!" + + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW) + ":" + + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW) + ) + users_quantity = get_cells(sheet, spreadsheet_id, range) + new_users_quantity = 0 + for i in users_quantity: + for j in i: + new_users_quantity = int(j) - 1 + sheet.values().update( + spreadsheetId = spreadsheet_id, + range = METADATA_TAB_NAME + "!" + int_to_column(USERS_QUANTITY_COLUMN_ID) + str(USERS_QUANTITY_ROW), + valueInputOption = "USER_ENTERED", + body = {"values":[[new_users_quantity]]} + ).execute() + return "Deletado!" \ No newline at end of file