ez326's picture
Upload app.py
8e69c14 verified
import streamlit as st
st.set_page_config(layout="wide")
css = """
<style>
/* Remove extra spacing in markdown paragraphs */
.stMarkdown p {
margin: 0 !important;
padding: 0 !important;
}
/* Compact styling for criterion name and description */
.criteria-name {
font-size: 12px;
font-weight: bold;
}
.criteria-description {
font-size: 10px;
color: #555;
}
.category-header {
margin-top: 6px;
margin-bottom: 3px;
font-size: 14px;
font-weight: bold;
border-bottom: 1px solid #ccc;
padding-bottom: 2px;
}
.app-header {
text-align: center;
margin-bottom: 6px;
font-size: 20px;
}
/* Enlarge slider thumb for easier touch */
div[data-baseweb="slider"] .Thumb {
width: 36px !important;
height: 36px !important;
}
/* Hide slider tick marks, tick bar, min/max texts, and empty slider label */
div[data-baseweb="slider"] .Tick,
div[data-baseweb="slider"] .TickBar,
div[data-testid="stSliderTickBarMin"],
div[data-testid="stSliderTickBarMax"],
div[data-testid="stSliderThumbValue"],
label[data-testid="stWidgetLabel"][aria-hidden="true"] {
display: none !important;
}
.stSlider {
margin-top: -10px !important;
}
/* Mobile adjustments */
@media (max-width: 600px) {
.stHorizontalBlock {
flex-wrap: nowrap !important;
}
.stColumn {
padding-left: 2px !important;
padding-right: 2px !important;
min-width: 0;
}
.stCheckbox {
transform: scale(0.8);
transform-origin: left center;
}
}
</style>
"""
st.markdown(css, unsafe_allow_html=True)
criteria = {
"Writing": [
{"name": "Dialogue", "description": "Word choice, realism, subtext, and implications."},
{"name": "Screenwriting", "description": "Structure, plot progression, and narrative choices."},
{"name": "Character Development", "description": "Depth, relatability, motivations, and arcs."},
{"name": "Theme & Symbolism", "description": "Use of deeper meaning, metaphors, and thematic consistency."}
],
"Cinematography": [
{"name": "Camera Work", "description": "Shot composition, stability, movement, and angles."},
{"name": "Lighting", "description": "Contrast, exposure control, and mood-setting."},
{"name": "Color Grading", "description": "Palette consistency, contrast, and emotional tone."},
{"name": "Framing & Aspect Ratio", "description": "Use of space, focus, and visual storytelling."}
],
"Editing & Pacing": [
{"name": "Scene Transitions", "description": "Smoothness, creativity, and effectiveness."},
{"name": "Continuity", "description": "Logical flow and lack of visual inconsistencies."},
{"name": "Pacing", "description": "Balance between slow and fast scenes, engagement level."},
{"name": "Use of Montage", "description": "Storytelling efficiency via edited sequences."}
],
"Sound": [
{"name": "Dialogue Mixing", "description": "Clarity, balance, and intelligibility of speech."},
{"name": "Foley & Sound Effects", "description": "Realism, accuracy, and integration into the world."},
{"name": "Score & Music", "description": "Uniqueness, memorability, and emotional impact."},
{"name": "Spatial Audio & Atmosphere", "description": "Immersion, ambient sound accuracy, and use of silence."}
],
"Directing & Performance": [
{"name": "Directing", "description": "Cohesion of vision, creative choices, and execution."},
{"name": "Acting", "description": "Expression, dialogue delivery, and emotional depth."},
{"name": "Blocking & Staging", "description": "Character positioning, movement, and scene composition."},
{"name": "Action & Stunt Choreography", "description": "Realism, execution, and visual readability."}
],
"Production & Visuals": [
{"name": "Production Design", "description": "Set design, world-building, and authenticity."},
{"name": "Costume & Makeup", "description": "Period accuracy, character enhancement, and detailing."},
{"name": "Practical Effects & Props", "description": "Use of real elements over CGI, believability."},
{"name": "VFX & CGI Integration", "description": "Quality, realism, and seamless blending."}
],
"Engagement & Replay Value": [
{"name": "Plot", "description": "Uniqueness, engagement, predictability, and emotional weight."},
{"name": "Originality", "description": "Avoidance of clichés, fresh storytelling, and innovation."},
{"name": "Rewatchability", "description": "Whether the movie holds up over multiple viewings."},
{"name": "Emotional Impact", "description": "Strength of connection, intensity of response."}
]
}
def calculate_score(ratings):
valid = [r for r in ratings if r is not None]
if not valid:
return "Please rate at least one criterion."
avg = sum(valid) / len(valid)
scaled_score = (1/18) * (avg ** 2) + (19/18) * avg - (1/9)
return f"Final Scaled Score: {scaled_score:.2f} / 10"
st.markdown("<h1 class='app-header'>Movie Rating System</h1>", unsafe_allow_html=True)
ratings = []
# For each criterion, display a row with the checkbox on the left, then title/description and slider
for group, subcriteria in criteria.items():
st.markdown(f"<div class='category-header'>{group}</div>", unsafe_allow_html=True)
for idx, crit in enumerate(subcriteria):
with st.container():
cols = st.columns([0.5, 7])
checkbox_col = cols[0]
combined_col = cols[1]
include = checkbox_col.checkbox("", value=True, key=f"include_{group}_{idx}")
combined = (
f"<span class='criteria-name'>{crit['name']}</span>"
f"&nbsp;&nbsp;&nbsp;"
f"<span class='criteria-description'>{crit['description']}</span>"
)
combined_col.markdown(combined, unsafe_allow_html=True)
rating = combined_col.slider(
"", 1.0, 7.0, 4.0, step=0.01, key=f"slider_{group}_{idx}", disabled=(not include)
)
ratings.append(None if not include else rating)
if st.button("Calculate Score"):
result = calculate_score(ratings)
st.markdown(f"<h2 style='text-align:center;'>{result}</h2>", unsafe_allow_html=True)