File size: 6,609 Bytes
8d1a2b7
c3a2fab
d77f67c
 
c25859b
8d1a2b7
2d35e22
086e34b
 
 
 
462e149
e2ef182
13e4f75
e2ef182
 
 
13e4f75
2d35e22
e2ef182
 
 
13e4f75
 
e2ef182
2d35e22
e2ef182
 
 
 
 
 
 
c351604
e2ef182
13e4f75
 
e2ef182
462e149
e2ef182
 
 
 
086e34b
 
e2ef182
 
 
ab57869
e2ef182
62dcd3c
e2ef182
 
 
 
 
 
 
 
 
 
 
 
 
 
8d1a2b7
c25859b
8d1a2b7
c3a2fab
b8406fc
 
 
 
 
 
 
13e4f75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8406fc
c3a2fab
8d1a2b7
4570e2e
c25859b
 
 
 
8d1a2b7
c3a2fab
8d1a2b7
 
 
833a547
8d1a2b7
 
 
e156efe
833a547
 
 
 
e607035
 
 
 
 
 
 
833a547
e607035
e156efe
8d1a2b7
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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)