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

- 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:
Poidevin, Antoine (ITOP CM) - AF
2026-02-20 10:33:09 +01:00
parent beda405953
commit 6a4ccc3376
38 changed files with 4319 additions and 11161 deletions

130
views/contributions.py Normal file
View 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."
)