|
import requests |
|
import os |
|
import streamlit as st |
|
import math |
|
import re |
|
from io import BytesIO |
|
from reportlab.lib.pagesizes import letter |
|
from reportlab.platypus import SimpleDocTemplate, Paragraph |
|
from reportlab.lib.styles import getSampleStyleSheet |
|
from azure.cosmos import CosmosClient |
|
from dotenv import load_dotenv |
|
|
|
load_dotenv() |
|
|
|
def get_question_topics(): |
|
url = os.environ["BASE_URL"]+"/question-topics" |
|
headers = { |
|
"x-api-key": os.environ["API_KEY"] |
|
} |
|
try: |
|
response = requests.get(url,headers=headers) |
|
response.raise_for_status() |
|
return response.json()["output"] |
|
except Exception as e: |
|
print(f"Fehler beim Fetchen der Topics: {e}") |
|
st.error("Someting went wrong. Please try again later.", icon="🚨") |
|
|
|
def get_coding_task_topics(): |
|
url = os.environ["BASE_URL"]+"/coding-task-topics" |
|
headers = { |
|
"x-api-key": os.environ["API_KEY"] |
|
} |
|
try: |
|
response = requests.get(url,headers=headers) |
|
response.raise_for_status() |
|
return response.json()["output"] |
|
except Exception as e: |
|
print(f"Fehler beim Fetchen der Topics: {e}") |
|
st.error("Someting went wrong. Please try again later.", icon="🚨") |
|
|
|
def get_questions(topic): |
|
topic = topic.replace(" ", "%20") |
|
topic = topic.replace("&", "%26") |
|
url = os.environ["BASE_URL"]+"/questions"+f"?dimension={topic}" |
|
headers = { |
|
"x-api-key": os.environ["API_KEY"] |
|
} |
|
try: |
|
response = requests.get(url, data=topic, headers=headers) |
|
response.raise_for_status() |
|
|
|
return response.json()["output"] |
|
except Exception as e: |
|
print(f"Fehler beim Fetchen der Topics: {e}") |
|
st.error("Someting went wrong. Please try again later.", icon="🚨") |
|
|
|
def get_coding_tasks(topic): |
|
url = os.environ["BASE_URL"]+"/coding-tasks"+f"?topic={topic}" |
|
headers = { |
|
"x-api-key": os.environ["API_KEY"] |
|
} |
|
try: |
|
response = requests.get(url, data=topic, headers=headers) |
|
response.raise_for_status() |
|
print(response.json()) |
|
return response.json()["output"] |
|
except Exception as e: |
|
print(f"Fehler beim Fetchen der Topics: {e}") |
|
st.error("Someting went wrong. Please try again later.", icon="🚨") |
|
|
|
def load_topics_into_question_list(): |
|
st.session_state["current_page"] = 1 |
|
with st.spinner("Loading questions..."): |
|
for topic in st.session_state["loaded_questions"]: |
|
if topic["topic"] not in st.session_state["selected_topics"]: |
|
st.session_state["loaded_questions"].remove(topic) |
|
for topic in st.session_state["selected_topics"]: |
|
if topic not in [topic["topic"] for topic in st.session_state["loaded_questions"]]: |
|
question_element = {"topic": topic, "questions": get_questions(topic)} |
|
st.session_state["loaded_questions"].append(question_element) |
|
|
|
def load_topics_into_task_list(): |
|
st.session_state["current_page"] = 1 |
|
with st.spinner("Loading coding tasks..."): |
|
for topic in st.session_state["loaded_tasks"]: |
|
if topic["topic"] not in st.session_state["selected_task_topics"]: |
|
st.session_state["loaded_tasks"].remove(topic) |
|
for topic in st.session_state["selected_task_topics"]: |
|
if topic not in [topic["topic"] for topic in st.session_state["loaded_tasks"]]: |
|
question_element = {"topic": topic, "tasks": get_coding_tasks(topic)} |
|
st.session_state["loaded_tasks"].append(question_element) |
|
|
|
def add_question_to_interview(question): |
|
if question not in st.session_state["questions_for_interview"]: |
|
st.session_state["questions_for_interview"].append(question) |
|
else: |
|
print("Question already in list") |
|
|
|
def increment_page(): |
|
if st.session_state["current_page"] < math.ceil(len(st.session_state["questions_to_display"])/10): |
|
st.session_state["current_page"] += 1 |
|
|
|
def decrement_page(): |
|
if st.session_state["current_page"] > 1: |
|
st.session_state["current_page"] -= 1 |
|
|
|
def change_question_type(): |
|
st.session_state["current_page"] = 1 |
|
if st.session_state["question_type"] == "question": |
|
st.session_state["question_type"] = "coding_tasks" |
|
else: |
|
st.session_state["question_type"] = "question" |
|
|
|
def update_questions_and_tasks(): |
|
try: |
|
with st.spinner("Updating questions and tasks..."): |
|
client: CosmosClient = st.session_state["db"] |
|
database = client.get_database_client("assessment-database") |
|
container = database.get_container_client("assessments") |
|
assessment = st.session_state["assessment_db_object"] |
|
questions_for_db = [] |
|
for question in st.session_state["questions_for_interview"]: |
|
questions_for_db.append({"question": question["question"], "perfect_answer": question["perfect_answer"], "score": "", "evaluation": ""}) |
|
assessment["questions"] = questions_for_db |
|
tasks_for_db = [] |
|
for task in st.session_state["tasks_for_interview"]: |
|
tasks_for_db.append({"coding_task": task["task"], "perfect_solution": task["perfect_solution"], "score": "", "evaluation": ""}) |
|
assessment["coding_tasks"] = tasks_for_db |
|
assessment["process_status"] = "assessment_prepared" |
|
container.upsert_item(assessment) |
|
except Exception as e: |
|
print(f"Fehler beim Speichern der Fragen und Aufgaben: {e}") |
|
st.error("Someting went wrong. Please try again later.", icon="🚨") |
|
|
|
def fix_br_tags(input_string: str): |
|
return input_string.replace("<br>", "<br/>") |
|
|
|
def remove_html_tags(input_string: str): |
|
clean = re.compile('<.*?>') |
|
return re.sub(clean, '', input_string) |
|
|
|
if "topics" not in st.session_state: |
|
topics = list(set([topic["dimension"] for topic in get_question_topics() if topic["dimension"] != None])) |
|
st.session_state["topics"] = topics |
|
if "task_topics" not in st.session_state: |
|
topics = list(set([topic for topic in get_coding_task_topics() if topic != None])) |
|
st.session_state["task_topics"] = topics |
|
if "loaded_questions" not in st.session_state: |
|
st.session_state["loaded_questions"] = [] |
|
if "loaded_tasks" not in st.session_state: |
|
st.session_state["loaded_tasks"] = [] |
|
if "selected_topics" not in st.session_state: |
|
st.session_state["selected_topics"] = [] |
|
if "questions_to_display" not in st.session_state: |
|
st.session_state["questions_to_display"] = [] |
|
if "tasks_to_display" not in st.session_state: |
|
st.session_state["tasks_to_display"] = [] |
|
if "questions_for_interview" not in st.session_state: |
|
st.session_state["questions_for_interview"] = [] |
|
if "current_page" not in st.session_state: |
|
st.session_state["current_page"] = 1 |
|
if "question_type" not in st.session_state: |
|
st.session_state["question_type"] = "question" |
|
if "tasks_for_interview" not in st.session_state: |
|
st.session_state["tasks_for_interview"] = [] |
|
if "db" not in st.session_state: |
|
client = CosmosClient(os.environ["COSMOS_DB_ENDPOINT"], os.environ["COSMOS_DB_KEY"]) |
|
st.session_state["db"] = client |
|
if "assessment_db_object" not in st.session_state: |
|
if "assessment-id" in st.query_params: |
|
client: CosmosClient = st.session_state["db"] |
|
database = client.get_database_client("assessment-database") |
|
container = database.get_container_client("assessments") |
|
assessment = container.query_items(query="SELECT * FROM c WHERE c.id = @assessment_id", parameters=[dict(name="@assessment_id", value=st.query_params["assessment-id"]) ,], enable_cross_partition_query=True, max_item_count=1) |
|
st.session_state["assessment_db_object"] = list(assessment)[0] |
|
else: |
|
st.error("No assessment found. Please contact the side admin.", icon="🚨") |
|
st.stop() |
|
|
|
col1, col2 = st.columns([2, 1]) |
|
|
|
col1.title("Interview Preparation") |
|
col2.image("https://www.workgenius.com/wp-content/uploads/2023/03/WorkGenius_navy-1.svg") |
|
|
|
|
|
st.write("Assessment: "+st.session_state["assessment_db_object"]["assessment_title"]) |
|
|
|
type_col1, type_col2 = st.columns([1, 1]) |
|
|
|
with type_col1: |
|
st.button("Questions", key="question_button", on_click=change_question_type, disabled=True if st.session_state["question_type"] == "question" else False, use_container_width=True) |
|
with type_col2: |
|
st.button("Coding tasks", key="coding_tasks", on_click=change_question_type, disabled=True if st.session_state["question_type"] == "coding_tasks" else False, use_container_width=True) |
|
|
|
|
|
if st.session_state["question_type"] == "question": |
|
st.multiselect("Select the topics for the questions", st.session_state["topics"], key="selected_topics", default=None, on_change=load_topics_into_question_list) |
|
st.divider() |
|
if len(st.session_state["selected_topics"]) > 0: |
|
st.subheader("Questions to choose from:") |
|
st.write("Filter according to the difficulty of the questions:") |
|
st.checkbox("Easy", key="checkbox_filter_easy", value=True) |
|
st.checkbox("Medium", key="checkbox_filter_medium", value=True) |
|
st.checkbox("Hard", key="checkbox_filter_hard", value=True) |
|
st.write("Filter by the topic of the questions:") |
|
for topic in st.session_state["loaded_questions"]: |
|
st.checkbox(topic["topic"], key="checkbox_filter_"+topic["topic"], value=True) |
|
result_questions = [] |
|
for i, topic in enumerate(st.session_state["loaded_questions"]): |
|
if st.session_state["checkbox_filter_"+topic["topic"]]: |
|
for j, question in enumerate(topic["questions"]): |
|
if st.session_state["checkbox_filter_easy"] and question["difficulty"] == "Easy": |
|
result_questions.append(question) |
|
if st.session_state["checkbox_filter_medium"] and question["difficulty"] == "Medium": |
|
result_questions.append(question) |
|
if st.session_state["checkbox_filter_hard"] and question["difficulty"] == "Hard": |
|
result_questions.append(question) |
|
st.session_state["questions_to_display"] = result_questions |
|
if len(st.session_state["questions_to_display"]) > 0: |
|
nav_col1, nav_col2, nav_col3 = st.columns([1, 4, 1]) |
|
|
|
nav_col1.button("◀️", key="nav1", use_container_width=True, on_click=decrement_page, disabled=True if st.session_state["current_page"] == 1 else False) |
|
nav_col2.markdown(f"<div style='text-align: center;'>Page {str(st.session_state['current_page'])} / {str(math.ceil(len(st.session_state['questions_to_display'])/10))}</div>", unsafe_allow_html=True) |
|
nav_col3.button("▶️", key="nav2", use_container_width=True, on_click=increment_page, disabled=True if st.session_state["current_page"] == math.ceil(len(st.session_state["questions_to_display"])/10) else False) |
|
|
|
for i in range((st.session_state["current_page"]-1)*10, st.session_state["current_page"]*10 if st.session_state["current_page"]*10 < len(st.session_state["questions_to_display"]) else len(st.session_state["questions_to_display"])): |
|
col_1, col_2 = st.columns([7, 1]) |
|
with col_1: |
|
st.write(st.session_state["questions_to_display"][i]["question"]) |
|
with col_2: |
|
st.button("Select", disabled=True if st.session_state["questions_to_display"][i] in st.session_state["questions_for_interview"] else False ,key="select_button_"+str(i), on_click=add_question_to_interview, args=(st.session_state["questions_to_display"][i],)) |
|
else: |
|
st.multiselect("Select the topics for the coding tasks", options=st.session_state["task_topics"], key="selected_task_topics", default=None, on_change=load_topics_into_task_list) |
|
st.divider() |
|
if len(st.session_state["selected_task_topics"]) > 0: |
|
st.subheader("Coding tasks to choose from:") |
|
st.write("Filter by the topic of the coding task:") |
|
for topic in st.session_state["loaded_tasks"]: |
|
st.checkbox(topic["topic"], key="checkbox_filter_tasks_"+topic["topic"], value=True) |
|
result_tasks = [] |
|
for i, topic in enumerate(st.session_state["loaded_tasks"]): |
|
if st.session_state["checkbox_filter_tasks_"+topic["topic"]]: |
|
for j, task in enumerate(topic["tasks"]): |
|
result_tasks.append(task) |
|
st.session_state["tasks_to_display"] = result_tasks |
|
if len(st.session_state["tasks_to_display"]) > 0: |
|
nav_col1, nav_col2, nav_col3 = st.columns([1, 4, 1]) |
|
|
|
nav_col1.button("◀️", key="nav1", use_container_width=True, on_click=decrement_page, disabled=True if st.session_state["current_page"] == 1 else False) |
|
nav_col2.markdown(f"<div style='text-align: center;'>Page {str(st.session_state['current_page'])} / {str(math.ceil(len(st.session_state['tasks_to_display'])/10))}</div>", unsafe_allow_html=True) |
|
nav_col3.button("▶️", key="nav2", use_container_width=True, on_click=increment_page, disabled=True if st.session_state["current_page"] == math.ceil(len(st.session_state["tasks_to_display"])/10) else False) |
|
|
|
for i in range((st.session_state["current_page"]-1)*10, st.session_state["current_page"]*10 if st.session_state["current_page"]*10 < len(st.session_state["tasks_to_display"]) else len(st.session_state["tasks_to_display"])): |
|
col_1, col_2 = st.columns([7, 1]) |
|
with col_1: |
|
st.write(st.session_state["tasks_to_display"][i]["task"]) |
|
with col_2: |
|
st.button("Select", disabled=True if st.session_state["tasks_to_display"][i] in st.session_state["tasks_for_interview"] else False ,key="select_button_tasks_"+str(i), on_click=st.session_state["tasks_for_interview"].append, args=(st.session_state["tasks_to_display"][i],)) |
|
st.divider() |
|
|
|
st.subheader("Questions for the interview:") |
|
if len(st.session_state["questions_for_interview"]) == 0: |
|
st.write("No questions selected yet.") |
|
for i, question in enumerate(st.session_state["questions_for_interview"]): |
|
interview_col_1, interview_col_2 = st.columns([7, 1]) |
|
with interview_col_1: |
|
st.write(question["question"]) |
|
with interview_col_2: |
|
st.button("Remove", key="remove_button_"+str(i), on_click=st.session_state["questions_for_interview"].remove, args=(question,)) |
|
st.subheader("Coding tasks for the interview:") |
|
if len(st.session_state["tasks_for_interview"]) == 0: |
|
st.write("No coding tasks selected yet.") |
|
for i, task in enumerate(st.session_state["tasks_for_interview"]): |
|
interview_col_1, interview_col_2 = st.columns([6, 2]) |
|
with interview_col_1: |
|
st.write(task["task"]) |
|
with interview_col_2: |
|
st.button("Remove", key="remove_button_tasks_"+str(i), on_click=st.session_state["tasks_for_interview"].remove, args=(task,)) |
|
st.divider() |
|
if len(st.session_state["questions_for_interview"]) > 0 and len(st.session_state["tasks_for_interview"]) > 0: |
|
st.write("You can now save the questions and coding tasks for your interview.") |
|
|
|
|
|
pdf_buffer = BytesIO() |
|
doc = SimpleDocTemplate(pdf_buffer, pagesize=letter, title="Interview Questions") |
|
|
|
styles = getSampleStyleSheet() |
|
paragraphs = [] |
|
for i, question in enumerate(st.session_state["questions_for_interview"]): |
|
paragraph_text = f"<font size='14'><b>Question {i+1}. :</b></font><br/><br/>{question['question']}<br/><b>Perfect answer:</b> {question['perfect_answer']}<br/><b>Difficulty:</b> {question['difficulty']}\n" |
|
try: |
|
paragraphs.append(Paragraph(paragraph_text, styles["Normal"])) |
|
except: |
|
try: |
|
paragraphs.append(Paragraph(fix_br_tags(paragraph_text), styles["Normal"])) |
|
except: |
|
paragraphs.append(Paragraph(remove_html_tags(paragraph_text), styles["Normal"])) |
|
paragraphs.append(Paragraph("<br/><br/>", styles["Normal"])) |
|
|
|
for i, task in enumerate(st.session_state["tasks_for_interview"]): |
|
paragraph_text = f"<font size='14'><b>Coding task {i+1}. :</b></font><br/><br/>{task['task']}<br/><b>Perfect answer:</b> {task['perfect_solution']}\n" |
|
try: |
|
paragraphs.append(Paragraph(paragraph_text, styles["Normal"])) |
|
except: |
|
try: |
|
paragraphs.append(Paragraph(fix_br_tags(paragraph_text), styles["Normal"])) |
|
except: |
|
paragraphs.append(Paragraph(remove_html_tags(paragraph_text), styles["Normal"])) |
|
paragraphs.append(Paragraph("<br/><br/>", styles["Normal"])) |
|
|
|
|
|
doc.build(paragraphs) |
|
|
|
|
|
pdf_buffer.seek(0) |
|
|
|
|
|
st.download_button(label="Download", data=pdf_buffer, file_name=f'interview_questions_{st.session_state["assessment_db_object"]["assessment_title"]}.pdf', mime="application/pdf", on_click=update_questions_and_tasks) |