Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	
		Pragya Jatav
		
	commited on
		
		
					Commit 
							
							·
						
						69b14e2
	
1
								Parent(s):
							
							85d2c7e
								
Delete two files
Browse files- pages/8_Scenario_Planner.py +0 -1515
- pages/9_Saved_Scenarios.py +0 -280
    	
        pages/8_Scenario_Planner.py
    DELETED
    
    | @@ -1,1515 +0,0 @@ | |
| 1 | 
            -
            import streamlit as st
         | 
| 2 | 
            -
            from numerize.numerize import numerize
         | 
| 3 | 
            -
            import numpy as np
         | 
| 4 | 
            -
            from functools import partial
         | 
| 5 | 
            -
            from collections import OrderedDict
         | 
| 6 | 
            -
            from plotly.subplots import make_subplots
         | 
| 7 | 
            -
            import plotly.graph_objects as go
         | 
| 8 | 
            -
            from utilities import (
         | 
| 9 | 
            -
                format_numbers,format_numbers_f,
         | 
| 10 | 
            -
                load_local_css,
         | 
| 11 | 
            -
                set_header,
         | 
| 12 | 
            -
                initialize_data,
         | 
| 13 | 
            -
                load_authenticator,
         | 
| 14 | 
            -
                send_email,
         | 
| 15 | 
            -
                channel_name_formating,
         | 
| 16 | 
            -
            )
         | 
| 17 | 
            -
            from classes import class_from_dict, class_to_dict
         | 
| 18 | 
            -
            import pickle
         | 
| 19 | 
            -
            import streamlit_authenticator as stauth
         | 
| 20 | 
            -
            import yaml
         | 
| 21 | 
            -
            from yaml import SafeLoader
         | 
| 22 | 
            -
            import re
         | 
| 23 | 
            -
            import pandas as pd
         | 
| 24 | 
            -
            import plotly.express as px
         | 
| 25 | 
            -
            # import response_curves_model_quality as rc
         | 
| 26 | 
            -
             | 
| 27 | 
            -
            st.set_page_config(layout="wide")
         | 
| 28 | 
            -
            load_local_css("styles.css")
         | 
| 29 | 
            -
            set_header()
         | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
            for k, v in st.session_state.items():
         | 
| 33 | 
            -
                if k not in ["logout", "login", "config"] and not k.startswith("FormSubmitter"):
         | 
| 34 | 
            -
                    st.session_state[k] = v
         | 
| 35 | 
            -
            # ======================================================== #
         | 
| 36 | 
            -
            # ======================= Functions ====================== #
         | 
| 37 | 
            -
            # ======================================================== #
         | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
            def optimize(key, status_placeholder):
         | 
| 41 | 
            -
                """
         | 
| 42 | 
            -
                Optimize the spends for the sales
         | 
| 43 | 
            -
                """
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                channel_list = [
         | 
| 46 | 
            -
                    key for key, value in st.session_state["optimization_channels"].items() if value
         | 
| 47 | 
            -
                ]
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                if len(channel_list) > 0:
         | 
| 50 | 
            -
                    scenario = st.session_state["scenario"]
         | 
| 51 | 
            -
                    if key.lower() == "media spends":
         | 
| 52 | 
            -
                        with status_placeholder:
         | 
| 53 | 
            -
                            with st.spinner("Optimizing"):
         | 
| 54 | 
            -
                                result = st.session_state["scenario"].optimize(
         | 
| 55 | 
            -
                                    st.session_state["total_spends_change"], channel_list
         | 
| 56 | 
            -
                                )
         | 
| 57 | 
            -
                    # elif key.lower() == "revenue":
         | 
| 58 | 
            -
                    else:
         | 
| 59 | 
            -
                        with status_placeholder:
         | 
| 60 | 
            -
                            with st.spinner("Optimizing"):
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                                result = st.session_state["scenario"].optimize_spends(
         | 
| 63 | 
            -
                                    st.session_state["total_sales_change"], channel_list
         | 
| 64 | 
            -
                                )
         | 
| 65 | 
            -
                    for channel_name, modified_spends in result:
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                        st.session_state[channel_name] = numerize(
         | 
| 68 | 
            -
                            modified_spends * scenario.channels[channel_name].conversion_rate,
         | 
| 69 | 
            -
                            1,
         | 
| 70 | 
            -
                        )
         | 
| 71 | 
            -
                        prev_spends = (
         | 
| 72 | 
            -
                            st.session_state["scenario"].channels[channel_name].actual_total_spends
         | 
| 73 | 
            -
                        )
         | 
| 74 | 
            -
                        st.session_state[f"{channel_name}_change"] = round(
         | 
| 75 | 
            -
                            100 * (modified_spends - prev_spends) / prev_spends, 2
         | 
| 76 | 
            -
                        )
         | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
            def save_scenario(scenario_name):
         | 
| 80 | 
            -
                """
         | 
| 81 | 
            -
                Save the current scenario with the mentioned name in the session state
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                Parameters
         | 
| 84 | 
            -
                ----------
         | 
| 85 | 
            -
                scenario_name
         | 
| 86 | 
            -
                    Name of the scenario to be saved
         | 
| 87 | 
            -
                """
         | 
| 88 | 
            -
                if "saved_scenarios" not in st.session_state:
         | 
| 89 | 
            -
                    st.session_state = OrderedDict()
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                # st.session_state['saved_scenarios'][scenario_name] = st.session_state['scenario'].save()
         | 
| 92 | 
            -
                st.session_state["saved_scenarios"][scenario_name] = class_to_dict(
         | 
| 93 | 
            -
                    st.session_state["scenario"]
         | 
| 94 | 
            -
                )
         | 
| 95 | 
            -
                st.session_state["scenario_input"] = ""
         | 
| 96 | 
            -
                # print(type(st.session_state['saved_scenarios']))
         | 
| 97 | 
            -
                with open("../saved_scenarios.pkl", "wb") as f:
         | 
| 98 | 
            -
                    pickle.dump(st.session_state["saved_scenarios"], f)
         | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
            if "allow_spends_update" not in st.session_state:
         | 
| 102 | 
            -
                st.session_state["allow_spends_update"] = True
         | 
| 103 | 
            -
             | 
| 104 | 
            -
            if "allow_sales_update" not in st.session_state:
         | 
| 105 | 
            -
                st.session_state["allow_sales_update"] = True
         | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
            def update_sales_abs_slider():
         | 
| 109 | 
            -
                actual_sales = _scenario.actual_total_sales
         | 
| 110 | 
            -
                if validate_input(st.session_state["total_sales_change_abs_slider"]):
         | 
| 111 | 
            -
                    modified_sales = extract_number_for_string(
         | 
| 112 | 
            -
                        st.session_state["total_sales_change_abs_slider"]
         | 
| 113 | 
            -
                    )
         | 
| 114 | 
            -
                    st.session_state["total_sales_change"] = round(
         | 
| 115 | 
            -
                        ((modified_sales / actual_sales) - 1) * 100
         | 
| 116 | 
            -
                    )
         | 
| 117 | 
            -
                    st.session_state["total_sales_change_abs"] = numerize(modified_sales, 1)
         | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
            def update_sales_abs():
         | 
| 121 | 
            -
                if (
         | 
| 122 | 
            -
                    st.session_state["total_sales_change_abs"]
         | 
| 123 | 
            -
                    in st.session_state["total_sales_change_abs_slider_options"]
         | 
| 124 | 
            -
                ):
         | 
| 125 | 
            -
                    st.session_state["allow_sales_update"] = True
         | 
| 126 | 
            -
                else:
         | 
| 127 | 
            -
                    st.session_state["allow_sales_update"] = False
         | 
| 128 | 
            -
             | 
| 129 | 
            -
                actual_sales = _scenario.actual_total_sales
         | 
| 130 | 
            -
                if (
         | 
| 131 | 
            -
                    validate_input(st.session_state["total_sales_change_abs"])
         | 
| 132 | 
            -
                    and st.session_state["allow_sales_update"]
         | 
| 133 | 
            -
                ):
         | 
| 134 | 
            -
                    modified_sales = extract_number_for_string(
         | 
| 135 | 
            -
                        st.session_state["total_sales_change_abs"]
         | 
| 136 | 
            -
                    )
         | 
| 137 | 
            -
                    st.session_state["total_sales_change"] = round(
         | 
| 138 | 
            -
                        ((modified_sales / actual_sales) - 1) * 100
         | 
| 139 | 
            -
                    )
         | 
| 140 | 
            -
                    st.session_state["total_sales_change_abs_slider"] = numerize(modified_sales, 1)
         | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
            def update_sales():
         | 
| 144 | 
            -
                st.session_state["total_sales_change_abs"] = numerize(
         | 
| 145 | 
            -
                    (1 + st.session_state["total_sales_change"] / 100)
         | 
| 146 | 
            -
                    * _scenario.actual_total_sales,
         | 
| 147 | 
            -
                    1,
         | 
| 148 | 
            -
                )
         | 
| 149 | 
            -
                st.session_state["total_sales_change_abs_slider"] = numerize(
         | 
| 150 | 
            -
                    (1 + st.session_state["total_sales_change"] / 100)
         | 
| 151 | 
            -
                    * _scenario.actual_total_sales,
         | 
| 152 | 
            -
                    1,
         | 
| 153 | 
            -
                )
         | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
            def update_all_spends_abs_slider():
         | 
| 157 | 
            -
                actual_spends = _scenario.actual_total_spends
         | 
| 158 | 
            -
                if validate_input(st.session_state["total_spends_change_abs_slider"]):
         | 
| 159 | 
            -
                    modified_spends = extract_number_for_string(
         | 
| 160 | 
            -
                        st.session_state["total_spends_change_abs_slider"]
         | 
| 161 | 
            -
                    )
         | 
| 162 | 
            -
                    st.session_state["total_spends_change"] = round(
         | 
| 163 | 
            -
                        ((modified_spends / actual_spends) - 1) * 100
         | 
| 164 | 
            -
                    )
         | 
| 165 | 
            -
                    st.session_state["total_spends_change_abs"] = numerize(modified_spends, 1)
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                    update_all_spends()
         | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
            # def update_all_spends_abs_slider():
         | 
| 171 | 
            -
            #     actual_spends = _scenario.actual_total_spends
         | 
| 172 | 
            -
            #     if validate_input(st.session_state["total_spends_change_abs_slider"]):
         | 
| 173 | 
            -
            #         print("#" * 100)
         | 
| 174 | 
            -
            #         print(st.session_state["total_spends_change_abs_slider"])C:\Users\PragyaJatav\Downloads\Untitled Folder 2\simulatorAldi\pages\8_Scenario_Planner.py
         | 
| 175 | 
            -
            #         print("#" * 100)
         | 
| 176 | 
            -
             | 
| 177 | 
            -
            #         modified_spends = extract_number_for_string(
         | 
| 178 | 
            -
            #             st.session_state["total_spends_change_abs_slider"]
         | 
| 179 | 
            -
            #         )
         | 
| 180 | 
            -
            #         st.session_state["total_spends_change"] = (
         | 
| 181 | 
            -
            #             (modified_spends / actual_spends) - 1
         | 
| 182 | 
            -
            #         ) * 100
         | 
| 183 | 
            -
            #         st.session_state["total_spends_change_abs"] = st.session_state[
         | 
| 184 | 
            -
            #             "total_spends_change_abs_slider"
         | 
| 185 | 
            -
            #         ]
         | 
| 186 | 
            -
             | 
| 187 | 
            -
            #         update_all_spends()
         | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
            def update_all_spends_abs():
         | 
| 191 | 
            -
                if (
         | 
| 192 | 
            -
                    st.session_state["total_spends_change_abs"]
         | 
| 193 | 
            -
                    in st.session_state["total_spends_change_abs_slider_options"]
         | 
| 194 | 
            -
                ):
         | 
| 195 | 
            -
                    st.session_state["allow_spends_update"] = True
         | 
| 196 | 
            -
                else:
         | 
| 197 | 
            -
                    st.session_state["allow_spends_update"] = False
         | 
| 198 | 
            -
             | 
| 199 | 
            -
                actual_spends = _scenario.actual_total_spends
         | 
| 200 | 
            -
                if (
         | 
| 201 | 
            -
                    validate_input(st.session_state["total_spends_change_abs"])
         | 
| 202 | 
            -
                    and st.session_state["allow_spends_update"]
         | 
| 203 | 
            -
                ):
         | 
| 204 | 
            -
                    modified_spends = extract_number_for_string(
         | 
| 205 | 
            -
                        st.session_state["total_spends_change_abs"]
         | 
| 206 | 
            -
                    )
         | 
| 207 | 
            -
                    st.session_state["total_spends_change"] = (
         | 
| 208 | 
            -
                        (modified_spends / actual_spends) - 1
         | 
| 209 | 
            -
                    ) * 100
         | 
| 210 | 
            -
                    st.session_state["total_spends_change_abs_slider"] = st.session_state[
         | 
| 211 | 
            -
                        "total_spends_change_abs"
         | 
| 212 | 
            -
                    ]
         | 
| 213 | 
            -
             | 
| 214 | 
            -
                    update_all_spends()
         | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
            def update_spends():
         | 
| 218 | 
            -
                st.session_state["total_spends_change_abs"] = numerize(
         | 
| 219 | 
            -
                    (1 + st.session_state["total_spends_change"] / 100)
         | 
| 220 | 
            -
                    * _scenario.actual_total_spends,
         | 
| 221 | 
            -
                    1,
         | 
| 222 | 
            -
                )
         | 
| 223 | 
            -
                st.session_state["total_spends_change_abs_slider"] = numerize(
         | 
| 224 | 
            -
                    (1 + st.session_state["total_spends_change"] / 100)
         | 
| 225 | 
            -
                    * _scenario.actual_total_spends,
         | 
| 226 | 
            -
                    1,
         | 
| 227 | 
            -
                )
         | 
| 228 | 
            -
             | 
| 229 | 
            -
                update_all_spends()
         | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
            def update_all_spends():
         | 
| 233 | 
            -
                """
         | 
| 234 | 
            -
                Updates spends for all the channels with the given overall spends change
         | 
| 235 | 
            -
                """
         | 
| 236 | 
            -
                percent_change = st.session_state["total_spends_change"]
         | 
| 237 | 
            -
             | 
| 238 | 
            -
                for channel_name in st.session_state["channels_list"]:
         | 
| 239 | 
            -
                    channel = st.session_state["scenario"].channels[channel_name]
         | 
| 240 | 
            -
                    current_spends = channel.actual_total_spends
         | 
| 241 | 
            -
                    modified_spends = (1 + percent_change / 100) * current_spends
         | 
| 242 | 
            -
                    st.session_state["scenario"].update(channel_name, modified_spends)
         | 
| 243 | 
            -
                    st.session_state[channel_name] = numerize(
         | 
| 244 | 
            -
                        modified_spends * channel.conversion_rate, 1
         | 
| 245 | 
            -
                    )
         | 
| 246 | 
            -
                    st.session_state[f"{channel_name}_change"] = percent_change
         | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
            def extract_number_for_string(string_input):
         | 
| 250 | 
            -
                string_input = string_input.upper()
         | 
| 251 | 
            -
                if string_input.endswith("K"):
         | 
| 252 | 
            -
                    return float(string_input[:-1]) * 10**3
         | 
| 253 | 
            -
                elif string_input.endswith("M"):
         | 
| 254 | 
            -
                    return float(string_input[:-1]) * 10**6
         | 
| 255 | 
            -
                elif string_input.endswith("B"):
         | 
| 256 | 
            -
                    return float(string_input[:-1]) * 10**9
         | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
            def validate_input(string_input):
         | 
| 260 | 
            -
                pattern = r"\d+\.?\d*[K|M|B]$"
         | 
| 261 | 
            -
                match = re.match(pattern, string_input)
         | 
| 262 | 
            -
                if match is None:
         | 
| 263 | 
            -
                    return False
         | 
| 264 | 
            -
                return True
         | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
            def update_data_by_percent(channel_name):
         | 
| 268 | 
            -
                prev_spends = (
         | 
| 269 | 
            -
                    st.session_state["scenario"].channels[channel_name].actual_total_spends
         | 
| 270 | 
            -
                    * st.session_state["scenario"].channels[channel_name].conversion_rate
         | 
| 271 | 
            -
                )
         | 
| 272 | 
            -
                modified_spends = prev_spends * (
         | 
| 273 | 
            -
                    1 + st.session_state[f"{channel_name}_change"] / 100
         | 
| 274 | 
            -
                )
         | 
| 275 | 
            -
                st.session_state[channel_name] = numerize(modified_spends, 1)
         | 
| 276 | 
            -
                st.session_state["scenario"].update(
         | 
| 277 | 
            -
                    channel_name,
         | 
| 278 | 
            -
                    modified_spends
         | 
| 279 | 
            -
                    / st.session_state["scenario"].channels[channel_name].conversion_rate,
         | 
| 280 | 
            -
                )
         | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 283 | 
            -
            def update_data(channel_name):
         | 
| 284 | 
            -
                """
         | 
| 285 | 
            -
                Updates the spends for the given channel
         | 
| 286 | 
            -
                """
         | 
| 287 | 
            -
             | 
| 288 | 
            -
                if validate_input(st.session_state[channel_name]):
         | 
| 289 | 
            -
                    modified_spends = extract_number_for_string(st.session_state[channel_name])
         | 
| 290 | 
            -
                    prev_spends = (
         | 
| 291 | 
            -
                        st.session_state["scenario"].channels[channel_name].actual_total_spends
         | 
| 292 | 
            -
                        * st.session_state["scenario"].channels[channel_name].conversion_rate
         | 
| 293 | 
            -
                    )
         | 
| 294 | 
            -
                    st.session_state[f"{channel_name}_change"] = round(
         | 
| 295 | 
            -
                        100 * (modified_spends - prev_spends) / prev_spends, 2
         | 
| 296 | 
            -
                    )
         | 
| 297 | 
            -
                    st.session_state["scenario"].update(
         | 
| 298 | 
            -
                        channel_name,
         | 
| 299 | 
            -
                        modified_spends
         | 
| 300 | 
            -
                        / st.session_state["scenario"].channels[channel_name].conversion_rate,
         | 
| 301 | 
            -
                    )
         | 
| 302 | 
            -
                # st.session_state['scenario'].update(channel_name, modified_spends)
         | 
| 303 | 
            -
                # else:
         | 
| 304 | 
            -
                #     try:
         | 
| 305 | 
            -
                #         modified_spends = float(st.session_state[channel_name])
         | 
| 306 | 
            -
                #         prev_spends = st.session_state['scenario'].channels[channel_name].actual_total_spends * st.session_state['scenario'].channels[channel_name].conversion_rate
         | 
| 307 | 
            -
                #         st.session_state[f'{channel_name}_change'] = round(100*(modified_spends - prev_spends) / prev_spends,2)
         | 
| 308 | 
            -
                #         st.session_state['scenario'].update(channel_name, modified_spends/st.session_state['scenario'].channels[channel_name].conversion_rate)
         | 
| 309 | 
            -
                #         st.session_state[f'{channel_name}'] = numerize(modified_spends,1)
         | 
| 310 | 
            -
                #     except ValueError:
         | 
| 311 | 
            -
                #         st.write('Invalid input')
         | 
| 312 | 
            -
             | 
| 313 | 
            -
             | 
| 314 | 
            -
            def select_channel_for_optimization(channel_name):
         | 
| 315 | 
            -
                """
         | 
| 316 | 
            -
                Marks the given channel for optimization
         | 
| 317 | 
            -
                """
         | 
| 318 | 
            -
                st.session_state["optimization_channels"][channel_name] = st.session_state[
         | 
| 319 | 
            -
                    f"{channel_name}_selected"
         | 
| 320 | 
            -
                ]
         | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 323 | 
            -
            def select_all_channels_for_optimization():
         | 
| 324 | 
            -
                """
         | 
| 325 | 
            -
                Marks all the channel for optimization
         | 
| 326 | 
            -
                """
         | 
| 327 | 
            -
                for channel_name in st.session_state["optimization_channels"].keys():
         | 
| 328 | 
            -
                    st.session_state[f"{channel_name}_selected"] = st.session_state[
         | 
| 329 | 
            -
                        "optimze_all_channels"
         | 
| 330 | 
            -
                    ]
         | 
| 331 | 
            -
                    st.session_state["optimization_channels"][channel_name] = st.session_state[
         | 
| 332 | 
            -
                        "optimze_all_channels"
         | 
| 333 | 
            -
                    ]
         | 
| 334 | 
            -
             | 
| 335 | 
            -
             | 
| 336 | 
            -
            def update_penalty():
         | 
| 337 | 
            -
                """
         | 
| 338 | 
            -
                Updates the penalty flag for sales calculation
         | 
| 339 | 
            -
                """
         | 
| 340 | 
            -
                st.session_state["scenario"].update_penalty(st.session_state["apply_penalty"])
         | 
| 341 | 
            -
             | 
| 342 | 
            -
             | 
| 343 | 
            -
            def reset_scenario(panel_selected, file_selected, updated_rcs):
         | 
| 344 | 
            -
                # #print(st.session_state['default_scenario_dict'])
         | 
| 345 | 
            -
                # st.session_state['scenario']  = class_from_dict(st.session_state['default_scenario_dict'])
         | 
| 346 | 
            -
                # for channel in st.session_state['scenario'].channels.values():
         | 
| 347 | 
            -
                #     st.session_state[channel.name] = float(channel.actual_total_spends * channel.conversion_rate)
         | 
| 348 | 
            -
                # initialize_data()
         | 
| 349 | 
            -
             | 
| 350 | 
            -
                if panel_selected == "Total Market":
         | 
| 351 | 
            -
                    initialize_data(
         | 
| 352 | 
            -
                        panel=panel_selected,
         | 
| 353 | 
            -
                        target_file=file_selected,
         | 
| 354 | 
            -
                        updated_rcs=updated_rcs,
         | 
| 355 | 
            -
                        metrics=metrics_selected,
         | 
| 356 | 
            -
                    )
         | 
| 357 | 
            -
                    panel = None
         | 
| 358 | 
            -
                else:
         | 
| 359 | 
            -
                    initialize_data(
         | 
| 360 | 
            -
                        panel=panel_selected,
         | 
| 361 | 
            -
                        target_file=file_selected,
         | 
| 362 | 
            -
                        updated_rcs=updated_rcs,
         | 
| 363 | 
            -
                        metrics=metrics_selected,
         | 
| 364 | 
            -
                    )
         | 
| 365 | 
            -
             | 
| 366 | 
            -
                for channel_name in st.session_state["channels_list"]:
         | 
| 367 | 
            -
                    st.session_state[f"{channel_name}_selected"] = False
         | 
| 368 | 
            -
                    st.session_state[f"{channel_name}_change"] = 0
         | 
| 369 | 
            -
                st.session_state["optimze_all_channels"] = False
         | 
| 370 | 
            -
             | 
| 371 | 
            -
                st.session_state["total_sales_change"] = 0
         | 
| 372 | 
            -
             | 
| 373 | 
            -
                update_spends()
         | 
| 374 | 
            -
                update_sales()
         | 
| 375 | 
            -
             | 
| 376 | 
            -
                reset_inputs()
         | 
| 377 | 
            -
             | 
| 378 | 
            -
                # st.rerun()
         | 
| 379 | 
            -
             | 
| 380 | 
            -
             | 
| 381 | 
            -
            def format_number(num):
         | 
| 382 | 
            -
                if num >= 1_000_000:
         | 
| 383 | 
            -
                    return f"{num / 1_000_000:.2f}M"
         | 
| 384 | 
            -
                elif num >= 1_000:
         | 
| 385 | 
            -
                    return f"{num / 1_000:.0f}K"
         | 
| 386 | 
            -
                else:
         | 
| 387 | 
            -
                    return f"{num:.2f}"
         | 
| 388 | 
            -
             | 
| 389 | 
            -
             | 
| 390 | 
            -
            def summary_plot(data, x, y, title, text_column):
         | 
| 391 | 
            -
                fig = px.bar(
         | 
| 392 | 
            -
                    data,
         | 
| 393 | 
            -
                    x=x,
         | 
| 394 | 
            -
                    y=y,
         | 
| 395 | 
            -
                    orientation="h",
         | 
| 396 | 
            -
                    title=title,
         | 
| 397 | 
            -
                    text=text_column,
         | 
| 398 | 
            -
                    color="Channel_name",
         | 
| 399 | 
            -
                )
         | 
| 400 | 
            -
             | 
| 401 | 
            -
                # Convert text_column to numeric values
         | 
| 402 | 
            -
                data[text_column] = pd.to_numeric(data[text_column], errors="coerce")
         | 
| 403 | 
            -
             | 
| 404 | 
            -
                # Update the format of the displayed text based on magnitude
         | 
| 405 | 
            -
                fig.update_traces(
         | 
| 406 | 
            -
                    texttemplate="%{text:.2s}",
         | 
| 407 | 
            -
                    textposition="outside",
         | 
| 408 | 
            -
                    hovertemplate="%{x:.2s}",
         | 
| 409 | 
            -
                )
         | 
| 410 | 
            -
             | 
| 411 | 
            -
                fig.update_layout(xaxis_title=x, yaxis_title="Channel Name", showlegend=False)
         | 
| 412 | 
            -
                return fig
         | 
| 413 | 
            -
             | 
| 414 | 
            -
             | 
| 415 | 
            -
            def s_curve(x, K, b, a, x0):
         | 
| 416 | 
            -
                return K / (1 + b * np.exp(-a * (x - x0)))
         | 
| 417 | 
            -
             | 
| 418 | 
            -
             | 
| 419 | 
            -
            def find_segment_value(x, roi, mroi):
         | 
| 420 | 
            -
                start_value = x[0]
         | 
| 421 | 
            -
                end_value = x[len(x) - 1]
         | 
| 422 | 
            -
             | 
| 423 | 
            -
                # Condition for green region: Both MROI and ROI > 1
         | 
| 424 | 
            -
                green_condition = (roi > 1) & (mroi > 1)
         | 
| 425 | 
            -
                left_indices = np.where(green_condition)[0]
         | 
| 426 | 
            -
                left_value = x[left_indices[0]] if left_indices.size > 0 else x[0]
         | 
| 427 | 
            -
             | 
| 428 | 
            -
                right_indices = np.where(green_condition)[0]
         | 
| 429 | 
            -
                right_value = x[right_indices[-1]] if right_indices.size > 0 else x[0]
         | 
| 430 | 
            -
             | 
| 431 | 
            -
                return start_value, end_value, left_value, right_value
         | 
| 432 | 
            -
             | 
| 433 | 
            -
             | 
| 434 | 
            -
            def calculate_rgba(
         | 
| 435 | 
            -
                start_value, end_value, left_value, right_value, current_channel_spends
         | 
| 436 | 
            -
            ):
         | 
| 437 | 
            -
                # Initialize alpha to None for clarity
         | 
| 438 | 
            -
                alpha = None
         | 
| 439 | 
            -
             | 
| 440 | 
            -
                # Determine the color and calculate relative_position and alpha based on the point's position
         | 
| 441 | 
            -
                if start_value <= current_channel_spends <= left_value:
         | 
| 442 | 
            -
                    color = "yellow"
         | 
| 443 | 
            -
                    relative_position = (current_channel_spends - start_value) / (
         | 
| 444 | 
            -
                        left_value - start_value
         | 
| 445 | 
            -
                    )
         | 
| 446 | 
            -
                    alpha = 0.8 - (0.6 * relative_position)  # Alpha decreases from start to end
         | 
| 447 | 
            -
             | 
| 448 | 
            -
                elif left_value < current_channel_spends <= right_value:
         | 
| 449 | 
            -
                    color = "green"
         | 
| 450 | 
            -
                    relative_position = (current_channel_spends - left_value) / (
         | 
| 451 | 
            -
                        right_value - left_value
         | 
| 452 | 
            -
                    )
         | 
| 453 | 
            -
                    alpha = 0.8 - (0.6 * relative_position)  # Alpha decreases from start to end
         | 
| 454 | 
            -
             | 
| 455 | 
            -
                elif right_value < current_channel_spends <= end_value:
         | 
| 456 | 
            -
                    color = "red"
         | 
| 457 | 
            -
                    relative_position = (current_channel_spends - right_value) / (
         | 
| 458 | 
            -
                        end_value - right_value
         | 
| 459 | 
            -
                    )
         | 
| 460 | 
            -
                    alpha = 0.2 + (0.6 * relative_position)  # Alpha increases from start to end
         | 
| 461 | 
            -
             | 
| 462 | 
            -
                else:
         | 
| 463 | 
            -
                    # Default case, if the spends are outside the defined ranges
         | 
| 464 | 
            -
                    return "rgba(136, 136, 136, 0.5)"  # Grey for values outside the range
         | 
| 465 | 
            -
             | 
| 466 | 
            -
                # Ensure alpha is within the intended range in case of any calculation overshoot
         | 
| 467 | 
            -
                alpha = max(0.2, min(alpha, 0.8))
         | 
| 468 | 
            -
             | 
| 469 | 
            -
                # Define color codes for RGBA
         | 
| 470 | 
            -
                color_codes = {
         | 
| 471 | 
            -
                    "yellow": "255, 255, 0",  # RGB for yellow
         | 
| 472 | 
            -
                    "green": "0, 128, 0",  # RGB for green
         | 
| 473 | 
            -
                    "red": "255, 0, 0",  # RGB for red
         | 
| 474 | 
            -
                }
         | 
| 475 | 
            -
             | 
| 476 | 
            -
                rgba = f"rgba({color_codes[color]}, {alpha})"
         | 
| 477 | 
            -
                return rgba
         | 
| 478 | 
            -
             | 
| 479 | 
            -
             | 
| 480 | 
            -
            def debug_temp(x_test, power, K, b, a, x0):
         | 
| 481 | 
            -
                print("*" * 100)
         | 
| 482 | 
            -
                # Calculate the count of bins
         | 
| 483 | 
            -
                count_lower_bin = sum(1 for x in x_test if x <= 2524)
         | 
| 484 | 
            -
                count_center_bin = sum(1 for x in x_test if x > 2524 and x <= 3377)
         | 
| 485 | 
            -
                count_ = sum(1 for x in x_test if x > 3377)
         | 
| 486 | 
            -
             | 
| 487 | 
            -
                print(
         | 
| 488 | 
            -
                    f"""
         | 
| 489 | 
            -
                        lower : {count_lower_bin}
         | 
| 490 | 
            -
                        center : {count_center_bin}
         | 
| 491 | 
            -
                        upper : {count_}
         | 
| 492 | 
            -
                      """
         | 
| 493 | 
            -
                )
         | 
| 494 | 
            -
             | 
| 495 | 
            -
             | 
| 496 | 
            -
            # @st.cache
         | 
| 497 | 
            -
            def plot_response_curves(summary_df_sorted):
         | 
| 498 | 
            -
                # cols = 3
         | 
| 499 | 
            -
                # rows = (
         | 
| 500 | 
            -
                #     len(channels_list) // cols
         | 
| 501 | 
            -
                #     if len(channels_list) % cols == 0
         | 
| 502 | 
            -
                #     else len(channels_list) // cols + 1
         | 
| 503 | 
            -
                # )
         | 
| 504 | 
            -
                # rcs = st.session_state["rcs"]
         | 
| 505 | 
            -
                # shapes = []
         | 
| 506 | 
            -
                # fig = make_subplots(rows=rows, cols=cols, subplot_titles=channels_list)
         | 
| 507 | 
            -
                channel_cols = [
         | 
| 508 | 
            -
                'BroadcastTV',
         | 
| 509 | 
            -
                'CableTV',
         | 
| 510 | 
            -
                'Connected&OTTTV',
         | 
| 511 | 
            -
                'DisplayProspecting',
         | 
| 512 | 
            -
                'DisplayRetargeting',
         | 
| 513 | 
            -
                    'Video',
         | 
| 514 | 
            -
                'SocialProspecting',
         | 
| 515 | 
            -
                'SocialRetargeting',
         | 
| 516 | 
            -
                'SearchBrand',
         | 
| 517 | 
            -
                'SearchNon-brand',
         | 
| 518 | 
            -
                'DigitalPartners',
         | 
| 519 | 
            -
                'Audio',
         | 
| 520 | 
            -
                'Email']
         | 
| 521 | 
            -
                summary_df_sorted.index = summary_df_sorted["Channel_name"]
         | 
| 522 | 
            -
                for i in range(0, len(channels_list)):
         | 
| 523 | 
            -
                    col = channels_list[i]
         | 
| 524 | 
            -
                    if col == "Panel":
         | 
| 525 | 
            -
                        continue
         | 
| 526 | 
            -
                    st.write(col)
         | 
| 527 | 
            -
                    x_modified = summary_df_sorted["Optimized_spend"][col]/104
         | 
| 528 | 
            -
                    y_modified = summary_df_sorted["New_sales"][col]/104
         | 
| 529 | 
            -
                    st.plotly_chart(rc.response_curves(col,x_modified,y_modified))
         | 
| 530 | 
            -
                    
         | 
| 531 | 
            -
             | 
| 532 | 
            -
            # @st.cache
         | 
| 533 | 
            -
            # def plot_response_curves():
         | 
| 534 | 
            -
            #     cols = 4
         | 
| 535 | 
            -
            #     rcs = st.session_state["rcs"]
         | 
| 536 | 
            -
            #     shapes = []
         | 
| 537 | 
            -
            #     fig = make_subplots(rows=6, cols=cols, subplot_titles=channels_list)
         | 
| 538 | 
            -
            #     for i in range(0, len(channels_list)):
         | 
| 539 | 
            -
            #         col = channels_list[i]
         | 
| 540 | 
            -
            #         x = st.session_state["actual_df"][col].values
         | 
| 541 | 
            -
            #         spends = x.sum()
         | 
| 542 | 
            -
            #         power = np.ceil(np.log(x.max()) / np.log(10)) - 3
         | 
| 543 | 
            -
            #         x = np.linspace(0, 3 * x.max(), 200)
         | 
| 544 | 
            -
             | 
| 545 | 
            -
            #         K = rcs[col]["K"]
         | 
| 546 | 
            -
            #         b = rcs[col]["b"]
         | 
| 547 | 
            -
            #         a = rcs[col]["a"]
         | 
| 548 | 
            -
            #         x0 = rcs[col]["x0"]
         | 
| 549 | 
            -
             | 
| 550 | 
            -
            #         y = s_curve(x / 10**power, K, b, a, x0)
         | 
| 551 | 
            -
            #         roi = y / x
         | 
| 552 | 
            -
            #         marginal_roi = a * (y) * (1 - y / K)
         | 
| 553 | 
            -
            #         fig.add_trace(
         | 
| 554 | 
            -
            #             go.Scatter(
         | 
| 555 | 
            -
            #                 x=52
         | 
| 556 | 
            -
            #                 * x
         | 
| 557 | 
            -
            #                 * st.session_state["scenario"].channels[col].conversion_rate,
         | 
| 558 | 
            -
            #                 y=52 * y,
         | 
| 559 | 
            -
            #                 name=col,
         | 
| 560 | 
            -
            #                 customdata=np.stack((roi, marginal_roi), axis=-1),
         | 
| 561 | 
            -
            #                 hovertemplate="Spend:%{x:$.2s}<br>Sale:%{y:$.2s}<br>ROI:%{customdata[0]:.3f}<br>MROI:%{customdata[1]:.3f}",
         | 
| 562 | 
            -
            #             ),
         | 
| 563 | 
            -
            #             row=1 + (i) // cols,
         | 
| 564 | 
            -
            #             col=i % cols + 1,
         | 
| 565 | 
            -
            #         )
         | 
| 566 | 
            -
             | 
| 567 | 
            -
            #         fig.add_trace(
         | 
| 568 | 
            -
            #             go.Scatter(
         | 
| 569 | 
            -
            #                 x=[
         | 
| 570 | 
            -
            #                     spends
         | 
| 571 | 
            -
            #                     * st.session_state["scenario"]
         | 
| 572 | 
            -
            #                     .channels[col]
         | 
| 573 | 
            -
            #                     .conversion_rate
         | 
| 574 | 
            -
            #                 ],
         | 
| 575 | 
            -
            #                 y=[52 * s_curve(spends / (10**power * 52), K, b, a, x0)],
         | 
| 576 | 
            -
            #                 name=col,
         | 
| 577 | 
            -
            #                 legendgroup=col,
         | 
| 578 | 
            -
            #                 showlegend=False,
         | 
| 579 | 
            -
            #                 marker=dict(color=["black"]),
         | 
| 580 | 
            -
            #             ),
         | 
| 581 | 
            -
            #             row=1 + (i) // cols,
         | 
| 582 | 
            -
            #             col=i % cols + 1,
         | 
| 583 | 
            -
            #         )
         | 
| 584 | 
            -
             | 
| 585 | 
            -
            #         shapes.append(
         | 
| 586 | 
            -
            #             go.layout.Shape(
         | 
| 587 | 
            -
            #                 type="line",
         | 
| 588 | 
            -
            #                 x0=0,
         | 
| 589 | 
            -
            #                 y0=52 * s_curve(spends / (10**power * 52), K, b, a, x0),
         | 
| 590 | 
            -
            #                 x1=spends
         | 
| 591 | 
            -
            #                 * st.session_state["scenario"].channels[col].conversion_rate,
         | 
| 592 | 
            -
            #                 y1=52 * s_curve(spends / (10**power * 52), K, b, a, x0),
         | 
| 593 | 
            -
            #                 line_width=1,
         | 
| 594 | 
            -
            #                 line_dash="dash",
         | 
| 595 | 
            -
            #                 line_color="black",
         | 
| 596 | 
            -
            #                 xref=f"x{i+1}",
         | 
| 597 | 
            -
            #                 yref=f"y{i+1}",
         | 
| 598 | 
            -
            #             )
         | 
| 599 | 
            -
            #         )
         | 
| 600 | 
            -
             | 
| 601 | 
            -
            #         shapes.append(
         | 
| 602 | 
            -
            #             go.layout.Shape(
         | 
| 603 | 
            -
            #                 type="line",
         | 
| 604 | 
            -
            #                 x0=spends
         | 
| 605 | 
            -
            #                 * st.session_state["scenario"].channels[col].conversion_rate,
         | 
| 606 | 
            -
            #                 y0=0,
         | 
| 607 | 
            -
            #                 x1=spends
         | 
| 608 | 
            -
            #                 * st.session_state["scenario"].channels[col].conversion_rate,
         | 
| 609 | 
            -
            #                 y1=52 * s_curve(spends / (10**power * 52), K, b, a, x0),
         | 
| 610 | 
            -
            #                 line_width=1,
         | 
| 611 | 
            -
            #                 line_dash="dash",
         | 
| 612 | 
            -
            #                 line_color="black",
         | 
| 613 | 
            -
            #                 xref=f"x{i+1}",
         | 
| 614 | 
            -
            #                 yref=f"y{i+1}",
         | 
| 615 | 
            -
            #             )
         | 
| 616 | 
            -
            #         )
         | 
| 617 | 
            -
             | 
| 618 | 
            -
            #     fig.update_layout(
         | 
| 619 | 
            -
            #         height=1500,
         | 
| 620 | 
            -
            #         width=1000,
         | 
| 621 | 
            -
            #         title_text="Response Curves",
         | 
| 622 | 
            -
            #         showlegend=False,
         | 
| 623 | 
            -
            #         shapes=shapes,
         | 
| 624 | 
            -
            #     )
         | 
| 625 | 
            -
            #     fig.update_annotations(font_size=10)
         | 
| 626 | 
            -
            #     fig.update_xaxes(title="Spends")
         | 
| 627 | 
            -
            #     fig.update_yaxes(title=target)
         | 
| 628 | 
            -
            #     return fig
         | 
| 629 | 
            -
             | 
| 630 | 
            -
             | 
| 631 | 
            -
            # ======================================================== #
         | 
| 632 | 
            -
            # ==================== HTML Components =================== #
         | 
| 633 | 
            -
            # ======================================================== #
         | 
| 634 | 
            -
             | 
| 635 | 
            -
             | 
| 636 | 
            -
            def generate_spending_header(heading):
         | 
| 637 | 
            -
                return st.markdown(
         | 
| 638 | 
            -
                    f"""<h2 class="spends-header">{heading}</h2>""", unsafe_allow_html=True
         | 
| 639 | 
            -
                )
         | 
| 640 | 
            -
             | 
| 641 | 
            -
             | 
| 642 | 
            -
            # ======================================================== #
         | 
| 643 | 
            -
            # =================== Session variables ================== #
         | 
| 644 | 
            -
            # ======================================================== #
         | 
| 645 | 
            -
             | 
| 646 | 
            -
            with open("config.yaml") as file:
         | 
| 647 | 
            -
                config = yaml.load(file, Loader=SafeLoader)
         | 
| 648 | 
            -
                st.session_state["config"] = config
         | 
| 649 | 
            -
             | 
| 650 | 
            -
            authenticator = stauth.Authenticate(
         | 
| 651 | 
            -
                config["credentials"],
         | 
| 652 | 
            -
                config["cookie"]["name"],
         | 
| 653 | 
            -
                config["cookie"]["key"],
         | 
| 654 | 
            -
                config["cookie"]["expiry_days"],
         | 
| 655 | 
            -
                config["preauthorized"],
         | 
| 656 | 
            -
            )
         | 
| 657 | 
            -
            st.session_state["authenticator"] = authenticator
         | 
| 658 | 
            -
            name, authentication_status, username = authenticator.login("Login", "main")
         | 
| 659 | 
            -
            auth_status = st.session_state.get("authentication_status")
         | 
| 660 | 
            -
             | 
| 661 | 
            -
            import os
         | 
| 662 | 
            -
            import glob
         | 
| 663 | 
            -
             | 
| 664 | 
            -
             | 
| 665 | 
            -
            def get_excel_names(directory):
         | 
| 666 | 
            -
                # Create a list to hold the final parts of the filenames
         | 
| 667 | 
            -
                last_portions = []
         | 
| 668 | 
            -
             | 
| 669 | 
            -
                # Patterns to match Excel files (.xlsx and .xls) that contain @#
         | 
| 670 | 
            -
                patterns = [
         | 
| 671 | 
            -
                    os.path.join(directory, "*@#*.xlsx"),
         | 
| 672 | 
            -
                    os.path.join(directory, "*@#*.xls"),
         | 
| 673 | 
            -
                ]
         | 
| 674 | 
            -
             | 
| 675 | 
            -
                # Process each pattern
         | 
| 676 | 
            -
                for pattern in patterns:
         | 
| 677 | 
            -
                    files = glob.glob(pattern)
         | 
| 678 | 
            -
             | 
| 679 | 
            -
                    # Extracting the last portion after @# for each file
         | 
| 680 | 
            -
                    for file in files:
         | 
| 681 | 
            -
                        base_name = os.path.basename(file)
         | 
| 682 | 
            -
                        last_portion = base_name.split("@#")[-1]
         | 
| 683 | 
            -
                        last_portion = last_portion.replace(".xlsx", "").replace(
         | 
| 684 | 
            -
                            ".xls", ""
         | 
| 685 | 
            -
                        )  # Removing extensions
         | 
| 686 | 
            -
                        last_portions.append(last_portion)
         | 
| 687 | 
            -
             | 
| 688 | 
            -
                return last_portions
         | 
| 689 | 
            -
             | 
| 690 | 
            -
             | 
| 691 | 
            -
            def name_formating(channel_name):
         | 
| 692 | 
            -
                # Replace underscores with spaces
         | 
| 693 | 
            -
                name_mod = channel_name.replace("_", " ")
         | 
| 694 | 
            -
             | 
| 695 | 
            -
                # Capitalize the first letter of each word
         | 
| 696 | 
            -
                name_mod = name_mod.title()
         | 
| 697 | 
            -
             | 
| 698 | 
            -
                return name_mod
         | 
| 699 | 
            -
             | 
| 700 | 
            -
             | 
| 701 | 
            -
            @st.cache_data(show_spinner=False)
         | 
| 702 | 
            -
            def panel_fetch(file_selected):
         | 
| 703 | 
            -
                raw_data_mmm_df = pd.read_excel(file_selected, sheet_name="RAW DATA MMM")
         | 
| 704 | 
            -
             | 
| 705 | 
            -
                # if "Panel" in raw_data_mmm_df.columns:
         | 
| 706 | 
            -
                #     panel = list(set(raw_data_mmm_df["Panel"]))
         | 
| 707 | 
            -
                # else:
         | 
| 708 | 
            -
                #     raw_data_mmm_df = None
         | 
| 709 | 
            -
                #     panel = None
         | 
| 710 | 
            -
                # raw_data_mmm_df = None
         | 
| 711 | 
            -
                panel = None
         | 
| 712 | 
            -
                return panel
         | 
| 713 | 
            -
             | 
| 714 | 
            -
             | 
| 715 | 
            -
            def reset_inputs():
         | 
| 716 | 
            -
                if "total_spends_change_abs" in st.session_state:
         | 
| 717 | 
            -
                    del st.session_state.total_spends_change_abs
         | 
| 718 | 
            -
                if "total_spends_change" in st.session_state:
         | 
| 719 | 
            -
                    del st.session_state.total_spends_change
         | 
| 720 | 
            -
                if "total_spends_change_abs_slider" in st.session_state:
         | 
| 721 | 
            -
                    del st.session_state.total_spends_change_abs_slider
         | 
| 722 | 
            -
             | 
| 723 | 
            -
                if "total_sales_change_abs" in st.session_state:
         | 
| 724 | 
            -
                    del st.session_state.total_sales_change_abs
         | 
| 725 | 
            -
                if "total_sales_change" in st.session_state:
         | 
| 726 | 
            -
                    del st.session_state.total_sales_change
         | 
| 727 | 
            -
                if "total_sales_change_abs_slider" in st.session_state:
         | 
| 728 | 
            -
                    del st.session_state.total_sales_change_abs_slider
         | 
| 729 | 
            -
             | 
| 730 | 
            -
                st.session_state["initialized"] = False
         | 
| 731 | 
            -
             | 
| 732 | 
            -
             | 
| 733 | 
            -
            if auth_status == True:
         | 
| 734 | 
            -
                authenticator.logout("Logout", "main")
         | 
| 735 | 
            -
                st.header("Scenario Planner")
         | 
| 736 | 
            -
                def scenario_planner_plots():
         | 
| 737 | 
            -
                    
         | 
| 738 | 
            -
                    with st.expander('Optimized Spends Overview'):
         | 
| 739 | 
            -
                        # if st.button('Refresh'):
         | 
| 740 | 
            -
                        #     st.experimental_rerun()
         | 
| 741 | 
            -
             | 
| 742 | 
            -
                        import plotly.graph_objects as go
         | 
| 743 | 
            -
                        from plotly.subplots import make_subplots
         | 
| 744 | 
            -
             | 
| 745 | 
            -
                        # Define light colors for bars
         | 
| 746 | 
            -
                        import plotly.graph_objects as go
         | 
| 747 | 
            -
                        from plotly.subplots import make_subplots
         | 
| 748 | 
            -
             | 
| 749 | 
            -
                        st.empty()
         | 
| 750 | 
            -
                        #st.header('Model Result Analysis')
         | 
| 751 | 
            -
                        spends_data=pd.read_excel('Overview_data_test.xlsx')
         | 
| 752 | 
            -
             | 
| 753 | 
            -
                        with open('summary_df.pkl', 'rb') as file:
         | 
| 754 | 
            -
                            summary_df_sorted = pickle.load(file)
         | 
| 755 | 
            -
                        #st.write(summary_df_sorted)
         | 
| 756 | 
            -
             | 
| 757 | 
            -
                        # selected_scenario= st.selectbox('Select Saved Scenarios',['S1','S2']) 
         | 
| 758 | 
            -
                        summary_df_sorted=summary_df_sorted.sort_values(by=['Optimized_spend'],ascending=False)
         | 
| 759 | 
            -
                        summary_df_sorted['old_efficiency']=(summary_df_sorted['Old_sales']/summary_df_sorted['Old_sales'].sum())/(summary_df_sorted['Actual_spend']/summary_df_sorted['Actual_spend'].sum())
         | 
| 760 | 
            -
                        summary_df_sorted['new_efficiency']=(summary_df_sorted['New_sales']/summary_df_sorted['New_sales'].sum())/(summary_df_sorted['Optimized_spend']/summary_df_sorted['Optimized_spend'].sum())
         | 
| 761 | 
            -
             | 
| 762 | 
            -
                        summary_df_sorted['old_roi']=summary_df_sorted['Old_sales']/summary_df_sorted['Actual_spend']
         | 
| 763 | 
            -
                        summary_df_sorted['new_roi']=summary_df_sorted['New_sales']/summary_df_sorted['Optimized_spend']
         | 
| 764 | 
            -
             | 
| 765 | 
            -
                        total_actual_spend = summary_df_sorted['Actual_spend'].sum()
         | 
| 766 | 
            -
                        total_optimized_spend = summary_df_sorted['Optimized_spend'].sum()
         | 
| 767 | 
            -
             | 
| 768 | 
            -
                        actual_spend_percentage = (summary_df_sorted['Actual_spend'] / total_actual_spend) * 100
         | 
| 769 | 
            -
                        optimized_spend_percentage = (summary_df_sorted['Optimized_spend'] / total_optimized_spend) * 100
         | 
| 770 | 
            -
             | 
| 771 | 
            -
             | 
| 772 | 
            -
             | 
| 773 | 
            -
                        light_blue = 'rgba(0, 31, 120, 0.7)'
         | 
| 774 | 
            -
                        light_orange = 'rgba(0, 181, 219, 0.7)'
         | 
| 775 | 
            -
                        light_green = 'rgba(240, 61, 20, 0.7)'
         | 
| 776 | 
            -
                        light_red = 'rgba(250, 110, 10, 0.7)'
         | 
| 777 | 
            -
                        light_purple = 'rgba(255, 191, 69, 0.7)'
         | 
| 778 | 
            -
             | 
| 779 | 
            -
             | 
| 780 | 
            -
                        # # Create subplots with one row and two columns
         | 
| 781 | 
            -
                        # fig = make_subplots(rows=3, cols=1, subplot_titles=("Actual vs. Optimized Spend", "Actual vs. Optimized Contribution", "Actual vs. Optimized ROI"))
         | 
| 782 | 
            -
             | 
| 783 | 
            -
                        # # Add actual vs optimized spend bars
         | 
| 784 | 
            -
             | 
| 785 | 
            -
                        
         | 
| 786 | 
            -
                        # fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['Actual_spend'], name='Actual',
         | 
| 787 | 
            -
                        #                      text=summary_df_sorted['Actual_spend'].apply(format_number) + ' '+' (' + actual_spend_percentage.round(2).astype(str) + '%)',
         | 
| 788 | 
            -
                        #                        marker_color=light_blue, orientation='h'), 
         | 
| 789 | 
            -
                        #                      row=1,
         | 
| 790 | 
            -
                        #                        col=1)
         | 
| 791 | 
            -
                        
         | 
| 792 | 
            -
                        
         | 
| 793 | 
            -
                        # fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['Optimized_spend'], name='Optimized',
         | 
| 794 | 
            -
                        #                      text=summary_df_sorted['Optimized_spend'].apply(format_number) + ' (' + optimized_spend_percentage.round(2).astype(str) + '%)',
         | 
| 795 | 
            -
                        #                        marker_color=light_orange, 
         | 
| 796 | 
            -
                        #                        orientation='h'),
         | 
| 797 | 
            -
                        #                          row=1, 
         | 
| 798 | 
            -
                        #                          col=1)
         | 
| 799 | 
            -
                        
         | 
| 800 | 
            -
                        # fig.update_xaxes(title_text="Amount", row=1, col=1)
         | 
| 801 | 
            -
             | 
| 802 | 
            -
                        # # Add actual vs optimized Contribution
         | 
| 803 | 
            -
                        # fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['New_sales'],
         | 
| 804 | 
            -
                        #                       name='Optimized Contribution',text=summary_df_sorted['New_sales'].apply(format_number), 
         | 
| 805 | 
            -
                        #                       marker_color=light_orange, orientation='h',showlegend=False), row=2, col=1)
         | 
| 806 | 
            -
                        
         | 
| 807 | 
            -
                        # fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['Old_sales'], 
         | 
| 808 | 
            -
                        #                      name='Actual Contribution',text=summary_df_sorted['Old_sales'].apply(format_number), 
         | 
| 809 | 
            -
                        #                      marker_color=light_blue, orientation='h',showlegend=False), row=2, col=1)
         | 
| 810 | 
            -
                        
         | 
| 811 | 
            -
                
         | 
| 812 | 
            -
                        # fig.update_xaxes(title_text="Contribution", row=2, col=1) 
         | 
| 813 | 
            -
             | 
| 814 | 
            -
                        # # Add actual vs optimized ROI bars
         | 
| 815 | 
            -
                                
         | 
| 816 | 
            -
                        # fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['new_roi'], 
         | 
| 817 | 
            -
                        #                      name='Optimized ROI',text=summary_df_sorted['new_roi'].apply(format_number) , 
         | 
| 818 | 
            -
                        #                      marker_color=light_orange, orientation='h',showlegend=False), row=3, col=1)
         | 
| 819 | 
            -
                        
         | 
| 820 | 
            -
                        # fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['old_roi'], 
         | 
| 821 | 
            -
                        #                      name='Actual ROI', text=summary_df_sorted['old_roi'].apply(format_number) ,
         | 
| 822 | 
            -
                        #                        marker_color=light_blue, orientation='h',showlegend=False), row=3, col=1)
         | 
| 823 | 
            -
             | 
| 824 | 
            -
                        # fig.update_xaxes(title_text="ROI", row=3, col=1)
         | 
| 825 | 
            -
             | 
| 826 | 
            -
                        # # Update layout
         | 
| 827 | 
            -
                        # fig.update_layout(title_text="Actual vs. Optimized Metrics for Media Channels",
         | 
| 828 | 
            -
                        #                    showlegend=True, yaxis=dict(title='Media Channels', autorange="reversed"))
         | 
| 829 | 
            -
             | 
| 830 | 
            -
                        # st.plotly_chart(fig,use_container_width=True)
         | 
| 831 | 
            -
             | 
| 832 | 
            -
                        # Create subplots with one row and two columns
         | 
| 833 | 
            -
                        fig = go.Figure()
         | 
| 834 | 
            -
                        # Add actual vs optimized spend bars
         | 
| 835 | 
            -
             | 
| 836 | 
            -
                        
         | 
| 837 | 
            -
                        fig.add_trace(go.Bar(x=summary_df_sorted['Channel_name'], y=summary_df_sorted['Actual_spend'], name='Actual',
         | 
| 838 | 
            -
                                            text=summary_df_sorted['Actual_spend'].apply(format_number) + ' '
         | 
| 839 | 
            -
                                            #  + 
         | 
| 840 | 
            -
                                            #  ' '+
         | 
| 841 | 
            -
                                            # '</br> (' + actual_spend_percentage.astype(int).astype(str) + '%)'
         | 
| 842 | 
            -
                                            ,textposition='outside',#textfont=dict(size=30), 
         | 
| 843 | 
            -
                                            marker_color=light_blue))
         | 
| 844 | 
            -
                        
         | 
| 845 | 
            -
                        
         | 
| 846 | 
            -
                        fig.add_trace(go.Bar(x=summary_df_sorted['Channel_name'], y=summary_df_sorted['Optimized_spend'], name='Optimized',
         | 
| 847 | 
            -
                                            text=summary_df_sorted['Optimized_spend'].apply(format_number) + ' '
         | 
| 848 | 
            -
                                            #    + 
         | 
| 849 | 
            -
                                            #  '</br> (' + optimized_spend_percentage.astype(int).astype(str) + '%)'
         | 
| 850 | 
            -
                                            ,textposition='outside',#textfont=dict(size=30), 
         | 
| 851 | 
            -
                                            marker_color=light_orange))
         | 
| 852 | 
            -
                        
         | 
| 853 | 
            -
                        fig.update_xaxes(title_text="Channels")
         | 
| 854 | 
            -
                        fig.update_yaxes(title_text="Spends ($)")
         | 
| 855 | 
            -
                        fig.update_layout(
         | 
| 856 | 
            -
                            title = "Actual vs. Optimized Spends",
         | 
| 857 | 
            -
                                    margin=dict(t=40, b=40, l=40, r=40)
         | 
| 858 | 
            -
                                )
         | 
| 859 | 
            -
                        
         | 
| 860 | 
            -
                        st.plotly_chart(fig,use_container_width=True)
         | 
| 861 | 
            -
             | 
| 862 | 
            -
                        # Add actual vs optimized Contribution
         | 
| 863 | 
            -
                        fig = go.Figure()
         | 
| 864 | 
            -
                        fig.add_trace(go.Bar(x=summary_df_sorted['Channel_name'], y=summary_df_sorted['Old_sales'], 
         | 
| 865 | 
            -
                                            name='Actual Contribution',text=summary_df_sorted['Old_sales'].apply(format_number),textposition='outside', 
         | 
| 866 | 
            -
                                            marker_color=light_blue,showlegend=True))
         | 
| 867 | 
            -
                        
         | 
| 868 | 
            -
                        fig.add_trace(go.Bar(x=summary_df_sorted['Channel_name'], y=summary_df_sorted['New_sales'],
         | 
| 869 | 
            -
                                            name='Optimized Contribution',text=summary_df_sorted['New_sales'].apply(format_number),textposition='outside', 
         | 
| 870 | 
            -
                                            marker_color=light_orange, showlegend=True))
         | 
| 871 | 
            -
                        
         | 
| 872 | 
            -
                        
         | 
| 873 | 
            -
                
         | 
| 874 | 
            -
                        fig.update_yaxes(title_text="Contribution")
         | 
| 875 | 
            -
                        fig.update_xaxes(title_text="Channels") 
         | 
| 876 | 
            -
                        fig.update_layout(
         | 
| 877 | 
            -
                            title = "Actual vs. Optimized Contributions",
         | 
| 878 | 
            -
                                    margin=dict(t=40, b=40, l=40, r=40)
         | 
| 879 | 
            -
                                    # yaxis=dict(range=[0, 0.002]),
         | 
| 880 | 
            -
                                )
         | 
| 881 | 
            -
                        st.plotly_chart(fig,use_container_width=True)
         | 
| 882 | 
            -
             | 
| 883 | 
            -
                        # Add actual vs optimized Efficiency bars
         | 
| 884 | 
            -
                        fig = go.Figure()
         | 
| 885 | 
            -
                        summary_df_sorted_p =  summary_df_sorted[summary_df_sorted['Channel_name']!="Panel"]
         | 
| 886 | 
            -
                        fig.add_trace(go.Bar(x=summary_df_sorted_p['Channel_name'], y=summary_df_sorted_p['old_efficiency'], 
         | 
| 887 | 
            -
                                            name='Actual Efficiency', text=summary_df_sorted_p['old_efficiency'].apply(format_number) ,textposition='outside',
         | 
| 888 | 
            -
                                            marker_color=light_blue,showlegend=True))
         | 
| 889 | 
            -
                        fig.add_trace(go.Bar(x=summary_df_sorted_p['Channel_name'], y=summary_df_sorted_p['new_efficiency'], 
         | 
| 890 | 
            -
                                            name='Optimized Efficiency',text=summary_df_sorted_p['new_efficiency'].apply(format_number),textposition='outside' , 
         | 
| 891 | 
            -
                                            marker_color=light_orange,showlegend=True))
         | 
| 892 | 
            -
                        
         | 
| 893 | 
            -
                        fig.update_xaxes(title_text="Channels")
         | 
| 894 | 
            -
                        fig.update_yaxes(title_text="ROI")
         | 
| 895 | 
            -
                        fig.update_layout(
         | 
| 896 | 
            -
                            title = "Actual vs. Optimized ROI",
         | 
| 897 | 
            -
                                    margin=dict(t=40, b=40, l=40, r=40),
         | 
| 898 | 
            -
                                    # yaxis=dict(range=[0, 0.002]),
         | 
| 899 | 
            -
                                )
         | 
| 900 | 
            -
                            
         | 
| 901 | 
            -
                        st.plotly_chart(fig,use_container_width=True)
         | 
| 902 | 
            -
             | 
| 903 | 
            -
             | 
| 904 | 
            -
                # Response Metrics
         | 
| 905 | 
            -
                directory = "metrics_level_data"
         | 
| 906 | 
            -
                metrics_list = get_excel_names(directory)
         | 
| 907 | 
            -
                
         | 
| 908 | 
            -
                # metrics_selected = col1.selectbox(
         | 
| 909 | 
            -
                #     "Response Metrics",
         | 
| 910 | 
            -
                #     metrics_list,
         | 
| 911 | 
            -
                #     format_func=name_formating,
         | 
| 912 | 
            -
                #     index=0,
         | 
| 913 | 
            -
                #     on_change=reset_inputs,
         | 
| 914 | 
            -
                # )
         | 
| 915 | 
            -
             | 
| 916 | 
            -
                metrics_selected='prospects'
         | 
| 917 | 
            -
                # Target
         | 
| 918 | 
            -
                target = name_formating(metrics_selected)
         | 
| 919 | 
            -
             | 
| 920 | 
            -
                file_selected = (
         | 
| 921 | 
            -
                    f"Overview_data_test_panel@#{metrics_selected}.xlsx"
         | 
| 922 | 
            -
                )
         | 
| 923 | 
            -
             | 
| 924 | 
            -
                # Panel List
         | 
| 925 | 
            -
                panel_list = panel_fetch(file_selected)
         | 
| 926 | 
            -
             | 
| 927 | 
            -
                # # Panel Selected
         | 
| 928 | 
            -
                # panel_selected = st.selectbox(
         | 
| 929 | 
            -
                #     "Markets",
         | 
| 930 | 
            -
                #     ["Total Market"] + panel_list,
         | 
| 931 | 
            -
                #     index=0,
         | 
| 932 | 
            -
                #     on_change=reset_inputs,
         | 
| 933 | 
            -
                # )
         | 
| 934 | 
            -
                
         | 
| 935 | 
            -
                # st.write(panel_selected)
         | 
| 936 | 
            -
                panel_selected = "Total Market"
         | 
| 937 | 
            -
                st.session_state['selected_markets']=panel_selected
         | 
| 938 | 
            -
             | 
| 939 | 
            -
                if "update_rcs" in st.session_state:
         | 
| 940 | 
            -
                    updated_rcs = st.session_state["update_rcs"]
         | 
| 941 | 
            -
                else:
         | 
| 942 | 
            -
                    updated_rcs = None
         | 
| 943 | 
            -
             | 
| 944 | 
            -
                if "first_time" not in st.session_state:
         | 
| 945 | 
            -
                    st.session_state["first_time"] = True
         | 
| 946 | 
            -
             | 
| 947 | 
            -
                # Check if state is initiaized
         | 
| 948 | 
            -
                is_state_initiaized = st.session_state.get("initialized", False)
         | 
| 949 | 
            -
                if not is_state_initiaized or st.session_state["first_time"]:
         | 
| 950 | 
            -
                    # initialize_data()
         | 
| 951 | 
            -
                    if panel_selected == "Total Market":
         | 
| 952 | 
            -
                        initialize_data(
         | 
| 953 | 
            -
                            panel=panel_selected,
         | 
| 954 | 
            -
                            target_file=file_selected,
         | 
| 955 | 
            -
                            updated_rcs=updated_rcs,
         | 
| 956 | 
            -
                            metrics=metrics_selected,
         | 
| 957 | 
            -
                        )
         | 
| 958 | 
            -
                        panel = None
         | 
| 959 | 
            -
                    else:
         | 
| 960 | 
            -
                        initialize_data(
         | 
| 961 | 
            -
                            panel=panel_selected,
         | 
| 962 | 
            -
                            target_file=file_selected,
         | 
| 963 | 
            -
                            updated_rcs=updated_rcs,
         | 
| 964 | 
            -
                            metrics=metrics_selected,
         | 
| 965 | 
            -
                        )
         | 
| 966 | 
            -
                    st.session_state["initialized"] = True
         | 
| 967 | 
            -
                    st.session_state["first_time"] = False
         | 
| 968 | 
            -
             | 
| 969 | 
            -
                # initialize_data(
         | 
| 970 | 
            -
                #             panel=panel_selected,
         | 
| 971 | 
            -
                #             target_file=file_selected,
         | 
| 972 | 
            -
                #             updated_rcs=updated_rcs,
         | 
| 973 | 
            -
                #             metrics=metrics_selected,
         | 
| 974 | 
            -
                #         )
         | 
| 975 | 
            -
                # st.session_state["initialized"] = True
         | 
| 976 | 
            -
                # st.session_state["first_time"] = False
         | 
| 977 | 
            -
             | 
| 978 | 
            -
                # Channels List
         | 
| 979 | 
            -
                channels_list = st.session_state["channels_list"]
         | 
| 980 | 
            -
             | 
| 981 | 
            -
                # ======================================================== #
         | 
| 982 | 
            -
                # ========================== UI ========================== #
         | 
| 983 | 
            -
                # ======================================================== #
         | 
| 984 | 
            -
             | 
| 985 | 
            -
                # print(list(st.session_state.keys()))
         | 
| 986 | 
            -
                main_header = st.columns((2, 2))
         | 
| 987 | 
            -
                sub_header = st.columns((1, 1, 1, 1))
         | 
| 988 | 
            -
                _scenario = st.session_state["scenario"]
         | 
| 989 | 
            -
             | 
| 990 | 
            -
                if "total_spends_change" not in st.session_state:
         | 
| 991 | 
            -
                    st.session_state.total_spends_change = 0
         | 
| 992 | 
            -
             | 
| 993 | 
            -
                if "total_sales_change" not in st.session_state:
         | 
| 994 | 
            -
                    st.session_state.total_sales_change = 0
         | 
| 995 | 
            -
             | 
| 996 | 
            -
                if "total_spends_change_abs" not in st.session_state:
         | 
| 997 | 
            -
                    st.session_state["total_spends_change_abs"] = numerize(
         | 
| 998 | 
            -
                        _scenario.actual_total_spends, 1
         | 
| 999 | 
            -
                    )
         | 
| 1000 | 
            -
             | 
| 1001 | 
            -
                if "total_sales_change_abs" not in st.session_state:
         | 
| 1002 | 
            -
                    st.session_state["total_sales_change_abs"] = numerize(
         | 
| 1003 | 
            -
                        _scenario.actual_total_sales, 1
         | 
| 1004 | 
            -
                    )
         | 
| 1005 | 
            -
             | 
| 1006 | 
            -
                if "total_spends_change_abs_slider" not in st.session_state:
         | 
| 1007 | 
            -
                    st.session_state.total_spends_change_abs_slider = numerize(
         | 
| 1008 | 
            -
                        _scenario.actual_total_spends, 1
         | 
| 1009 | 
            -
                    )
         | 
| 1010 | 
            -
             | 
| 1011 | 
            -
                if "total_sales_change_abs_slider" not in st.session_state:
         | 
| 1012 | 
            -
                    st.session_state.total_sales_change_abs_slider = numerize(
         | 
| 1013 | 
            -
                        _scenario.actual_total_sales, 1
         | 
| 1014 | 
            -
                    )
         | 
| 1015 | 
            -
             | 
| 1016 | 
            -
                with main_header[0]:
         | 
| 1017 | 
            -
                    st.subheader("Actual")
         | 
| 1018 | 
            -
             | 
| 1019 | 
            -
                with main_header[-1]:
         | 
| 1020 | 
            -
                    st.subheader("Simulated")
         | 
| 1021 | 
            -
             | 
| 1022 | 
            -
                with sub_header[0]:
         | 
| 1023 | 
            -
                    st.metric(label="Spends", value=format_numbers(_scenario.actual_total_spends))
         | 
| 1024 | 
            -
             | 
| 1025 | 
            -
                with sub_header[1]:
         | 
| 1026 | 
            -
                    st.metric(
         | 
| 1027 | 
            -
                        label=target,
         | 
| 1028 | 
            -
                        value=format_numbers_f(
         | 
| 1029 | 
            -
                            float(_scenario.actual_total_sales)
         | 
| 1030 | 
            -
                        ),
         | 
| 1031 | 
            -
                    )
         | 
| 1032 | 
            -
             | 
| 1033 | 
            -
                with sub_header[2]:
         | 
| 1034 | 
            -
                    st.metric(
         | 
| 1035 | 
            -
                        label="Spends",
         | 
| 1036 | 
            -
                        value=format_numbers(_scenario.modified_total_spends),
         | 
| 1037 | 
            -
                        delta=numerize(_scenario.delta_spends, 1),
         | 
| 1038 | 
            -
                    )
         | 
| 1039 | 
            -
             | 
| 1040 | 
            -
                with sub_header[3]:
         | 
| 1041 | 
            -
                    st.metric(
         | 
| 1042 | 
            -
                        label=target,
         | 
| 1043 | 
            -
                        value=format_numbers_f(
         | 
| 1044 | 
            -
                            float(_scenario.modified_total_sales)
         | 
| 1045 | 
            -
                        ),
         | 
| 1046 | 
            -
                        delta=numerize(_scenario.delta_sales, 1),
         | 
| 1047 | 
            -
                    )
         | 
| 1048 | 
            -
             | 
| 1049 | 
            -
                with st.expander("Channel Spends Simulator", expanded=True):
         | 
| 1050 | 
            -
                    _columns1 = st.columns((2, 2, 1, 1))
         | 
| 1051 | 
            -
                    with _columns1[0]:
         | 
| 1052 | 
            -
                        optimization_selection = st.selectbox(
         | 
| 1053 | 
            -
                            "Optimize", options=["Media Spends", target], key="optimization_key"
         | 
| 1054 | 
            -
                        )
         | 
| 1055 | 
            -
             | 
| 1056 | 
            -
                    with _columns1[1]:
         | 
| 1057 | 
            -
                        st.markdown("#")
         | 
| 1058 | 
            -
                        # if st.checkbox(
         | 
| 1059 | 
            -
                        #     label="Optimize all Channels",
         | 
| 1060 | 
            -
                        #     key="optimze_all_channels",
         | 
| 1061 | 
            -
                        #     value=False,
         | 
| 1062 | 
            -
                        #     # on_change=select_all_channels_for_optimization,
         | 
| 1063 | 
            -
                        # ):
         | 
| 1064 | 
            -
                        #     select_all_channels_for_optimization()
         | 
| 1065 | 
            -
             | 
| 1066 | 
            -
                        st.checkbox(
         | 
| 1067 | 
            -
                            label="Optimize all Channels",
         | 
| 1068 | 
            -
                            key="optimze_all_channels",
         | 
| 1069 | 
            -
                            value=False,
         | 
| 1070 | 
            -
                            on_change=select_all_channels_for_optimization,
         | 
| 1071 | 
            -
                        )
         | 
| 1072 | 
            -
             | 
| 1073 | 
            -
                    with _columns1[2]:
         | 
| 1074 | 
            -
                        st.markdown("#")
         | 
| 1075 | 
            -
                        # st.button(
         | 
| 1076 | 
            -
                        #     "Optimize",
         | 
| 1077 | 
            -
                        #     on_click=optimize,
         | 
| 1078 | 
            -
                        #     args=(st.session_state["optimization_key"]),
         | 
| 1079 | 
            -
                        #     use_container_width=True,
         | 
| 1080 | 
            -
                        # )
         | 
| 1081 | 
            -
             | 
| 1082 | 
            -
                        optimize_placeholder = st.empty()
         | 
| 1083 | 
            -
             | 
| 1084 | 
            -
                    with _columns1[3]:
         | 
| 1085 | 
            -
                        st.markdown("#")
         | 
| 1086 | 
            -
                        st.button(
         | 
| 1087 | 
            -
                            "Reset",
         | 
| 1088 | 
            -
                            on_click=reset_scenario,
         | 
| 1089 | 
            -
                            args=(panel_selected, file_selected, updated_rcs),
         | 
| 1090 | 
            -
                            # use_container_width=True,
         | 
| 1091 | 
            -
                        )
         | 
| 1092 | 
            -
                        # st.write(target)
         | 
| 1093 | 
            -
             | 
| 1094 | 
            -
             | 
| 1095 | 
            -
                    _columns2 = st.columns((2, 2, 2))
         | 
| 1096 | 
            -
                    if st.session_state["optimization_key"] == "Media Spends":
         | 
| 1097 | 
            -
                        with _columns2[0]:
         | 
| 1098 | 
            -
                            spend_input = st.text_input(
         | 
| 1099 | 
            -
                                "Absolute",
         | 
| 1100 | 
            -
                                key="total_spends_change_abs",
         | 
| 1101 | 
            -
                                # label_visibility="collapsed",
         | 
| 1102 | 
            -
                                on_change=update_all_spends_abs,
         | 
| 1103 | 
            -
                            )
         | 
| 1104 | 
            -
             | 
| 1105 | 
            -
                        with _columns2[1]:
         | 
| 1106 | 
            -
                            st.number_input(
         | 
| 1107 | 
            -
                                "Percent Change",
         | 
| 1108 | 
            -
                                key="total_spends_change",
         | 
| 1109 | 
            -
                                min_value=-50,
         | 
| 1110 | 
            -
                                max_value=50,
         | 
| 1111 | 
            -
                                step=1,
         | 
| 1112 | 
            -
                                on_change=update_spends,
         | 
| 1113 | 
            -
                            )
         | 
| 1114 | 
            -
             | 
| 1115 | 
            -
                        with _columns2[2]:
         | 
| 1116 | 
            -
                            min_value = round(_scenario.actual_total_spends * 0.5)
         | 
| 1117 | 
            -
                            max_value = round(_scenario.actual_total_spends * 1.5)
         | 
| 1118 | 
            -
                            st.session_state["total_spends_change_abs_slider_options"] = [
         | 
| 1119 | 
            -
                                numerize(value, 1)
         | 
| 1120 | 
            -
                                for value in range(min_value, max_value + 1, int(1e4))
         | 
| 1121 | 
            -
                            ]
         | 
| 1122 | 
            -
             | 
| 1123 | 
            -
                            # st.select_slider(
         | 
| 1124 | 
            -
                            #     "Absolute Slider",
         | 
| 1125 | 
            -
                            #     options=st.session_state["total_spends_change_abs_slider_options"],
         | 
| 1126 | 
            -
                            #     key="total_spends_change_abs_slider",
         | 
| 1127 | 
            -
                            #     on_change=update_all_spends_abs_slider,
         | 
| 1128 | 
            -
                            # )
         | 
| 1129 | 
            -
                    
         | 
| 1130 | 
            -
                    elif st.session_state["optimization_key"] == target:
         | 
| 1131 | 
            -
                        # st.write(target)
         | 
| 1132 | 
            -
                        with _columns2[0]:
         | 
| 1133 | 
            -
                            sales_input = st.text_input(
         | 
| 1134 | 
            -
                                "Absolute",
         | 
| 1135 | 
            -
                                key="total_sales_change_abs",
         | 
| 1136 | 
            -
                                on_change=update_sales_abs,
         | 
| 1137 | 
            -
                            )
         | 
| 1138 | 
            -
             | 
| 1139 | 
            -
                        with _columns2[1]:
         | 
| 1140 | 
            -
                            st.number_input(
         | 
| 1141 | 
            -
                                "Percent Change",
         | 
| 1142 | 
            -
                                key="total_sales_change",
         | 
| 1143 | 
            -
                                min_value=-50,
         | 
| 1144 | 
            -
                                max_value=50,
         | 
| 1145 | 
            -
                                step=1,
         | 
| 1146 | 
            -
                                on_change=update_sales,
         | 
| 1147 | 
            -
                            )
         | 
| 1148 | 
            -
                        with _columns2[2]:
         | 
| 1149 | 
            -
                            min_value = round(_scenario.actual_total_sales * 0.5)
         | 
| 1150 | 
            -
                            max_value = round(_scenario.actual_total_sales * 1.5)
         | 
| 1151 | 
            -
                            st.write(min_value)
         | 
| 1152 | 
            -
                            st.write(max_value)
         | 
| 1153 | 
            -
                            # for value in range(min_value, max_value + 1, int(100)):
         | 
| 1154 | 
            -
                            #     st.write(numerize(value, 1))
         | 
| 1155 | 
            -
                            st.session_state["total_sales_change_abs_slider_options"] = [
         | 
| 1156 | 
            -
                                numerize(value, 1)
         | 
| 1157 | 
            -
                                for value in range(min_value, max_value + 1, int(100))
         | 
| 1158 | 
            -
                            ]
         | 
| 1159 | 
            -
             | 
| 1160 | 
            -
                            st.select_slider(
         | 
| 1161 | 
            -
                                "Absolute Slider",
         | 
| 1162 | 
            -
                                options=st.session_state["total_sales_change_abs_slider_options"],
         | 
| 1163 | 
            -
                                key="total_sales_change_abs_slider",
         | 
| 1164 | 
            -
                                on_change=update_sales_abs_slider,
         | 
| 1165 | 
            -
                                # value=numerize(min_value, 1)
         | 
| 1166 | 
            -
                            )
         | 
| 1167 | 
            -
             | 
| 1168 | 
            -
                    if (
         | 
| 1169 | 
            -
                        not st.session_state["allow_sales_update"]
         | 
| 1170 | 
            -
                        and optimization_selection == target
         | 
| 1171 | 
            -
                    ):
         | 
| 1172 | 
            -
                        st.warning("Invalid Input")
         | 
| 1173 | 
            -
             | 
| 1174 | 
            -
                    if (
         | 
| 1175 | 
            -
                        not st.session_state["allow_spends_update"]
         | 
| 1176 | 
            -
                        and optimization_selection == "Media Spends"
         | 
| 1177 | 
            -
                    ):
         | 
| 1178 | 
            -
                        st.warning("Invalid Input")
         | 
| 1179 | 
            -
             | 
| 1180 | 
            -
                    status_placeholder = st.empty()
         | 
| 1181 | 
            -
             | 
| 1182 | 
            -
                    # if optimize_placeholder.button("Optimize", use_container_width=True):
         | 
| 1183 | 
            -
                    #     optimize(st.session_state["optimization_key"], status_placeholder)
         | 
| 1184 | 
            -
                    #     st.rerun()
         | 
| 1185 | 
            -
             | 
| 1186 | 
            -
                    optimize_placeholder.button(
         | 
| 1187 | 
            -
                        "Optimize",
         | 
| 1188 | 
            -
                        on_click=optimize,
         | 
| 1189 | 
            -
                        args=(st.session_state["optimization_key"], status_placeholder),
         | 
| 1190 | 
            -
                        # use_container_width=True,
         | 
| 1191 | 
            -
                    )
         | 
| 1192 | 
            -
             | 
| 1193 | 
            -
                    st.markdown("""<hr class="spends-heading-seperator">""", unsafe_allow_html=True)
         | 
| 1194 | 
            -
                    _columns = st.columns((2.5, 2, 1.5, 1.5, 1))
         | 
| 1195 | 
            -
                    with _columns[0]:
         | 
| 1196 | 
            -
                        generate_spending_header("Channel")
         | 
| 1197 | 
            -
                    with _columns[1]:
         | 
| 1198 | 
            -
                        generate_spending_header("Spends Input")
         | 
| 1199 | 
            -
                    with _columns[2]:
         | 
| 1200 | 
            -
                        generate_spending_header("Spends")
         | 
| 1201 | 
            -
                    with _columns[3]:
         | 
| 1202 | 
            -
                        generate_spending_header(target)
         | 
| 1203 | 
            -
                    with _columns[4]:
         | 
| 1204 | 
            -
                        generate_spending_header("Optimize")
         | 
| 1205 | 
            -
             | 
| 1206 | 
            -
                    st.markdown("""<hr class="spends-heading-seperator">""", unsafe_allow_html=True)
         | 
| 1207 | 
            -
             | 
| 1208 | 
            -
                    if "acutual_predicted" not in st.session_state:
         | 
| 1209 | 
            -
                        st.session_state["acutual_predicted"] = {
         | 
| 1210 | 
            -
                            "Channel_name": [],
         | 
| 1211 | 
            -
                            "Actual_spend": [],
         | 
| 1212 | 
            -
                            "Optimized_spend": [],
         | 
| 1213 | 
            -
                            "Delta": [],
         | 
| 1214 | 
            -
                            "New_sales":[],
         | 
| 1215 | 
            -
                            "Old_sales":[]
         | 
| 1216 | 
            -
                        }
         | 
| 1217 | 
            -
                    for i, channel_name in enumerate(channels_list):
         | 
| 1218 | 
            -
                        # st.write(channel_name)
         | 
| 1219 | 
            -
                        _channel_class = st.session_state["scenario"].channels[channel_name]
         | 
| 1220 | 
            -
                        _columns = st.columns((2.5, 1.5, 1.5, 1.5, 1))
         | 
| 1221 | 
            -
                        with _columns[0]:
         | 
| 1222 | 
            -
                            st.write(channel_name_formating(channel_name))
         | 
| 1223 | 
            -
                            bin_placeholder = st.container()
         | 
| 1224 | 
            -
             | 
| 1225 | 
            -
                        with _columns[1]:
         | 
| 1226 | 
            -
                            channel_bounds = _channel_class.bounds
         | 
| 1227 | 
            -
                            channel_spends = float(_channel_class.actual_total_spends)
         | 
| 1228 | 
            -
                            min_value = float((1 + channel_bounds[0] / 100) * channel_spends)
         | 
| 1229 | 
            -
                            max_value = float((1 + channel_bounds[1] / 100) * channel_spends)
         | 
| 1230 | 
            -
                            ##print(st.session_state[channel_name])
         | 
| 1231 | 
            -
                            spend_input = st.text_input(
         | 
| 1232 | 
            -
                                channel_name,
         | 
| 1233 | 
            -
                                key=channel_name,
         | 
| 1234 | 
            -
                                label_visibility="collapsed",
         | 
| 1235 | 
            -
                                on_change=partial(update_data, channel_name),
         | 
| 1236 | 
            -
                            )
         | 
| 1237 | 
            -
                            if not validate_input(spend_input):
         | 
| 1238 | 
            -
                                st.error("Invalid input")
         | 
| 1239 | 
            -
             | 
| 1240 | 
            -
                            channel_name_current = f"{channel_name}_change"
         | 
| 1241 | 
            -
             | 
| 1242 | 
            -
                            st.number_input(
         | 
| 1243 | 
            -
                                "Percent Change",
         | 
| 1244 | 
            -
                                key=channel_name_current,
         | 
| 1245 | 
            -
                                step=1,
         | 
| 1246 | 
            -
                                on_change=partial(update_data_by_percent, channel_name),
         | 
| 1247 | 
            -
                            )
         | 
| 1248 | 
            -
             | 
| 1249 | 
            -
                        with _columns[2]:
         | 
| 1250 | 
            -
                            # spends
         | 
| 1251 | 
            -
                            current_channel_spends = float(
         | 
| 1252 | 
            -
                                _channel_class.modified_total_spends
         | 
| 1253 | 
            -
                                * _channel_class.conversion_rate
         | 
| 1254 | 
            -
                            )
         | 
| 1255 | 
            -
                            actual_channel_spends = float(
         | 
| 1256 | 
            -
                                _channel_class.actual_total_spends * _channel_class.conversion_rate
         | 
| 1257 | 
            -
                            )
         | 
| 1258 | 
            -
                            spends_delta = float(
         | 
| 1259 | 
            -
                                _channel_class.delta_spends * _channel_class.conversion_rate
         | 
| 1260 | 
            -
                            )
         | 
| 1261 | 
            -
                            st.session_state["acutual_predicted"]["Channel_name"].append(
         | 
| 1262 | 
            -
                                channel_name
         | 
| 1263 | 
            -
                            )
         | 
| 1264 | 
            -
                            st.session_state["acutual_predicted"]["Actual_spend"].append(
         | 
| 1265 | 
            -
                                actual_channel_spends
         | 
| 1266 | 
            -
                            )
         | 
| 1267 | 
            -
                            st.session_state["acutual_predicted"]["Optimized_spend"].append(
         | 
| 1268 | 
            -
                                current_channel_spends
         | 
| 1269 | 
            -
                            )
         | 
| 1270 | 
            -
                            st.session_state["acutual_predicted"]["Delta"].append(spends_delta)
         | 
| 1271 | 
            -
                            ## REMOVE
         | 
| 1272 | 
            -
                            st.metric(
         | 
| 1273 | 
            -
                                "Spends",
         | 
| 1274 | 
            -
                                format_numbers(current_channel_spends),
         | 
| 1275 | 
            -
                                delta=numerize(spends_delta, 1),
         | 
| 1276 | 
            -
                                label_visibility="collapsed",
         | 
| 1277 | 
            -
                            )
         | 
| 1278 | 
            -
             | 
| 1279 | 
            -
                        with _columns[3]:
         | 
| 1280 | 
            -
                            # sales
         | 
| 1281 | 
            -
                            current_channel_sales = float(_channel_class.modified_total_sales)
         | 
| 1282 | 
            -
                            actual_channel_sales = float(_channel_class.actual_total_sales)
         | 
| 1283 | 
            -
                            sales_delta = float(_channel_class.delta_sales)
         | 
| 1284 | 
            -
                            st.session_state["acutual_predicted"]["Old_sales"].append(actual_channel_sales)
         | 
| 1285 | 
            -
                            st.session_state["acutual_predicted"]["New_sales"].append(current_channel_sales)
         | 
| 1286 | 
            -
                            #st.write(actual_channel_sales)
         | 
| 1287 | 
            -
             | 
| 1288 | 
            -
                            st.metric(
         | 
| 1289 | 
            -
                                target,
         | 
| 1290 | 
            -
                                format_numbers_f(current_channel_sales),
         | 
| 1291 | 
            -
                                delta=numerize(sales_delta, 1),
         | 
| 1292 | 
            -
                                label_visibility="collapsed",
         | 
| 1293 | 
            -
                            )
         | 
| 1294 | 
            -
             | 
| 1295 | 
            -
                        with _columns[4]:
         | 
| 1296 | 
            -
             | 
| 1297 | 
            -
                            # if st.checkbox(
         | 
| 1298 | 
            -
                            #     label="select for optimization",
         | 
| 1299 | 
            -
                            #     key=f"{channel_name}_selected",
         | 
| 1300 | 
            -
                            #     value=False,
         | 
| 1301 | 
            -
                            #     # on_change=partial(select_channel_for_optimization, channel_name),
         | 
| 1302 | 
            -
                            #     label_visibility="collapsed",
         | 
| 1303 | 
            -
                            # ):
         | 
| 1304 | 
            -
                            #     select_channel_for_optimization(channel_name)
         | 
| 1305 | 
            -
             | 
| 1306 | 
            -
                            st.checkbox(
         | 
| 1307 | 
            -
                                label="select for optimization",
         | 
| 1308 | 
            -
                                key=f"{channel_name}_selected",
         | 
| 1309 | 
            -
                                value=False,
         | 
| 1310 | 
            -
                                on_change=partial(select_channel_for_optimization, channel_name),
         | 
| 1311 | 
            -
                                label_visibility="collapsed",
         | 
| 1312 | 
            -
                            )
         | 
| 1313 | 
            -
             | 
| 1314 | 
            -
                        st.markdown(
         | 
| 1315 | 
            -
                            """<hr class="spends-child-seperator">""",
         | 
| 1316 | 
            -
                            unsafe_allow_html=True,
         | 
| 1317 | 
            -
                        )
         | 
| 1318 | 
            -
             | 
| 1319 | 
            -
                        # Bins
         | 
| 1320 | 
            -
                        col = channels_list[i]
         | 
| 1321 | 
            -
                        x_actual = st.session_state["scenario"].channels[col].actual_spends
         | 
| 1322 | 
            -
                        x_modified = st.session_state["scenario"].channels[col].modified_spends
         | 
| 1323 | 
            -
                        # x_modified_total = 0 
         | 
| 1324 | 
            -
                        # for c in channels_list:
         | 
| 1325 | 
            -
                        #     # st.write(c)
         | 
| 1326 | 
            -
                        #     # st.write(st.session_state["scenario"].channels[c].modified_spends)
         | 
| 1327 | 
            -
                        #     x_modified_total = x_modified_total + st.session_state["scenario"].channels[c].modified_spends.sum()
         | 
| 1328 | 
            -
                        # st.write(x_modified_total)
         | 
| 1329 | 
            -
                        
         | 
| 1330 | 
            -
                        x_total = x_modified.sum()
         | 
| 1331 | 
            -
                        power = np.ceil(np.log(x_actual.max()) / np.log(10)) - 3
         | 
| 1332 | 
            -
             | 
| 1333 | 
            -
                        updated_rcs_key = f"{metrics_selected}#@{panel_selected}#@{channel_name}"
         | 
| 1334 | 
            -
             | 
| 1335 | 
            -
                        if updated_rcs and updated_rcs_key in list(updated_rcs.keys()):
         | 
| 1336 | 
            -
                            K = updated_rcs[updated_rcs_key]["K"]
         | 
| 1337 | 
            -
                            b = updated_rcs[updated_rcs_key]["b"]
         | 
| 1338 | 
            -
                            a = updated_rcs[updated_rcs_key]["a"]
         | 
| 1339 | 
            -
                            x0 = updated_rcs[updated_rcs_key]["x0"]
         | 
| 1340 | 
            -
                        else:
         | 
| 1341 | 
            -
                            K = st.session_state["rcs"][col]["K"]
         | 
| 1342 | 
            -
                            b = st.session_state["rcs"][col]["b"]
         | 
| 1343 | 
            -
                            a = st.session_state["rcs"][col]["a"]
         | 
| 1344 | 
            -
                            x0 = st.session_state["rcs"][col]["x0"]
         | 
| 1345 | 
            -
             | 
| 1346 | 
            -
                        x_plot = np.linspace(0, 5 * x_actual.sum(), 200)
         | 
| 1347 | 
            -
             | 
| 1348 | 
            -
                        # Append current_channel_spends to the end of x_plot
         | 
| 1349 | 
            -
                        x_plot = np.append(x_plot, current_channel_spends)
         | 
| 1350 | 
            -
             | 
| 1351 | 
            -
                        x, y, marginal_roi = [], [], []
         | 
| 1352 | 
            -
                        for x_p in x_plot:
         | 
| 1353 | 
            -
                            x.append(x_p * x_actual / x_actual.sum())
         | 
| 1354 | 
            -
             | 
| 1355 | 
            -
                        for index in range(len(x_plot)):
         | 
| 1356 | 
            -
                            y.append(s_curve(x[index] / 10**power, K, b, a, x0))
         | 
| 1357 | 
            -
             | 
| 1358 | 
            -
                        for index in range(len(x_plot)):
         | 
| 1359 | 
            -
                            marginal_roi.append(
         | 
| 1360 | 
            -
                                a * y[index] * (1 - y[index] / np.maximum(K, np.finfo(float).eps))
         | 
| 1361 | 
            -
                            )
         | 
| 1362 | 
            -
             | 
| 1363 | 
            -
                        x = (
         | 
| 1364 | 
            -
                            np.sum(x, axis=1)
         | 
| 1365 | 
            -
                            * st.session_state["scenario"].channels[col].conversion_rate
         | 
| 1366 | 
            -
                        )
         | 
| 1367 | 
            -
                        y = np.sum(y, axis=1)
         | 
| 1368 | 
            -
                        marginal_roi = (
         | 
| 1369 | 
            -
                            np.average(marginal_roi, axis=1)
         | 
| 1370 | 
            -
                            / st.session_state["scenario"].channels[col].conversion_rate
         | 
| 1371 | 
            -
                        )
         | 
| 1372 | 
            -
             | 
| 1373 | 
            -
                        roi = y / np.maximum(x, np.finfo(float).eps)
         | 
| 1374 | 
            -
                        # roi = (y/np.sum(y))/(x/np.sum(x))
         | 
| 1375 | 
            -
                        # st.write(x)
         | 
| 1376 | 
            -
                        # st.write(y)
         | 
| 1377 | 
            -
                        # st.write(roi)
         | 
| 1378 | 
            -
             | 
| 1379 | 
            -
                        # st.write(roi[-1])
         | 
| 1380 | 
            -
                        
         | 
| 1381 | 
            -
                        roi_current, marginal_roi_current = roi[-1], marginal_roi[-1]
         | 
| 1382 | 
            -
                        x, y, roi, marginal_roi = (
         | 
| 1383 | 
            -
                            x[:-1],
         | 
| 1384 | 
            -
                            y[:-1],
         | 
| 1385 | 
            -
                            roi[:-1],
         | 
| 1386 | 
            -
                            marginal_roi[:-1],
         | 
| 1387 | 
            -
                        )  # Drop data for current spends
         | 
| 1388 | 
            -
             | 
| 1389 | 
            -
                        # roi_current = 
         | 
| 1390 | 
            -
             | 
| 1391 | 
            -
                        start_value, end_value, left_value, right_value = find_segment_value(
         | 
| 1392 | 
            -
                            x,
         | 
| 1393 | 
            -
                            roi,
         | 
| 1394 | 
            -
                            marginal_roi,
         | 
| 1395 | 
            -
                        )
         | 
| 1396 | 
            -
             | 
| 1397 | 
            -
                        #st.write(roi_current)
         | 
| 1398 | 
            -
             | 
| 1399 | 
            -
                        rgba = calculate_rgba(
         | 
| 1400 | 
            -
                            start_value,
         | 
| 1401 | 
            -
                            end_value,
         | 
| 1402 | 
            -
                            left_value,
         | 
| 1403 | 
            -
                            right_value,
         | 
| 1404 | 
            -
                            current_channel_spends,
         | 
| 1405 | 
            -
                        )
         | 
| 1406 | 
            -
             | 
| 1407 | 
            -
                        summary_df = pd.DataFrame(st.session_state["acutual_predicted"])
         | 
| 1408 | 
            -
                        # st.dataframe(summary_df)
         | 
| 1409 | 
            -
                        summary_df.drop_duplicates(subset="Channel_name", keep="last", inplace=True)
         | 
| 1410 | 
            -
                        # st.dataframe(summary_df)
         | 
| 1411 | 
            -
             | 
| 1412 | 
            -
                        summary_df_sorted = summary_df.sort_values(by="Delta", ascending=False)
         | 
| 1413 | 
            -
                        summary_df_sorted["Delta_percent"] = np.round(
         | 
| 1414 | 
            -
                            ((summary_df_sorted["Optimized_spend"] / summary_df_sorted["Actual_spend"]) - 1)
         | 
| 1415 | 
            -
                            * 100,
         | 
| 1416 | 
            -
                            2,
         | 
| 1417 | 
            -
                        )
         | 
| 1418 | 
            -
             | 
| 1419 | 
            -
                        summary_df_sorted=summary_df_sorted.sort_values(by=['Optimized_spend'],ascending=False)
         | 
| 1420 | 
            -
                        summary_df_sorted['old_efficiency']=(summary_df_sorted['Old_sales']/summary_df_sorted['Old_sales'].sum())/(summary_df_sorted['Actual_spend']/summary_df_sorted['Actual_spend'].sum())
         | 
| 1421 | 
            -
                        summary_df_sorted['new_efficiency']=(summary_df_sorted['New_sales']/summary_df_sorted['New_sales'].sum())/(summary_df_sorted['Optimized_spend']/summary_df_sorted['Optimized_spend'].sum())
         | 
| 1422 | 
            -
                        
         | 
| 1423 | 
            -
                        a = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['new_efficiency'][0]
         | 
| 1424 | 
            -
                        # st.write(a)
         | 
| 1425 | 
            -
             | 
| 1426 | 
            -
                        with bin_placeholder:
         | 
| 1427 | 
            -
                            st.markdown(
         | 
| 1428 | 
            -
                                f"""
         | 
| 1429 | 
            -
                                <div style="
         | 
| 1430 | 
            -
                                    border-radius: 12px;
         | 
| 1431 | 
            -
                                    background-color: {rgba};
         | 
| 1432 | 
            -
                                    padding: 10px;
         | 
| 1433 | 
            -
                                    text-align: center;
         | 
| 1434 | 
            -
                                    color: #006EC0;
         | 
| 1435 | 
            -
                                    ">
         | 
| 1436 | 
            -
                                    <p style="margin: 0; font-size: 20px;">Efficiency: {round(a,2)}</p>
         | 
| 1437 | 
            -
                                    <!--<p style="margin: 0; font-size: 20px;">Marginal ROI: {round(marginal_roi_current,1)}</p>-->
         | 
| 1438 | 
            -
                                </div>
         | 
| 1439 | 
            -
                                """,
         | 
| 1440 | 
            -
                                unsafe_allow_html=True,
         | 
| 1441 | 
            -
                            )
         | 
| 1442 | 
            -
             | 
| 1443 | 
            -
                # with st.expander("See Response Curves", expanded=True):
         | 
| 1444 | 
            -
                #     fig = plot_response_curves(summary_df_sorted)
         | 
| 1445 | 
            -
                #     # st.plotly_chart(rc.response_curves(col))
         | 
| 1446 | 
            -
                #     # st.plotly_chart(fig, use_container_width=True)
         | 
| 1447 | 
            -
             | 
| 1448 | 
            -
                summary_df = pd.DataFrame(st.session_state["acutual_predicted"])
         | 
| 1449 | 
            -
                # st.dataframe(summary_df)
         | 
| 1450 | 
            -
                summary_df.drop_duplicates(subset="Channel_name", keep="last", inplace=True)
         | 
| 1451 | 
            -
                # st.dataframe(summary_df)
         | 
| 1452 | 
            -
             | 
| 1453 | 
            -
                summary_df_sorted = summary_df.sort_values(by="Delta", ascending=False)
         | 
| 1454 | 
            -
                summary_df_sorted["Delta_percent"] = np.round(
         | 
| 1455 | 
            -
                    ((summary_df_sorted["Optimized_spend"] / summary_df_sorted["Actual_spend"]) - 1)
         | 
| 1456 | 
            -
                    * 100,
         | 
| 1457 | 
            -
                    2,
         | 
| 1458 | 
            -
                )
         | 
| 1459 | 
            -
             | 
| 1460 | 
            -
                
         | 
| 1461 | 
            -
             | 
| 1462 | 
            -
                
         | 
| 1463 | 
            -
             | 
| 1464 | 
            -
                with open("summary_df.pkl", "wb") as f:
         | 
| 1465 | 
            -
                    pickle.dump(summary_df_sorted, f)
         | 
| 1466 | 
            -
                    # st.dataframe(summary_df_sorted)
         | 
| 1467 | 
            -
                    # ___columns=st.columns(3)
         | 
| 1468 | 
            -
                    # with ___columns[2]:
         | 
| 1469 | 
            -
                    #     fig=summary_plot(summary_df_sorted, x='Delta_percent', y='Channel_name', title='Delta', text_column='Delta_percent')
         | 
| 1470 | 
            -
                    #     st.plotly_chart(fig,use_container_width=True)
         | 
| 1471 | 
            -
                    # with ___columns[0]:
         | 
| 1472 | 
            -
                    #     fig=summary_plot(summary_df_sorted, x='Actual_spend', y='Channel_name', title='Actual Spend', text_column='Actual_spend')
         | 
| 1473 | 
            -
                    #     st.plotly_chart(fig,use_container_width=True)
         | 
| 1474 | 
            -
                    # with ___columns[1]:
         | 
| 1475 | 
            -
                    #     fig=summary_plot(summary_df_sorted, x='Optimized_spend', y='Channel_name', title='Planned Spend', text_column='Optimized_spend')
         | 
| 1476 | 
            -
                    #     st.plotly_chart(fig,use_container_width=True)
         | 
| 1477 | 
            -
             | 
| 1478 | 
            -
                scenario_planner_plots()
         | 
| 1479 | 
            -
             | 
| 1480 | 
            -
                _columns = st.columns(2)
         | 
| 1481 | 
            -
                # with _columns[0]:
         | 
| 1482 | 
            -
                st.subheader("Save Scenario")
         | 
| 1483 | 
            -
                scenario_name = st.text_input(
         | 
| 1484 | 
            -
                    "Scenario name",
         | 
| 1485 | 
            -
                    key="scenario_input",
         | 
| 1486 | 
            -
                    placeholder="Scenario name",
         | 
| 1487 | 
            -
                    label_visibility="collapsed",
         | 
| 1488 | 
            -
                )
         | 
| 1489 | 
            -
                st.button(
         | 
| 1490 | 
            -
                    "Save",
         | 
| 1491 | 
            -
                    on_click=lambda: save_scenario(scenario_name),
         | 
| 1492 | 
            -
                    disabled=len(st.session_state["scenario_input"]) == 0,#use_container_width=True
         | 
| 1493 | 
            -
                )
         | 
| 1494 | 
            -
             | 
| 1495 | 
            -
             | 
| 1496 | 
            -
             | 
| 1497 | 
            -
            elif auth_status == False:
         | 
| 1498 | 
            -
                st.error("Username/Password is incorrect")
         | 
| 1499 | 
            -
             | 
| 1500 | 
            -
            if auth_status != True:
         | 
| 1501 | 
            -
                try:
         | 
| 1502 | 
            -
                    username_forgot_pw, email_forgot_password, random_password = (
         | 
| 1503 | 
            -
                        authenticator.forgot_password("Forgot password")
         | 
| 1504 | 
            -
                    )
         | 
| 1505 | 
            -
                    if username_forgot_pw:
         | 
| 1506 | 
            -
                        st.session_state["config"]["credentials"]["usernames"][username_forgot_pw][
         | 
| 1507 | 
            -
                            "password"
         | 
| 1508 | 
            -
                        ] = stauth.Hasher([random_password]).generate()[0]
         | 
| 1509 | 
            -
                        send_email(email_forgot_password, random_password)
         | 
| 1510 | 
            -
                        st.success("New password sent securely")
         | 
| 1511 | 
            -
                        # Random password to be transferred to user securely
         | 
| 1512 | 
            -
                    elif username_forgot_pw == False:
         | 
| 1513 | 
            -
                        st.error("Username not found")
         | 
| 1514 | 
            -
                except Exception as e:
         | 
| 1515 | 
            -
                    st.error(e)
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        pages/9_Saved_Scenarios.py
    DELETED
    
    | @@ -1,280 +0,0 @@ | |
| 1 | 
            -
            import streamlit as st
         | 
| 2 | 
            -
            from numerize.numerize import numerize
         | 
| 3 | 
            -
            import io
         | 
| 4 | 
            -
            import pandas as pd
         | 
| 5 | 
            -
            from utilities import (format_numbers,decimal_formater,
         | 
| 6 | 
            -
                                   channel_name_formating,
         | 
| 7 | 
            -
                                   load_local_css,set_header,
         | 
| 8 | 
            -
                                   initialize_data,
         | 
| 9 | 
            -
                                   load_authenticator)
         | 
| 10 | 
            -
            from openpyxl import Workbook
         | 
| 11 | 
            -
            from openpyxl.styles import Alignment,Font,PatternFill
         | 
| 12 | 
            -
            import pickle
         | 
| 13 | 
            -
            import streamlit_authenticator as stauth
         | 
| 14 | 
            -
            import yaml
         | 
| 15 | 
            -
            from yaml import SafeLoader
         | 
| 16 | 
            -
            from classes import class_from_dict
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            st.set_page_config(layout='wide')
         | 
| 19 | 
            -
            load_local_css('styles.css')
         | 
| 20 | 
            -
            set_header()
         | 
| 21 | 
            -
             | 
| 22 | 
            -
            # for k, v in st.session_state.items():
         | 
| 23 | 
            -
            #     if k not in ['logout', 'login','config'] and not k.startswith('FormSubmitter'):
         | 
| 24 | 
            -
            #         st.session_state[k] = v
         | 
| 25 | 
            -
             | 
| 26 | 
            -
            def create_scenario_summary(scenario_dict):
         | 
| 27 | 
            -
                summary_rows = []
         | 
| 28 | 
            -
                for channel_dict in scenario_dict['channels']:
         | 
| 29 | 
            -
                    name_mod = channel_name_formating(channel_dict['name'])
         | 
| 30 | 
            -
                    summary_rows.append([name_mod,
         | 
| 31 | 
            -
                                         channel_dict.get('actual_total_spends') * channel_dict.get('conversion_rate'),
         | 
| 32 | 
            -
                                         channel_dict.get('modified_total_spends') * channel_dict.get('conversion_rate'),
         | 
| 33 | 
            -
                                         channel_dict.get('actual_total_sales') ,
         | 
| 34 | 
            -
                                         channel_dict.get('modified_total_sales'),
         | 
| 35 | 
            -
                                        #  channel_dict.get('actual_total_sales') / (channel_dict.get('actual_total_spends') * channel_dict.get('conversion_rate')), 
         | 
| 36 | 
            -
                                        #  channel_dict.get('modified_total_sales') / (channel_dict.get('modified_total_spends') * channel_dict.get('conversion_rate')),
         | 
| 37 | 
            -
                                        #  channel_dict.get('actual_mroi'), 
         | 
| 38 | 
            -
                                        #  channel_dict.get('modified_mroi'),
         | 
| 39 | 
            -
                                        #  channel_dict.get('actual_total_spends') * channel_dict.get('conversion_rate') / channel_dict.get('actual_total_sales'),
         | 
| 40 | 
            -
                                        #  channel_dict.get('modified_total_spends') * channel_dict.get('conversion_rate') / channel_dict.get('modified_total_sales')
         | 
| 41 | 
            -
                                        ])
         | 
| 42 | 
            -
                    
         | 
| 43 | 
            -
                summary_rows.append(['Total',
         | 
| 44 | 
            -
                                     scenario_dict.get('actual_total_spends'), 
         | 
| 45 | 
            -
                                     scenario_dict.get('modified_total_spends'),
         | 
| 46 | 
            -
                                     scenario_dict.get('actual_total_sales'), 
         | 
| 47 | 
            -
                                     scenario_dict.get('modified_total_sales'),
         | 
| 48 | 
            -
                                    #  scenario_dict.get('actual_total_sales') / scenario_dict.get('actual_total_spends'),
         | 
| 49 | 
            -
                                    #  scenario_dict.get('modified_total_sales') / scenario_dict.get('modified_total_spends'),
         | 
| 50 | 
            -
                                    #  '-',
         | 
| 51 | 
            -
                                    #  '-',
         | 
| 52 | 
            -
                                    #  scenario_dict.get('actual_total_spends') / scenario_dict.get('actual_total_sales'),
         | 
| 53 | 
            -
                                    #  scenario_dict.get('modified_total_spends') / scenario_dict.get('modified_total_sales')
         | 
| 54 | 
            -
                                    ])
         | 
| 55 | 
            -
                
         | 
| 56 | 
            -
                columns_index = pd.MultiIndex.from_product([[''],['Channel']], names=["first", "second"])
         | 
| 57 | 
            -
                columns_index = columns_index.append(pd.MultiIndex.from_product([['Spends','Prospects'
         | 
| 58 | 
            -
                                                                                  #,'ROI','MROI','Spend per NRPU'
         | 
| 59 | 
            -
                                                                                  ],['Actual','Simulated']], names=["first", "second"]))
         | 
| 60 | 
            -
                return  pd.DataFrame(summary_rows, columns=columns_index)
         | 
| 61 | 
            -
                
         | 
| 62 | 
            -
             | 
| 63 | 
            -
               
         | 
| 64 | 
            -
            def summary_df_to_worksheet(df, ws):
         | 
| 65 | 
            -
                heading_fill = PatternFill(fill_type='solid',start_color='FF11B6BD',end_color='FF11B6BD')
         | 
| 66 | 
            -
                for j,header in enumerate(df.columns.values):
         | 
| 67 | 
            -
                    col = j + 1
         | 
| 68 | 
            -
                    for i in range(1,3):
         | 
| 69 | 
            -
                        ws.cell(row=i, column=j + 1, value=header[i - 1]).font = Font(bold=True, color='FF11B6BD')
         | 
| 70 | 
            -
                        ws.cell(row=i,column=j+1).fill = heading_fill
         | 
| 71 | 
            -
                    if  col > 1 and (col - 6)%5==0:    
         | 
| 72 | 
            -
                        ws.merge_cells(start_row=1, end_row=1, start_column = col-3, end_column=col)
         | 
| 73 | 
            -
                        ws.cell(row=1,column=col).alignment = Alignment(horizontal='center')
         | 
| 74 | 
            -
                for i,row in enumerate(df.itertuples()):
         | 
| 75 | 
            -
                    for j,value in enumerate(row):
         | 
| 76 | 
            -
                        if j == 0:
         | 
| 77 | 
            -
                            continue
         | 
| 78 | 
            -
                        elif (j-2)%4 == 0 or (j-3)%4 == 0:
         | 
| 79 | 
            -
                            ws.cell(row=i+3, column = j, value=value).number_format = '$#,##0.0' 
         | 
| 80 | 
            -
                        else:
         | 
| 81 | 
            -
                            ws.cell(row=i+3, column = j, value=value)
         | 
| 82 | 
            -
               
         | 
| 83 | 
            -
            from openpyxl.utils import get_column_letter
         | 
| 84 | 
            -
            from openpyxl.styles import Font, PatternFill
         | 
| 85 | 
            -
            import logging
         | 
| 86 | 
            -
             | 
| 87 | 
            -
            def scenario_df_to_worksheet(df, ws):
         | 
| 88 | 
            -
                heading_fill = PatternFill(start_color='FF11B6BD', end_color='FF11B6BD', fill_type='solid')
         | 
| 89 | 
            -
                
         | 
| 90 | 
            -
                for j, header in enumerate(df.columns.values):
         | 
| 91 | 
            -
                    cell = ws.cell(row=1, column=j + 1, value=header)
         | 
| 92 | 
            -
                    cell.font = Font(bold=True, color='FF11B6BD')
         | 
| 93 | 
            -
                    cell.fill = heading_fill
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                for i, row in enumerate(df.itertuples()):
         | 
| 96 | 
            -
                    for j, value in enumerate(row[1:], start=1):  # Start from index 1 to skip the index column
         | 
| 97 | 
            -
                        try:
         | 
| 98 | 
            -
                            cell = ws.cell(row=i + 2, column=j, value=value)
         | 
| 99 | 
            -
                            if isinstance(value, (int, float)):
         | 
| 100 | 
            -
                                cell.number_format = '$#,##0.0'
         | 
| 101 | 
            -
                            elif isinstance(value, str):
         | 
| 102 | 
            -
                                cell.value = value[:32767]
         | 
| 103 | 
            -
                            else:
         | 
| 104 | 
            -
                                cell.value = str(value)
         | 
| 105 | 
            -
                        except ValueError as e:
         | 
| 106 | 
            -
                            logging.error(f"Error assigning value '{value}' to cell {get_column_letter(j)}{i+2}: {e}")
         | 
| 107 | 
            -
                            cell.value = None  # Assign None to the cell where the error occurred
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                return ws
         | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
               
         | 
| 116 | 
            -
            def download_scenarios():
         | 
| 117 | 
            -
                """
         | 
| 118 | 
            -
                Makes a excel with all saved scenarios and saves it locally
         | 
| 119 | 
            -
                """
         | 
| 120 | 
            -
                ## create summary page
         | 
| 121 | 
            -
                if len(scenarios_to_download) == 0:
         | 
| 122 | 
            -
                    return
         | 
| 123 | 
            -
                wb = Workbook()
         | 
| 124 | 
            -
                wb.iso_dates = True
         | 
| 125 | 
            -
                wb.remove(wb.active)
         | 
| 126 | 
            -
                st.session_state['xlsx_buffer'] = io.BytesIO()
         | 
| 127 | 
            -
                summary_df = None
         | 
| 128 | 
            -
                #print(scenarios_to_download)
         | 
| 129 | 
            -
                for scenario_name in scenarios_to_download:
         | 
| 130 | 
            -
                    scenario_dict =  st.session_state['saved_scenarios'][scenario_name]
         | 
| 131 | 
            -
                    _spends = []
         | 
| 132 | 
            -
                    column_names = ['Date']
         | 
| 133 | 
            -
                    _sales = None
         | 
| 134 | 
            -
                    dates = None
         | 
| 135 | 
            -
                    summary_rows = []
         | 
| 136 | 
            -
                    for channel in scenario_dict['channels']:
         | 
| 137 | 
            -
                        if dates is None:
         | 
| 138 | 
            -
                            dates = channel.get('dates')
         | 
| 139 | 
            -
                            _spends.append(dates)
         | 
| 140 | 
            -
                        if _sales is None:
         | 
| 141 | 
            -
                            _sales = channel.get('modified_sales')
         | 
| 142 | 
            -
                        else:
         | 
| 143 | 
            -
                            _sales += channel.get('modified_sales')
         | 
| 144 | 
            -
                        _spends.append(channel.get('modified_spends') * channel.get('conversion_rate'))
         | 
| 145 | 
            -
                        column_names.append(channel.get('name'))
         | 
| 146 | 
            -
                        
         | 
| 147 | 
            -
                        name_mod = channel_name_formating(channel['name'])
         | 
| 148 | 
            -
                        summary_rows.append([name_mod,
         | 
| 149 | 
            -
                                            channel.get('modified_total_spends') * channel.get('conversion_rate') ,
         | 
| 150 | 
            -
                                            channel.get('modified_total_sales'),
         | 
| 151 | 
            -
                                            channel.get('modified_total_sales') / channel.get('modified_total_spends') * channel.get('conversion_rate'),
         | 
| 152 | 
            -
                                            channel.get('modified_mroi'),
         | 
| 153 | 
            -
                                            channel.get('modified_total_sales') / channel.get('modified_total_spends') * channel.get('conversion_rate')])
         | 
| 154 | 
            -
                    _spends.append(_sales)
         | 
| 155 | 
            -
                    column_names.append('NRPU')
         | 
| 156 | 
            -
                    scenario_df = pd.DataFrame(_spends).T
         | 
| 157 | 
            -
                    scenario_df.columns = column_names
         | 
| 158 | 
            -
                    ## write to sheet
         | 
| 159 | 
            -
                    ws = wb.create_sheet(scenario_name)
         | 
| 160 | 
            -
                    scenario_df_to_worksheet(scenario_df, ws)    
         | 
| 161 | 
            -
                    summary_rows.append(['Total',
         | 
| 162 | 
            -
                                    scenario_dict.get('modified_total_spends') ,
         | 
| 163 | 
            -
                                    scenario_dict.get('modified_total_sales'),
         | 
| 164 | 
            -
                                    scenario_dict.get('modified_total_sales') / scenario_dict.get('modified_total_spends'),
         | 
| 165 | 
            -
                                    '-',
         | 
| 166 | 
            -
                                    scenario_dict.get('modified_total_spends') / scenario_dict.get('modified_total_sales')])
         | 
| 167 | 
            -
                    columns_index = pd.MultiIndex.from_product([[''],['Channel']], names=["first", "second"])
         | 
| 168 | 
            -
                    columns_index = columns_index.append(pd.MultiIndex.from_product([[scenario_name],['Spends','NRPU','ROI','MROI','Spends per NRPU']], names=["first", "second"]))
         | 
| 169 | 
            -
                    if summary_df is None:
         | 
| 170 | 
            -
                        summary_df = pd.DataFrame(summary_rows, columns = columns_index)
         | 
| 171 | 
            -
                        summary_df = summary_df.set_index(('','Channel'))
         | 
| 172 | 
            -
                    else:
         | 
| 173 | 
            -
                        _df = pd.DataFrame(summary_rows, columns = columns_index)
         | 
| 174 | 
            -
                        _df = _df.set_index(('','Channel'))
         | 
| 175 | 
            -
                        summary_df = summary_df.merge(_df, left_index=True, right_index=True)
         | 
| 176 | 
            -
                ws = wb.create_sheet('Summary',0)
         | 
| 177 | 
            -
                summary_df_to_worksheet(summary_df.reset_index(), ws)
         | 
| 178 | 
            -
                wb.save(st.session_state['xlsx_buffer'])
         | 
| 179 | 
            -
                st.session_state['disable_download_button'] = False
         | 
| 180 | 
            -
             | 
| 181 | 
            -
            def disable_download_button():
         | 
| 182 | 
            -
                st.session_state['disable_download_button'] =True
         | 
| 183 | 
            -
             | 
| 184 | 
            -
            def transform(x):
         | 
| 185 | 
            -
                if x.name == ("",'Channel'):
         | 
| 186 | 
            -
                    return x
         | 
| 187 | 
            -
                elif x.name[0] == 'ROI' or x.name[0] == 'MROI':
         | 
| 188 | 
            -
                    return x.apply(lambda y : y if isinstance(y,str) else decimal_formater(format_numbers(y,include_indicator=False,n_decimals=4),n_decimals=4))
         | 
| 189 | 
            -
                else:
         | 
| 190 | 
            -
                    return x.apply(lambda y : y if isinstance(y,str) else format_numbers(y))
         | 
| 191 | 
            -
             | 
| 192 | 
            -
            def delete_scenario():
         | 
| 193 | 
            -
                if selected_scenario in st.session_state['saved_scenarios']:
         | 
| 194 | 
            -
                    del st.session_state['saved_scenarios'][selected_scenario]
         | 
| 195 | 
            -
                    with open('../saved_scenarios.pkl', 'wb') as f:
         | 
| 196 | 
            -
                        pickle.dump(st.session_state['saved_scenarios'],f)     
         | 
| 197 | 
            -
                        
         | 
| 198 | 
            -
            def load_scenario():
         | 
| 199 | 
            -
                if selected_scenario in st.session_state['saved_scenarios']:
         | 
| 200 | 
            -
                    st.session_state['scenario'] = class_from_dict(selected_scenario_details)
         | 
| 201 | 
            -
                    
         | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
            authenticator = st.session_state.get('authenticator')
         | 
| 205 | 
            -
            if authenticator is None:
         | 
| 206 | 
            -
                authenticator = load_authenticator()
         | 
| 207 | 
            -
             | 
| 208 | 
            -
            name, authentication_status, username = authenticator.login('Login', 'main')
         | 
| 209 | 
            -
            auth_status = st.session_state.get('authentication_status')
         | 
| 210 | 
            -
             | 
| 211 | 
            -
            if auth_status == True:
         | 
| 212 | 
            -
                is_state_initiaized = st.session_state.get('initialized',False)
         | 
| 213 | 
            -
                if not is_state_initiaized:
         | 
| 214 | 
            -
                    #print("Scenario page state reloaded")
         | 
| 215 | 
            -
                    initialize_data()
         | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
                saved_scenarios = st.session_state['saved_scenarios']
         | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
                if len(saved_scenarios) ==0:
         | 
| 222 | 
            -
                    st.header('No saved scenarios')
         | 
| 223 | 
            -
                    
         | 
| 224 | 
            -
                else:
         | 
| 225 | 
            -
                    
         | 
| 226 | 
            -
                    with st.sidebar:
         | 
| 227 | 
            -
                        selected_scenario = st.radio(
         | 
| 228 | 
            -
                            'Pick a scenario to view details',
         | 
| 229 | 
            -
                            list(saved_scenarios.keys())
         | 
| 230 | 
            -
                        )
         | 
| 231 | 
            -
                        st.markdown("""<hr>""", unsafe_allow_html=True)
         | 
| 232 | 
            -
                        scenarios_to_download = st.multiselect('Select scenarios to download',
         | 
| 233 | 
            -
                                    list(saved_scenarios.keys()))
         | 
| 234 | 
            -
                        
         | 
| 235 | 
            -
                        st.button('Prepare download',on_click=download_scenarios)
         | 
| 236 | 
            -
                        st.download_button(
         | 
| 237 | 
            -
                                label="Download Scenarios",
         | 
| 238 | 
            -
                                data=st.session_state['xlsx_buffer'].getvalue(),
         | 
| 239 | 
            -
                                file_name="scenarios.xlsx",
         | 
| 240 | 
            -
                                mime="application/vnd.ms-excel",
         | 
| 241 | 
            -
                                disabled= st.session_state['disable_download_button'],
         | 
| 242 | 
            -
                                on_click= disable_download_button
         | 
| 243 | 
            -
                            )
         | 
| 244 | 
            -
                        
         | 
| 245 | 
            -
                    column_1, column_2,column_3 = st.columns((6,1,1))
         | 
| 246 | 
            -
                    with column_1:
         | 
| 247 | 
            -
                        st.header(selected_scenario)
         | 
| 248 | 
            -
                    with column_2:
         | 
| 249 | 
            -
                        st.button('Delete scenarios', on_click=delete_scenario)
         | 
| 250 | 
            -
                    with column_3:
         | 
| 251 | 
            -
                        st.button('Load Scenario', on_click=load_scenario)
         | 
| 252 | 
            -
                    
         | 
| 253 | 
            -
                    selected_scenario_details = saved_scenarios[selected_scenario]
         | 
| 254 | 
            -
                    
         | 
| 255 | 
            -
                    pd.set_option('display.max_colwidth', 100)
         | 
| 256 | 
            -
                        
         | 
| 257 | 
            -
                    st.markdown(create_scenario_summary(selected_scenario_details).transform(transform).style.set_table_styles(
         | 
| 258 | 
            -
                [{
         | 
| 259 | 
            -
                    'selector': 'th',
         | 
| 260 | 
            -
                    'props': [('background-color', '#11B6BD')]
         | 
| 261 | 
            -
                },
         | 
| 262 | 
            -
                    {
         | 
| 263 | 
            -
                    'selector' : 'tr:nth-child(even)',
         | 
| 264 | 
            -
                    'props' : [('background-color', '#11B6BD')]
         | 
| 265 | 
            -
                    }
         | 
| 266 | 
            -
                    ]).to_html(),unsafe_allow_html=True)
         | 
| 267 | 
            -
                    
         | 
| 268 | 
            -
            elif auth_status == False:
         | 
| 269 | 
            -
                st.error('Username/Password is incorrect')
         | 
| 270 | 
            -
                
         | 
| 271 | 
            -
            if auth_status != True:
         | 
| 272 | 
            -
                try:
         | 
| 273 | 
            -
                    username_forgot_pw, email_forgot_password, random_password = authenticator.forgot_password('Forgot password')
         | 
| 274 | 
            -
                    if username_forgot_pw:
         | 
| 275 | 
            -
                        st.success('New password sent securely')
         | 
| 276 | 
            -
                        # Random password to be transferred to user securely
         | 
| 277 | 
            -
                    elif username_forgot_pw == False:
         | 
| 278 | 
            -
                        st.error('Username not found')
         | 
| 279 | 
            -
                except Exception as e:
         | 
| 280 | 
            -
                    st.error(e)
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  |