Program
import streamlit as st
import pandas as pd
import random
from difflib import SequenceMatcher
try:
data = pd.read_csv("Chem.csv")
except FileNotFoundError:
st.warning("Chem.csv not found. Please upload the CSV file.")
uploaded = st.file_uploader("Upload Chem.csv", type="csv")
if uploaded:
data = pd.read_csv(uploaded)
else:
st.stop()
name_col = "Element_Name"
symbol_col = "Symbol"
def is_close(answer, correct, threshold=0.8):
ratio = SequenceMatcher(None, answer.lower().strip(), correct.lower().strip()).ratio()
return ratio >= threshold
if "questions" not in st.session_state:
st.session_state.questions = []
if "index" not in st.session_state:
st.session_state.index = 0
if "score" not in st.session_state:
st.session_state.score = 0
if "results" not in st.session_state:
st.session_state.results = []
if "started" not in st.session_state:
st.session_state.started = False
st.title("Chemistry Quiz")
st.write("Test your knowledge of chemical elements and symbols.")
if not st.session_state.started:
num = st.number_input("How many questions would you like?", min_value=1, max_value=118, value=5)
if st.button("Start Quiz"):
st.session_state.questions = data.sample(num).to_dict(orient="records")
st.session_state.index = 0
st.session_state.score = 0
st.session_state.results = []
st.session_state.started = True
st.experimental_rerun()
else:
i = st.session_state.index
total = len(st.session_state.questions)
if i < total:
row = st.session_state.questions[i]
ask_type = random.choice(["name_to_symbol", "symbol_to_name"])
element = row[name_col]
symbol = row[symbol_col]
if ask_type == "name_to_symbol":
prompt = f"What is the symbol for {element}?"
correct = symbol
else:
prompt = f"What element has the symbol {symbol}?"
correct = element
st.subheader(f"Question {i+1} of {total}")
st.write(prompt)
answer = st.text_input("Your answer:", key=f"answer_{i}")
if st.button("Submit Answer", key=f"submit_{i}"):
if is_close(answer, correct):
st.success("Correct.")
st.session_state.score += 1
st.session_state.results.append((True, correct))
else:
st.error(f"Incorrect. Correct answer: {correct}")
st.session_state.results.append((False, correct))
st.session_state.index += 1
st.experimental_rerun()
else:
st.header("Quiz Complete")
st.write(f"Your final score: {st.session_state.score}/{total}")
if st.checkbox("Show all answers"):
for idx, (correct_flag, value) in enumerate(st.session_state.results, 1):
icon = "Correct" if correct_flag else "Incorrect"
st.write(f"{idx}. {value} - {icon}")
if st.button("Play Again"):
st.session_state.started = False
st.experimental_rerun()
This Python script implements an interactive Streamlit application that provides a user interface for a question-and-answer session based on external data.
1. Import Statements
import streamlit as st: Imports the Streamlit library, aliased asst, which is essential for building interactive web applications.import pandas as pd: Imports the Pandas library, aliased aspd, used for data manipulation and analysis, particularly for reading CSV files.import random: Imports therandommodule, used here to randomly select the type of question to ask.from difflib import SequenceMatcher: ImportsSequenceMatcherfrom thedifflibmodule, utilized for comparing sequences and calculating string similarity.
2. Data Loading
The script attempts to load data from a CSV file named
Chem.csvinto a Pandas DataFrame calleddata.It includes error handling: If
Chem.csvis not found (FileNotFoundError):A warning message is displayed using
st.warning().A
st.file_uploader()widget is presented, allowing the user to upload theChem.csvfile directly.If a file is uploaded, it's read into the
dataDataFrame.If no file is uploaded and the initial file is not found,
st.stop()halts the script execution.
3. Column Definitions
name_col = "Element_Name": Defines a variablename_colto store the string representing the column name for an item's full name.symbol_col = "Symbol": Defines a variablesymbol_colto store the string representing the column name for an item's short identifier.
4. Similarity Comparison Function
def is_close(answer, correct, threshold=0.8):This function compares a user's
answerwith thecorrectanswer.It converts both strings to lowercase and removes leading/trailing whitespace using
.lower().strip().SequenceMatcher(None, ..., ...).ratio()calculates the similarity ratio between the two strings.It returns
Trueif the calculated ratio is greater than or equal to the specifiedthreshold(defaulting to 0.80.8), indicating a sufficiently close match, otherwiseFalse.
5. Session State Initialization
This section initializes various variables within Streamlit's
st.session_state. Session state variables persist across rerun of the app.st.session_state.questions = []: Stores the list of selected data items to be used in the session.st.session_state.index = 0: Tracks the current question number or index within thequestionslist.st.session_state.score = 0: Keeps track of the user's correct answers.st.session_state.results = []: Stores a history of whether each question was answered correctly and the correct answer.st.session_state.started = False: A boolean flag indicating whether the interactive session has begun.
6. Application Title and Introduction
st.title("Chemistry Quiz"): Sets the main title of the Streamlit application.st.write("Test your knowledge of chemical elements and symbols."): Displays a brief introductory text below the title.
7. Starting the Session (if not st.session_state.started)
This block executes when the session has not yet started.
num = st.number_input(...): Allows the user to input the desired number of questions, with a minimum of 11, maximum of 118118, and a default value of 55 questions.if st.button("Start Quiz"):When the "Start Quiz" button is pressed:
data.sample(num).to_dict(...): Randomly selectsnumrows from the loadeddataDataFrame and converts them into a list of dictionaries, storing them inst.session_state.questions.Resets
index,score, andresultsto their initial values.Sets
st.session_state.started = Trueto transition to the active session state.st.experimental_rerun(): Forces the Streamlit application to rerun immediately, displaying the first question.
8. Active Session Logic (else block when st.session_state.started is True)
i = st.session_state.index: Retrieves the current question index.total = len(st.session_state.questions): Gets the total number of questions.8.1. Displaying Current Question (
if i < total)Executes as long as there are questions remaining.
row = st.session_state.questions[i]: Retrieves the current data item.ask_type = random.choice(...): Randomly decides whether to ask for the identifier given the name, or the name given the identifier.element = row[name_col]andsymbol = row[symbol_col]: Extracts the name and identifier from the current data item.Based on
ask_type, it constructs thepromptstring and determines thecorrectanswer.st.subheader(f"Question {i+1} of {total}"): Displays the current question number.st.write(prompt): Shows the actual question to the user.answer = st.text_input("Your answer:", key=f"answer_{i}"): Provides a text input field for the user to type their answer. Thekeyensures unique widget identification.
8.2. Submitting Answer (
if st.button("Submit Answer", key=f"submit_{i}"))When the "Submit Answer" button is clicked:
is_close(answer, correct): Compares the user's input with the correct answer using the defined similarity function.st.success("Correct.")orst.error(...): Provides visual feedback (green for correct, red for incorrect along with the correct answer).st.session_state.score += 1: Increments the score if the answer was correct.st.session_state.results.append(...): Records the outcome (correct/incorrect) and the correct answer for later review.st.session_state.index += 1: Moves to the next question.st.experimental_rerun(): Reruns the app to display the next question or the completion screen.
9. Session Completion (else block when i >= total)
This block executes once all questions have been answered.
st.header("Quiz Complete"): Displays a completion header.st.write(f"Your final score: {st.session_state.score}/{total}"): Shows the user's total score.if st.checkbox("Show all answers"):If the "Show all answers" checkbox is selected, it iterates through
st.session_state.results.For each result, it displays the item's correct value and indicates whether the user's answer was correct or incorrect.
if st.button("Play Again"):When the "Play Again" button is pressed, it resets
st.session_state.startedtoFalse.st.experimental_rerun(): Reruns the app, returning the user to the initial start screen to begin a new session.