add a AI chatbot, rename course names
This commit is contained in:
20
app.py
20
app.py
@@ -15,6 +15,8 @@ page_label = nv()
|
||||
if page_label == "Homepage":
|
||||
pg.home()
|
||||
|
||||
elif page_label == "BuffBot":
|
||||
pg.buffbot()
|
||||
elif page_label == "Outstanding Members":
|
||||
pg.outstanding_members()
|
||||
|
||||
@@ -33,14 +35,16 @@ elif page_label == "Join Us":
|
||||
# block of PythonX lessons
|
||||
elif page_label == "About PythonX":
|
||||
pg.pythonx_homepage()
|
||||
elif page_label == "Lesson1":
|
||||
pg.pythonx_lesson1()
|
||||
elif page_label == "Lesson2":
|
||||
pg.pythonx_lesson2()
|
||||
elif page_label == "Lesson3":
|
||||
pg.pythonx_lesson3()
|
||||
elif page_label == "Lesson4":
|
||||
pg.pythonx_lesson4()
|
||||
elif page_label == "Introduction":
|
||||
pg.pythonx_introduction()
|
||||
elif page_label == "WordCloud":
|
||||
pg.pythonx_wordcloud()
|
||||
elif page_label == "Finance":
|
||||
pg.pythonx_finance()
|
||||
elif page_label == "GeoMap":
|
||||
pg.pythonx_geomap()
|
||||
elif page_label == "BuffBot":
|
||||
pg.pythonx_buffbot()
|
||||
|
||||
# block of CIS Tech Challenge Event
|
||||
elif page_label == "CIS Tech Challenge":
|
||||
|
||||
16
app_config.json
Normal file
16
app_config.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"deepseek":{
|
||||
"api_url": "https://api.deepseek.com",
|
||||
"api_key": "sk-12165b127043441697a8940918e207ac"
|
||||
},
|
||||
|
||||
"ollama":{
|
||||
"api_url": "http://localhost:11434/v1",
|
||||
"api_key": "ollama"
|
||||
},
|
||||
|
||||
"send_email": {
|
||||
"sender_email": "noreply@buffteks.org",
|
||||
"password": "cidm4360fall2024@*"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"api_url": "https://api.deepseek.com",
|
||||
"api_key": "sk-12165b127043441697a8940918e207ac",
|
||||
"ollama_api_url": "http://localhost:11434/v1",
|
||||
"ollama_api_key": "ollama"
|
||||
}
|
||||
@@ -12,7 +12,7 @@ with st.expander("See Source Code"):
|
||||
st.code(f.read(), language="python")
|
||||
|
||||
# Load API credentials from config.json
|
||||
with open('chatbot_config.json') as config_file:
|
||||
with open('app_config.json') as config_file:
|
||||
config = json.load(config_file)
|
||||
openai_api_base_url = config["api_url"]
|
||||
openai_api_key = config["api_key"]
|
||||
|
||||
@@ -15,14 +15,14 @@ st.markdown("<h1 style='text-align: center; color: #451002;'>BuffBot🦬</h1>",
|
||||
# st.subheader()
|
||||
st.info("Powered by llama3.2:1b model via [Ollama](https://ollama.com/library/llama3.2:1b)!")
|
||||
with st.expander("See Source Code"):
|
||||
with open(__file__, "r") as f:
|
||||
st.code(f.read(), language="python")
|
||||
with open(__file__, "r") as f:
|
||||
st.code(f.read(), language="python")
|
||||
|
||||
# Load API credentials from config.json
|
||||
with open('chatbot_config.json') as config_file:
|
||||
with open('app_config.json') as config_file:
|
||||
config = json.load(config_file)
|
||||
api_base_url = config["ollama_api_url"]
|
||||
api_key = config["ollama_api_key"]
|
||||
api_base_url = config["ollama"]["api_url"]
|
||||
api_key = config["ollama"]["api_key"]
|
||||
|
||||
client = OpenAI(api_key=api_key, base_url=api_base_url)
|
||||
|
||||
|
||||
3
new_members.json
Normal file
3
new_members.json
Normal file
@@ -0,0 +1,3 @@
|
||||
[
|
||||
|
||||
]
|
||||
@@ -106,7 +106,9 @@ def send_email(sender_email, password, to_email, subject):
|
||||
server.starttls() # Enable TLS encryption for secure connection
|
||||
server.login(sender_email, password) # Log in with the sender's email and password
|
||||
server.send_message(message) # Send the email message
|
||||
|
||||
print("Email sent successfully!")
|
||||
|
||||
except Exception as e:
|
||||
# Catch and display any exceptions that occur during the sending process
|
||||
print(f"Failed to send email: {str(e)}")
|
||||
|
||||
@@ -6,10 +6,11 @@ from .join_us import join_us
|
||||
from .testing import testing
|
||||
from .reference import reference
|
||||
from .pythonx_lessons_pages.pythonx_homepage import pythonx_homepage
|
||||
from .pythonx_lessons_pages.pythonx_lesson1 import pythonx_lesson1
|
||||
from .pythonx_lessons_pages.pythonx_lesson2 import pythonx_lesson2
|
||||
from .pythonx_lessons_pages.pythonx_lesson3 import pythonx_lesson3
|
||||
from .pythonx_lessons_pages.pythonx_lesson4 import pythonx_lesson4
|
||||
from .pythonx_lessons_pages.pythonx_introduction import pythonx_introduction
|
||||
from .buff_bot import buffbot
|
||||
from .pythonx_lessons_pages.pythonx_finance import pythonx_finance
|
||||
from .pythonx_lessons_pages.pythonx_geomap import pythonx_geomap
|
||||
from .pythonx_lessons_pages.pythonx_wordcloud import pythonx_wordcloud
|
||||
from .outstanding_members import outstanding_members
|
||||
from .cis_tech_challenge_pages.cis_tech_challenge_homepage import cis_tech_challenge_homepage
|
||||
from .coreteks_pages.coreteks_homepage import coreteks_homepage
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
webpages/__pycache__/buff_bot.cpython-312.pyc
Normal file
BIN
webpages/__pycache__/buff_bot.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
119
webpages/buff_bot.py
Normal file
119
webpages/buff_bot.py
Normal file
@@ -0,0 +1,119 @@
|
||||
import streamlit as st
|
||||
from openai import OpenAI # OpenAI compatibility
|
||||
import json
|
||||
# reference:
|
||||
# - Use OpenAI to connect Ollama: https://ollama.com/blog/openai-compatibility
|
||||
# - Build Chatbot with streamlit: https://streamlit.io/generative-ai
|
||||
# - Ollama docker: https://hub.docker.com/r/ollama/ollama
|
||||
# - [TBD] Finetune: https://docs.loopin.network/tutorials/LLM/llama3-finetune
|
||||
|
||||
|
||||
# Clear chat history
|
||||
def clear_chat():
|
||||
st.session_state.messages = []
|
||||
st.toast("Chat Cleaned", icon="🧹")
|
||||
|
||||
def buffbot():
|
||||
# Set up the Streamlit app
|
||||
st.markdown("<h1 style='text-align: center; color: #451002;'>BuffBot🦬</h1>", unsafe_allow_html=True)
|
||||
st.markdown("<h5 style='text-align: center;'> Your friendly AI chatbot powered by LLM! 🤖 </h3>", unsafe_allow_html=True)
|
||||
# Display info and source code
|
||||
with st.expander("See Source Code"):
|
||||
with open(__file__, "r", encoding="utf-8") as f:
|
||||
st.code(f.read(), language="python")
|
||||
|
||||
# Select AI model for chatbot
|
||||
model_options = ["llama3.2:1b", "deepseek-chat", ]
|
||||
# on_change callback to clear chat history when model is changed
|
||||
selected_model = st.selectbox("**👉 Please select a model to start**", model_options, on_change=clear_chat)
|
||||
|
||||
# Initialize session state to store chat history and message count
|
||||
if "messages" not in st.session_state:
|
||||
st.session_state.messages = []
|
||||
# Initialize message count
|
||||
if "message_count" not in st.session_state:
|
||||
st.session_state.message_count = 0
|
||||
|
||||
# Load API credentials from config.json
|
||||
# the config file contains the API key and base URL for the selected model
|
||||
"""
|
||||
{
|
||||
"deepseek":{
|
||||
"api_url": "https://api.deepseek.com",
|
||||
"api_key": "YOUR_API_KEY"
|
||||
},
|
||||
|
||||
"ollama":{
|
||||
"api_url": "http://localhost:11434/v1",
|
||||
"api_key": "ollama"
|
||||
}
|
||||
}
|
||||
"""
|
||||
# The API key and base URL are loaded based on the selected model
|
||||
with open('app_config.json') as config_file:
|
||||
config = json.load(config_file)
|
||||
# deepseek-chat model, online API
|
||||
if selected_model == "deepseek-chat":
|
||||
api_base_url = config["deepseek"]["api_url"]
|
||||
api_key = config["deepseek"]["api_key"]
|
||||
st.info("Powered by the online [DeepSeek](https://www.deepseek.com/) API!\
|
||||
Just a heads up, you have 10 messages to use.")
|
||||
# Set the maximum number of user messages
|
||||
MAX_USER_MESSAGES = 10
|
||||
|
||||
# llama3.2:1b model, local API
|
||||
if selected_model == "llama3.2:1b":
|
||||
api_base_url = config["ollama"]["api_url"]
|
||||
api_key = config["ollama"]["api_key"]
|
||||
st.info("Powered by local llama3.2:1b model via [Ollama](https://ollama.com/library/llama3.2:1b)!\
|
||||
Just a heads up, you have 100 messages to use.")
|
||||
MAX_USER_MESSAGES = 100
|
||||
|
||||
# Initialize OpenAI client to connect with the selected model API
|
||||
client = OpenAI(api_key=api_key, base_url=api_base_url)
|
||||
|
||||
# print welcome message
|
||||
with st.chat_message("assistant", avatar="🦬"):
|
||||
st.markdown("Welcome to BuffBot! What Can I Do for You Today?🌞")
|
||||
|
||||
# Display chat history with different avatars for user and AI assistant
|
||||
for message in st.session_state.messages:
|
||||
if message["role"] == "user":
|
||||
avatar="🤠"
|
||||
else:
|
||||
avatar="🦬"
|
||||
with st.chat_message(message["role"], avatar=avatar):
|
||||
st.markdown(message["content"])
|
||||
|
||||
# Get user input
|
||||
if prompt := st.chat_input("Type your message here..."):
|
||||
# Add user message to chat history
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
# Display user message with cowboy avatar
|
||||
with st.chat_message("user", avatar="🤠"):
|
||||
st.markdown(prompt)
|
||||
|
||||
# Generate reply
|
||||
with st.chat_message("assistant", avatar="🦬"):
|
||||
with st.spinner('Thinking...'):
|
||||
# Call the selected model API to generate a response
|
||||
stream = client.chat.completions.create(
|
||||
model=selected_model,
|
||||
messages=[
|
||||
{"role": m["role"], "content": m["content"]}
|
||||
for m in st.session_state.messages
|
||||
],
|
||||
stream=True, # stream the response
|
||||
)
|
||||
# Display the response from the model API
|
||||
response = st.write_stream(stream)
|
||||
# Add the AI assistant response to the chat history
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
|
||||
# Clear chat history
|
||||
if st.button("Clear Chat"):
|
||||
clear_chat()
|
||||
st.rerun()
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -27,7 +27,7 @@ def coreteks_homepage():
|
||||
|
||||
# for linux talk
|
||||
st.subheader(" :two: Linux Security and Web Server Setup")
|
||||
st.image("./images/11-19-2024-CaddyAndLinux.jpg", width= 500)
|
||||
st.image("./images/11-19-2024-CaddyAndLinux.jpg", width= 700)
|
||||
st.link_button(label="Watch Video Recording", use_container_width=True, type="primary", url="https://wtamu0-my.sharepoint.com/:v:/g/personal/czhang_wtamu_edu/EdgZHrnkqihNrOZGYAT6O2MBSRBOBMv3czD_uIE21KgsWw?nav=eyJyZWZlcnJhbEluZm8iOnsicmVmZXJyYWxBcHAiOiJPbmVEcml2ZUZvckJ1c2luZXNzIiwicmVmZXJyYWxBcHBQbGF0Zm9ybSI6IldlYiIsInJlZmVycmFsTW9kZSI6InZpZXciLCJyZWZlcnJhbFZpZXciOiJNeUZpbGVzTGlua0NvcHkifX0&e=obIoyY", )
|
||||
st.link_button(label="Download PDF Instruction", use_container_width=True, type="primary", url="https://wtamu0-my.sharepoint.com/:b:/g/personal/czhang_wtamu_edu/Eaygqoc_FqxNgYj3BlEOXhsBzOj-BWTbNKwkpJEYSDBwgA?e=K7qxSU", )
|
||||
st.divider()
|
||||
|
||||
134
webpages/home.py
134
webpages/home.py
@@ -1,4 +1,136 @@
|
||||
import streamlit as st
|
||||
from .join_us import join_us
|
||||
|
||||
def home():
|
||||
st.html("./webpages/buffteks.html")
|
||||
|
||||
# Custom CSS to style the page
|
||||
st.markdown("""
|
||||
<style>
|
||||
body {
|
||||
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
background-color: #ffffff;
|
||||
color: #450012;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto 2rem;
|
||||
padding: 1rem;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 2px solid #333;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.faculty-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.faculty {
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.faculty img {
|
||||
height: 210px;
|
||||
width: 140px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.faculty-info {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.join {
|
||||
text-align: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Header
|
||||
st.markdown("""
|
||||
<div class="header-content">
|
||||
<h1>BuffTeks Student Organization</h1>
|
||||
<p>Building Skills, Crafting Code, Bridging Communities</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
|
||||
# Our Mission
|
||||
st.markdown("""
|
||||
<section>
|
||||
<h2>Our Mission</h2>
|
||||
<p>Empower members with advanced software development knowledge, foster new skills and technologies in a collaborative and engaging community.</p>
|
||||
</section>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Our Activities
|
||||
st.markdown("""
|
||||
<section>
|
||||
<h2>Our Activities</h2>
|
||||
<ul>
|
||||
<li><strong>BuffTeks Project:</strong> Faculty-led coding projects to provide IT solutions and support to problems facing local communities as part of an experiential learning effort.</li>
|
||||
<li><strong>BuffTeks Classroom:</strong> An open learning platform devoted to sharing knowledge of information technology including Python programming and web application development.</li>
|
||||
<li><strong>BuffTeks Event:</strong> Host competitions and hackathons that empower students to use classroom knowledge for real-world solutions.</li>
|
||||
</ul>
|
||||
</section>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Faculty Advisors
|
||||
st.markdown("""
|
||||
<section>
|
||||
<h2>Faculty Advisors</h2>
|
||||
<div class="faculty-container">
|
||||
<div class="faculty-row">
|
||||
<div class="faculty">
|
||||
<img src="https://www.wtamu.edu/_files/images/academics/college-business/headshots/babb-jeffry-22.png" alt="Dr. Jeffry Babb">
|
||||
<div class="faculty-info">
|
||||
<strong>Dr. Jeffry Babb</strong><br>
|
||||
BuffTeks Founder<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faculty">
|
||||
<img src="https://www.wtamu.edu/_files/images/academics/college-business/headshots/zhang-carl-22.png" alt="Dr. Carl Zhang">
|
||||
<div class="faculty-info">
|
||||
<strong>Dr. Carl Zhang</strong><br>
|
||||
<a href="mailto:czhang@wtamu.edu">czhang@wtamu.edu</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faculty">
|
||||
<img src="https://www.wtamu.edu/_files/images/academics/college-business/headshots/dana-kareem-22.png" alt="Mr. Kareem Dana">
|
||||
<div class="faculty-info">
|
||||
<strong>Mr. Kareem Dana</strong><br>
|
||||
<a href="mailto:kdana@wtamu.edu">kdana@wtamu.edu</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
@@ -1,50 +1,103 @@
|
||||
import streamlit as st
|
||||
from .SendEmail import send_email
|
||||
import time
|
||||
import json
|
||||
import re
|
||||
|
||||
# reset all inputs
|
||||
def clear_text():
|
||||
st.session_state["full_name"] = ""
|
||||
st.session_state["email"] = ""
|
||||
st.session_state["stu_major"] = None
|
||||
st.session_state["other_major"] = ""
|
||||
st.session_state["stu_year"] = None
|
||||
st.session_state["skills_selection"] = []
|
||||
st.session_state["other_skill"] = ""
|
||||
|
||||
def is_valid_email(email):
|
||||
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||
return re.match(pattern, email)
|
||||
|
||||
@st.dialog("Review Your Information")
|
||||
def review(review_info):
|
||||
st.write(review_info)
|
||||
confirm_btn = st.button("Confirm and Send Email", on_click=clear_text)
|
||||
if confirm_btn:
|
||||
# save new member info to json file
|
||||
try:
|
||||
with open('new_members.json', 'r+') as file:
|
||||
data = json.load(file)
|
||||
data.append(review_info)
|
||||
file.seek(0)
|
||||
json.dump(data, file, indent=4)
|
||||
except FileNotFoundError:
|
||||
with open('new_members.json', 'w') as file:
|
||||
json.dump([refiew_info], file, indent=4)
|
||||
|
||||
# load email config from app_config.json
|
||||
with open('app_config.json') as config_file:
|
||||
config = json.load(config_file)
|
||||
email_config = config["send_email"]
|
||||
|
||||
# send email to new member
|
||||
with st.spinner('📧 Sending Email...'):
|
||||
send_email(
|
||||
sender_email=email_config["sender_email"],
|
||||
password=email_config["password"],
|
||||
to_email=review_info["Email"],
|
||||
subject=f"Welcome to join BuffTeks, {review_info["Full Name"]}!"
|
||||
)
|
||||
time.sleep(3)
|
||||
st.success("🎉Thanks for submitting your information, you will receive an invitation email shortly. \
|
||||
\nPlease contact Dr.Zhang (czhang@wtamu.edu) if you need any help.")
|
||||
|
||||
progress_text = "⏱️ Window will be closed in 10 seconds..."
|
||||
my_bar = st.progress(0, text=progress_text)
|
||||
for percent_complete in range(99):
|
||||
time.sleep(0.1)
|
||||
my_bar.progress(percent_complete + 1, text=progress_text)
|
||||
time.sleep(1)
|
||||
st.rerun()
|
||||
|
||||
|
||||
def join_us():
|
||||
st.title("Join Us")
|
||||
st.write("Thank you for your interest in the BuffTeks student organization! Please share your information below, \
|
||||
and our Faculty Advisor will send you an invitation to join our Discord channel. \
|
||||
If you have any questions, feel free to contact our Faculty Advisor, Dr. Carl Zhang, at czhang@wtamu.edu.")
|
||||
|
||||
full_name = st.text_input("**Full Name**")
|
||||
wt_email = st.text_input("**WT Email**")
|
||||
full_name = st.text_input("**Full Name**", key="full_name")
|
||||
email = st.text_input("**Email**", key="email", placeholder="WT email is preferred")
|
||||
major_list = ["Accounting", "Computer Infromation Systems", "Economics", "Finance", "General Business", "Management", "Marketing", "Other"]
|
||||
stu_major = st.radio("**Major/Field of Study**",major_list)
|
||||
stu_major = st.radio("**Major/Field of Study**",major_list, key="stu_major")
|
||||
if stu_major == "Other":
|
||||
other_major = st.text_input("Please specify the other major")
|
||||
other_major = st.text_input("Please specify the other major", key="other_major")
|
||||
stu_major = other_major
|
||||
|
||||
year_of_study_list = ["Freshman", "Sophomore", "Junior", "Senior", "Graduate"]
|
||||
stu_year = st.radio("**Year of Study**", year_of_study_list)
|
||||
stu_year = st.radio("**Year of Study**", year_of_study_list, key="stu_year")
|
||||
|
||||
skills_options = ["Programming", "Cybersecurity", "Web Development", "Mobile App Development", "machine Learning/AI", "Data Analysis", "Other"]
|
||||
skills_selection = st.multiselect(
|
||||
label= "**Technical Skills You Are Interested In (Please check all that apply)**",
|
||||
options = skills_options,
|
||||
placeholder = "Choose all that apply")
|
||||
placeholder = "Choose all that apply",
|
||||
key="skills_selection")
|
||||
if "Other" in skills_selection:
|
||||
other_skill = st.text_input("**Please specify the other skills**")
|
||||
other_skill = st.text_input("**Please specify the other skills**", key="other_skill")
|
||||
skills_selection.remove("Other")
|
||||
skills_selection.append(f"Other ({other_skill})")
|
||||
skills_selection.append(f"{other_skill}")
|
||||
|
||||
next_btn = st.button("Next")
|
||||
|
||||
if next_btn:
|
||||
if "wtamu.edu" not in wt_email:
|
||||
st.warning("Please input your WT Email address to receive invitation")
|
||||
with st.spinner('Sending Email...'):
|
||||
send_email(sender_email="noreply@buffteks.org", password="cidm4360fall2024@*", to_email=wt_email, subject=f"Welcome to join ButtTeks, {full_name}!")
|
||||
st.balloons()
|
||||
st.success("Thanks for submitting your information, you will receive an invitation email shortly. \n Please contact Dr.Zhang (czhang@wtamu.edu) if you need any help.")
|
||||
|
||||
# @st.dialog("Check Email")
|
||||
# def confirm_email(wt_email, full_name):
|
||||
# st.write(f"Please double-check your **WT Email** in order to receive our invitation: \n {wt_email}")
|
||||
# if st.button("Confirm & Submit"):
|
||||
# send_email(sender_email="noreply@buffteks.org", password="cidm4360fall2024@*", to_email=wt_email, subject=f"Welcome to join ButtTeks, {full_name}!")
|
||||
# st.rerun()
|
||||
# return True
|
||||
|
||||
if not is_valid_email(email):
|
||||
st.error("Please enter a valid email address.")
|
||||
return
|
||||
st.session_state.review_info = {
|
||||
"Full Name": full_name,
|
||||
"Email": email,
|
||||
"Major/Field of Study": stu_major,
|
||||
"Year of Study": stu_year,
|
||||
"Technical Skills": skills_selection
|
||||
}
|
||||
review(review_info=st.session_state.review_info)
|
||||
|
||||
@@ -13,23 +13,25 @@ def navigation_bar():
|
||||
|
||||
page_label = sac.menu([
|
||||
sac.MenuItem('Homepage', icon='house'),
|
||||
sac.MenuItem('BuffBot', icon='robot'),
|
||||
sac.MenuItem('Outstanding Members', icon='award'),
|
||||
sac.MenuItem("Join Us", icon='person-add'),
|
||||
sac.MenuItem('BuffTeks Project', icon='bi bi-laptop'),
|
||||
sac.MenuItem('BuffTeks Event', icon='calendar-event', children=[
|
||||
sac.MenuItem('CIS Tech Challenge', icon='bi bi-trophy'),
|
||||
]),
|
||||
sac.MenuItem('BuffTeks Classroom', icon='book', children=[
|
||||
sac.MenuItem('About Classroom', icon='question-circle'),
|
||||
sac.MenuItem('PythonX', icon='bi bi-filetype-py', children=[
|
||||
sac.MenuItem('About PythonX', icon='question-circle'),
|
||||
sac.MenuItem('Lesson1', icon='1-square'),
|
||||
sac.MenuItem('Lesson2', icon='2-square'),
|
||||
sac.MenuItem('Lesson3', icon='3-square'),
|
||||
sac.MenuItem('Lesson4', icon='4-square'),
|
||||
sac.MenuItem('Introduction', icon='1-square'),
|
||||
sac.MenuItem('WordCloud', icon='2-square'),
|
||||
sac.MenuItem('Finance', icon='3-square'),
|
||||
sac.MenuItem('GeoMap', icon='4-square'),
|
||||
# sac.MenuItem('BuffBot', icon='5-square'),
|
||||
]),
|
||||
sac.MenuItem('CoreTeks', icon='bi bi-tools'),
|
||||
]),
|
||||
sac.MenuItem("Join Us", icon='person-add'),
|
||||
sac.MenuItem('BuffTeks Event', icon='calendar-event', children=[
|
||||
sac.MenuItem('CIS Tech Challenge', icon='bi bi-trophy'),
|
||||
]),
|
||||
# sac.MenuItem("Testing", icon='fingerprint'),
|
||||
# sac.MenuItem(type='divider'),
|
||||
# sac.MenuItem('Link', type='group', children=[
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,7 @@ import yfinance as yf
|
||||
import plotly.express as px
|
||||
from webpages import code_editor as ce
|
||||
|
||||
def pythonx_lesson3():
|
||||
def pythonx_finance():
|
||||
|
||||
st.title("Lesson 3: Collecting Stock Data Through API")
|
||||
st.header(":one: What is API")
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import folium
|
||||
from streamlit_folium import folium_static
|
||||
from geopy.geocoders import Nominatim
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
from folium.features import CustomIcon
|
||||
import pandas as pd # package for database connection
|
||||
import folium # package for creating maps
|
||||
from streamlit_folium import folium_static # package for displaying maps on streamlit
|
||||
from geopy.geocoders import Nominatim # package for geolocation conversion
|
||||
import sqlite3 # package for database connection
|
||||
from datetime import datetime # package for timestamp
|
||||
from folium.features import CustomIcon # package for custom icons on map
|
||||
|
||||
|
||||
def pythonx_lesson4():
|
||||
def pythonx_geomap():
|
||||
# Initialize the database
|
||||
conn = sqlite3.connect('./files/student_locations.db')
|
||||
# Create a table to store student locations
|
||||
c = conn.cursor()
|
||||
c.execute('''CREATE TABLE IF NOT EXISTS students
|
||||
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -24,16 +24,40 @@ def pythonx_lesson4():
|
||||
conn.commit()
|
||||
|
||||
|
||||
st.title('Where are Members From')
|
||||
|
||||
st.title("Lesson 4: Geographical Data Visualization")
|
||||
st.markdown("""
|
||||
This lesson demonstrates how to handle geolocation data and visualize it using maps in Python.
|
||||
|
||||
The main functionalities include:
|
||||
|
||||
- **User Input for Location**: Users can input their city and state or city and country through a form.
|
||||
|
||||
- **Geolocation Processing**: The input location is processed to obtain latitude and longitude coordinates.
|
||||
|
||||
- **Data Storage**: The processed location data is saved to a [SQLite](https://www.geeksforgeeks.org/python-sqlite/) database.
|
||||
|
||||
- **Map Visualization**: All stored student locations are displayed on an interactive map.
|
||||
|
||||
- **Statistics Display**: The code also provides statistics on the total number of students, unique cities, and unique countries, along with the top 5 cities.
|
||||
""")
|
||||
|
||||
# Display the source code
|
||||
with st.expander("See Source Code"):
|
||||
with open(__file__, "r", encoding="utf-8") as f:
|
||||
st.code(f.read(), language="python")
|
||||
|
||||
st.subheader("Student Location Tracker")
|
||||
# Input form for student location
|
||||
with st.form("student_form"):
|
||||
input_city = st.text_input("Enter your City, State (e.g.: Amarillo,TX), or City, Country (Toronto, Canada):")
|
||||
|
||||
submitted = st.form_submit_button("Submit")
|
||||
|
||||
if submitted:
|
||||
if submitted:
|
||||
# converting addresses (like "Mountain View, CA") into geographic
|
||||
# coordinates (like latitude 37.423021 and longitude -122.083739)
|
||||
lat, lon, city, state, country = get_location(input_city)
|
||||
# Save the location data to the database
|
||||
if lat and lon:
|
||||
save_student(conn, city, state, country, lat, lon)
|
||||
st.success(f"Location saved: {city}, {country}")
|
||||
@@ -66,7 +90,7 @@ def pythonx_lesson4():
|
||||
conn.close()
|
||||
|
||||
|
||||
|
||||
# convert address to latitude and longitude
|
||||
def get_location(city):
|
||||
geolocator = Nominatim(user_agent="student_location_app")
|
||||
try:
|
||||
@@ -82,7 +106,7 @@ def get_location(city):
|
||||
st.write(e)
|
||||
return None, None, None, None, None
|
||||
|
||||
|
||||
# save student location to database
|
||||
def save_student(conn, city, state, country, lat, lon):
|
||||
c = conn.cursor()
|
||||
timestamp = datetime.now()
|
||||
@@ -90,11 +114,14 @@ def save_student(conn, city, state, country, lat, lon):
|
||||
(city, state, country, lat, lon, timestamp))
|
||||
conn.commit()
|
||||
|
||||
# get all student locations from database
|
||||
def get_all_students(conn):
|
||||
df = pd.read_sql_query("SELECT * from students", conn)
|
||||
return df
|
||||
|
||||
# create map with student locations
|
||||
def create_map(df):
|
||||
# Create a map centered at the US
|
||||
m = folium.Map(location=[41.2706, -97.1749], zoom_start=4)
|
||||
|
||||
# Group by city and count occurrences
|
||||
@@ -104,6 +131,7 @@ def create_map(df):
|
||||
max_count = city_counts['count'].max()
|
||||
min_size, max_size = 5, 20 # min and max marker sizes
|
||||
|
||||
# Add markers for each city
|
||||
for _, row in city_counts.iterrows():
|
||||
# Create a custom icon
|
||||
icon = CustomIcon(
|
||||
@@ -112,7 +140,7 @@ def create_map(df):
|
||||
icon_anchor=(15, 30), # Adjust anchor point if needed
|
||||
popup_anchor=(0, -30) # Adjust popup anchor if needed
|
||||
)
|
||||
|
||||
# Calculate marker size based on count
|
||||
folium.Marker(
|
||||
location=[row['latitude'], row['longitude']],
|
||||
popup=f"{row['city']} <br> {row['count']}",
|
||||
@@ -3,7 +3,7 @@ from webpages import code_editor as ce
|
||||
|
||||
|
||||
|
||||
def pythonx_lesson1():
|
||||
def pythonx_introduction():
|
||||
st.title("Lesson 1: Introduction to Python")
|
||||
# Lesson1-Part1: what is programming
|
||||
st.header(":one: From Idea to Program")
|
||||
@@ -4,7 +4,7 @@ from wordcloud import WordCloud
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def pythonx_lesson2():
|
||||
def pythonx_wordcloud():
|
||||
st.title("Lesson 2: Create WordClouds in Python")
|
||||
st.header(":one: What is WordClouds")
|
||||
st.markdown("""
|
||||
Reference in New Issue
Block a user