feat: add interactive exploration of Shannon's capacity formula with Plotly graphs
All checks were successful
Build & Deploy Shannon / 🏗️ Build & Deploy Shannon (push) Successful in 3m1s
All checks were successful
Build & Deploy Shannon / 🏗️ Build & Deploy Shannon (push) Successful in 3m1s
- Implemented bandwidth sensitivity and power sensitivity plots. - Created a contour map for bit rate multiplying factors. - Added input parameters for C/N and bandwidth with validation. - Displayed computed results and sensitivity analysis metrics. - Integrated interactive graphs for user exploration. - Included background information section for user guidance.
This commit is contained in:
130
views/contributions.py
Normal file
130
views/contributions.py
Normal file
@@ -0,0 +1,130 @@
|
||||
"""
|
||||
Page 3: Community Contributions
|
||||
|
||||
Read, write, search and delete user contributions stored in SQLite.
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
from core.database import write_contribution, search_contributions, delete_contribution
|
||||
|
||||
|
||||
def render():
|
||||
"""Render the Contributions page."""
|
||||
|
||||
st.markdown("# 💬 Community Contributions")
|
||||
st.markdown(
|
||||
"Share your observations about Shannon's theorem, satellite communications, "
|
||||
"or suggest improvements. Contributions are stored locally and shared with all users."
|
||||
)
|
||||
|
||||
tab_read, tab_write = st.tabs(["📖 Read Contributions", "✍️ Write Contribution"])
|
||||
|
||||
# ── Read Contributions ──
|
||||
with tab_read:
|
||||
st.markdown("### 🔍 Search Contributions")
|
||||
|
||||
db_choice = st.radio(
|
||||
"Database",
|
||||
["Theory", "Real World"],
|
||||
horizontal=True,
|
||||
key="db_read",
|
||||
)
|
||||
db_name = "Shannon_Theory.db" if db_choice == "Theory" else "Shannon_Real.db"
|
||||
|
||||
col_f1, col_f2 = st.columns(2)
|
||||
with col_f1:
|
||||
name_filter = st.text_input("Filter by Name", key="filter_name")
|
||||
title_filter = st.text_input("Filter by Title", key="filter_title")
|
||||
with col_f2:
|
||||
kw_filter = st.text_input("Filter by Keywords", key="filter_kw")
|
||||
content_filter = st.text_input("Filter by Content", key="filter_content")
|
||||
|
||||
if st.button("🔍 Search", type="primary", key="btn_search"):
|
||||
results = search_contributions(
|
||||
db_name,
|
||||
name_filter=name_filter,
|
||||
title_filter=title_filter,
|
||||
keywords_filter=kw_filter,
|
||||
content_filter=content_filter,
|
||||
)
|
||||
st.session_state["contrib_results"] = results
|
||||
|
||||
results = st.session_state.get("contrib_results", [])
|
||||
|
||||
if results:
|
||||
st.success(f"Found {len(results)} contribution(s).")
|
||||
for i, contrib in enumerate(results):
|
||||
with st.expander(
|
||||
f"#{contrib['num']} — {contrib['title']} by {contrib['name']} ({contrib['date']})",
|
||||
expanded=(i == 0),
|
||||
):
|
||||
st.markdown(contrib["text"])
|
||||
if contrib["keywords"]:
|
||||
st.caption(f"🏷️ Keywords: {contrib['keywords']}")
|
||||
|
||||
# Delete functionality
|
||||
with st.popover("🗑️ Delete"):
|
||||
st.warning("This action cannot be undone.")
|
||||
del_password = st.text_input(
|
||||
"Enter contribution password",
|
||||
type="password",
|
||||
key=f"del_pw_{contrib['num']}",
|
||||
)
|
||||
if st.button("Confirm Delete", key=f"del_btn_{contrib['num']}"):
|
||||
if delete_contribution(db_name, contrib["num"], del_password):
|
||||
st.success(f"✅ Contribution #{contrib['num']} deleted.")
|
||||
# Refresh results
|
||||
st.session_state["contrib_results"] = search_contributions(
|
||||
db_name,
|
||||
name_filter=name_filter,
|
||||
title_filter=title_filter,
|
||||
keywords_filter=kw_filter,
|
||||
content_filter=content_filter,
|
||||
)
|
||||
st.rerun()
|
||||
else:
|
||||
st.error("❌ Incorrect password or contribution not found.")
|
||||
elif "contrib_results" in st.session_state:
|
||||
st.info("No contributions found matching your filters.")
|
||||
|
||||
# ── Write Contribution ──
|
||||
with tab_write:
|
||||
st.markdown("### ✍️ New Contribution")
|
||||
|
||||
db_choice_w = st.radio(
|
||||
"Database",
|
||||
["Theory", "Real World"],
|
||||
horizontal=True,
|
||||
key="db_write",
|
||||
)
|
||||
db_name_w = "Shannon_Theory.db" if db_choice_w == "Theory" else "Shannon_Real.db"
|
||||
|
||||
with st.form("contribution_form", clear_on_submit=True):
|
||||
name = st.text_input("Your Name / Initials *", max_chars=100)
|
||||
title = st.text_input("Title *", max_chars=200)
|
||||
keywords = st.text_input("Keywords (comma-separated)", max_chars=200)
|
||||
text = st.text_area("Your contribution *", height=200)
|
||||
password = st.text_input(
|
||||
"Password (optional — leave empty to allow anyone to delete)",
|
||||
type="password",
|
||||
)
|
||||
|
||||
submitted = st.form_submit_button("📤 Submit", type="primary")
|
||||
|
||||
if submitted:
|
||||
if not name or not title or not text:
|
||||
st.error("❌ Please fill in all required fields (marked with *).")
|
||||
else:
|
||||
new_id = write_contribution(db_name_w, name, title, keywords, text, password)
|
||||
st.success(f"✅ Thank you! Your contribution has been stored with ID #{new_id}.")
|
||||
st.balloons()
|
||||
|
||||
with st.expander("❓ Help"):
|
||||
st.markdown(
|
||||
"Write your contribution as a free text. Contributions should be:\n\n"
|
||||
"- Candid observations about the technical subject\n"
|
||||
"- References to relevant material (ideally as web links)\n"
|
||||
"- Open discussion items about adjacent subjects\n"
|
||||
"- Suggestions for improvement\n\n"
|
||||
"You can retrieve and delete your contribution from the Read tab using your password."
|
||||
)
|
||||
Reference in New Issue
Block a user