SUNGJIN LEE commited on
Commit
312b9eb
โ€ข
1 Parent(s): 299fe51

Initial commit

Browse files
Files changed (13) hide show
  1. .devcontainer/devcontainer.json +33 -0
  2. .gitignore +3 -0
  3. app.py +54 -0
  4. chart.py +16 -0
  5. config.yaml +12 -0
  6. data.py +48 -0
  7. js.py +41 -0
  8. map.py +35 -0
  9. map_recommend.py +40 -0
  10. pages/About.py +30 -0
  11. pages/Dashboard.py +107 -0
  12. pages/Recommendation System.py +91 -0
  13. requirements.txt +37 -0
.devcontainer/devcontainer.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Python 3",
3
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
4
+ "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
5
+ "customizations": {
6
+ "codespaces": {
7
+ "openFiles": [
8
+ "README.md",
9
+ "Home.py"
10
+ ]
11
+ },
12
+ "vscode": {
13
+ "settings": {},
14
+ "extensions": [
15
+ "ms-python.python",
16
+ "ms-python.vscode-pylance"
17
+ ]
18
+ }
19
+ },
20
+ "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo 'โœ… Packages installed and Requirements met'",
21
+ "postAttachCommand": {
22
+ "server": "streamlit run Home.py --server.enableCORS false --server.enableXsrfProtection false"
23
+ },
24
+ "portsAttributes": {
25
+ "8501": {
26
+ "label": "Application",
27
+ "onAutoForward": "openPreview"
28
+ }
29
+ },
30
+ "forwardPorts": [
31
+ 8501
32
+ ]
33
+ }
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ generate_keys.py
2
+ __pycache__/
3
+ .streamlit/
app.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit.logger import get_logger
3
+ import streamlit_authenticator as stauth
4
+ import yaml
5
+
6
+ LOGGER = get_logger(__name__)
7
+
8
+ def run():
9
+ st.set_page_config(
10
+ page_title="SKT AI Fellowship Team ASAP",
11
+ page_icon="๐Ÿ“ก",
12
+ layout="centered"
13
+ )
14
+
15
+ st.write("# SKT AI Fellowship Team ASAP ๐Ÿ‘‹")
16
+
17
+ def st_authenticator():
18
+ with open('config.yaml') as file:
19
+ config = yaml.load(file, Loader=stauth.SafeLoader)
20
+
21
+ authenticator = stauth.Authenticate(
22
+ config['credentials'],
23
+ config['cookie']['name'],
24
+ config['cookie']['key'],
25
+ config['cookie']['expiry_days'],
26
+ config['preauthorized']
27
+ )
28
+
29
+ return authenticator
30
+
31
+ if __name__ == "__main__":
32
+ run()
33
+ authenticator = st_authenticator()
34
+
35
+ if 'authentication_status' not in st.session_state:
36
+ st.session_state['authentication_status'] = None
37
+ st.session_state['username'] = None
38
+
39
+ name, authentication_status, username = authenticator.login("main", "Login")
40
+
41
+ if authentication_status:
42
+ st.session_state['authentication_status'] = True
43
+ st.session_state['username'] = username
44
+ st.success(f"{name}๋‹˜, ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!")
45
+ authenticator.logout('Logout', 'main', key='unique_key')
46
+
47
+ elif authentication_status is False:
48
+ st.session_state['authentication_status'] = False
49
+ st.error('์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.')
50
+
51
+ elif authentication_status is None:
52
+ st.session_state['authentication_status'] = None
53
+ st.warning('์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.')
54
+
chart.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import altair as alt
3
+
4
+ def create_area_chart(filtered_data_long, selected_cell):
5
+ chart = alt.Chart(filtered_data_long).mark_area().encode(
6
+ x=alt.X('timestamp:T', title='Timestamp'),
7
+ y=alt.Y('Value:Q', title='RB Used'),
8
+ color=alt.Color('RB:N', title='RB Type'),
9
+ tooltip=['timestamp:T', 'RB:N', 'Value:Q']
10
+ ).properties(
11
+ width=800,
12
+ height=400,
13
+ title=f'RB Usage for Cell ID: {selected_cell}'
14
+ ).interactive()
15
+
16
+ return chart
config.yaml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cookie:
2
+ expiry_days: 1
3
+ key: some_signature_key
4
+ name: streamlit-cookie
5
+ credentials:
6
+ usernames:
7
+ asap:
8
+ name: asap
9
+ password: $2b$12$T657ZXBqAyJuartbrwlUMOP9G.n94O8qsdsuyDZRxUKQ2Yj.TsJHu
10
+ preauthorized:
11
+ emails:
12
data.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import streamlit as st
3
+ from google.oauth2.service_account import Credentials
4
+ from googleapiclient.discovery import build
5
+ from googleapiclient.http import MediaIoBaseDownload
6
+ import io
7
+
8
+ # Google Drive ๋ฐ Sheets API ์ธ์ฆ
9
+ scope = [
10
+ "https://www.googleapis.com/auth/drive.readonly"
11
+ ]
12
+ credentials = Credentials.from_service_account_info(st.secrets["google"], scopes=scope)
13
+ file_id = st.secrets["drive"]["file_id"]
14
+
15
+ drive_service = build('drive', 'v3', credentials=credentials)
16
+
17
+ @st.cache_data(show_spinner=False)
18
+ def load_data():
19
+ request = drive_service.files().get_media(fileId=file_id)
20
+
21
+ file_buffer = io.BytesIO()
22
+
23
+ downloader = MediaIoBaseDownload(file_buffer, request)
24
+ done = False
25
+
26
+ progress_bar = st.sidebar.progress(0)
27
+ progress_text = st.sidebar.empty()
28
+ progress_text.text("๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘...")
29
+
30
+ while not done:
31
+ status, done = downloader.next_chunk()
32
+ progress = int(status.progress() * 100)
33
+ progress_bar.progress(progress)
34
+ progress_text.text(f"๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘...({progress}%)")
35
+
36
+ file_buffer.seek(0)
37
+ df = pd.read_csv(file_buffer)
38
+
39
+ df['ru_svc_lat_val'] = df['ru_svc_lat_val'].astype(float)
40
+ df['ru_svc_lng_val'] = df['ru_svc_lng_val'].astype(float)
41
+
42
+ df_map = df.drop_duplicates(subset=['ru_svc_lat_val', 'ru_svc_lng_val'])
43
+
44
+ progress_bar.empty()
45
+ progress_text.empty()
46
+ st.sidebar.success("๋ฐ์ดํ„ฐ ๋กœ๋“œ ์™„๋ฃŒ!")
47
+
48
+ return df, df_map
js.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from folium.map import Marker
2
+ from jinja2 import Template
3
+
4
+ def set_marker_click_template():
5
+ click_marker = """
6
+ {% macro script(this, kwargs) %}
7
+
8
+ function copyToClipboard(text) {
9
+ navigator.clipboard.writeText(text).then(function() {
10
+ console.log("ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค: ", text);
11
+ }, function(err) {
12
+ console.error("ํด๋ฆฝ๋ณด๋“œ ๋ณต์‚ฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค: ", err);
13
+ });
14
+ }
15
+
16
+ function showToast() {
17
+ var toast = document.getElementById("toast");
18
+ toast.style.visibility = "visible";
19
+ setTimeout(function() {
20
+ toast.style.visibility = "hidden";
21
+ }, 3000);
22
+ }
23
+
24
+ function onClick(e) {
25
+ var marker = e.target;
26
+ if (marker.getTooltip()) {
27
+ var cellID = marker.getTooltip().getElement().innerText.trim();
28
+ copyToClipboard(cellID);
29
+ }
30
+ }
31
+
32
+ var {{ this.get_name() }} = L.marker(
33
+ {{ this.location|tojson }},
34
+ {{ this.options|tojson }}
35
+ ).addTo({{ this._parent.get_name() }}).on('click', onClick);
36
+
37
+ {% endmacro %}
38
+ """
39
+
40
+ Marker._template = Template(click_marker)
41
+
map.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import folium
2
+ from folium import CustomIcon, DivIcon
3
+
4
+ def create_map(dataframe):
5
+ m = folium.Map(
6
+ location=[35.1796, 129.0756],
7
+ zoom_start=12,
8
+ control_scale=True,
9
+ tiles='CartoDB positron'
10
+ )
11
+
12
+ for idx, row in dataframe.iterrows():
13
+ cell_id = row['enbid_pci']
14
+
15
+ color = 'green'
16
+ custom_icon = DivIcon(
17
+ html=f"""
18
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
19
+ <circle cx="10" cy="10" r="5.625" fill="{color}" stroke="#000000" stroke-width="1.25"/>
20
+ </svg>
21
+ """,
22
+ icon_size=(20, 20),
23
+ icon_anchor=(10, 10)
24
+ )
25
+
26
+ marker = folium.Marker(
27
+ # popup=f'Cell ID: {cell_id}',
28
+ location=(row['ru_svc_lat_val'], row['ru_svc_lng_val']),
29
+ icon=custom_icon,
30
+ tooltip=f'{cell_id}'
31
+ )
32
+
33
+ marker.add_to(m)
34
+
35
+ return m
map_recommend.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import folium
2
+ from folium import CustomIcon, DivIcon
3
+
4
+ def create_map(dataframe, recommendations):
5
+ m = folium.Map(
6
+ location=[35.1796, 129.0756],
7
+ zoom_start=12,
8
+ control_scale=True,
9
+ tiles='CartoDB positron'
10
+ )
11
+
12
+ for idx, row in dataframe.iterrows():
13
+ cell_id = row['enbid_pci']
14
+
15
+ recommended_cell_state = recommendations.get(cell_id, 'OFF')
16
+
17
+ if recommended_cell_state == 'ON':
18
+ color = 'blue'
19
+ else:
20
+ color = 'red'
21
+
22
+ custom_icon = DivIcon(
23
+ html=f"""
24
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
25
+ <circle cx="10" cy="10" r="5.625" fill="{color}" stroke="#000000" stroke-width="1.25"/>
26
+ </svg>
27
+ """,
28
+ icon_size=(20, 20),
29
+ icon_anchor=(10, 10)
30
+ )
31
+
32
+ marker = folium.Marker(
33
+ location=(row['ru_svc_lat_val'], row['ru_svc_lng_val']),
34
+ icon=custom_icon,
35
+ tooltip=f'{cell_id} - {recommended_cell_state}'
36
+ )
37
+
38
+ marker.add_to(m)
39
+
40
+ return m
pages/About.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit.logger import get_logger
3
+
4
+ LOGGER = get_logger(__name__)
5
+
6
+ def run():
7
+ st.set_page_config(
8
+ page_title="About"
9
+ )
10
+
11
+ st.markdown(
12
+ """
13
+ ##### *Team ASAP์€ ๋„คํŠธ์›Œํฌ์˜ ์—๋„ˆ์ง€ ์†Œ๋น„๋ฅผ ์ค„์ด๊ณ  ํƒ„์†Œ ๋ฐฐ์ถœ์„ ๊ฐ์†Œ์‹œํ‚ค๊ธฐ ์œ„ํ•œ AI ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ๋Š” ๋ชจ๋ฐ”์ผ ๋„คํŠธ์›Œํฌ์—์„œ ์—๋„ˆ์ง€ ํšจ์œจ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜์—ฌ ์ง€์† ๊ฐ€๋Šฅํ•œ ๋ฐœ์ „์„ ์ด๋ฃจ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.*
14
+
15
+ ##### Green AI์˜ ํ•„์š”์„ฑ
16
+ - **ํšจ์œจ์„ฑ**: AI ๊ธฐ๋ฐ˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋„คํŠธ์›Œํฌ์˜ ์—๋„ˆ์ง€ ์†Œ๋น„ ํŒจํ„ด์„ ๋ถ„์„ํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์†Œ๋น„๋ฅผ ์ค„์ž…๋‹ˆ๋‹ค.
17
+ - **๊ณ ๊ฐ ๊ฒฝํ—˜**: ๊ณ ๊ฐ ๊ฒฝํ—˜์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ ์—๋„ˆ์ง€๋ฅผ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ๋Š” ์†”๋ฃจ์…˜์„ ๊ฐœ๋ฐœํ•ฉ๋‹ˆ๋‹ค.
18
+ - **์ง€์† ๊ฐ€๋Šฅ์„ฑ**: ํƒ„์†Œ ๋ฐฐ์ถœ์„ ์ค„์ด๊ณ  ์šด์˜๋น„์šฉ(OPEX)์„ ์ ˆ๊ฐํ•˜์—ฌ ํ™˜๊ฒฝ๊ณผ ๊ฒฝ์ œ์  ์ด์ต์„ ๋™์‹œ์— ์ถ”๊ตฌํ•ฉ๋‹ˆ๋‹ค.
19
+
20
+ ##### ์ฃผ์š” ๊ธฐ์ˆ 
21
+ - **AI ๊ธฐ๋ฐ˜ ์—๋„ˆ์ง€ ์ ˆ์•ฝ ์•Œ๊ณ ๋ฆฌ์ฆ˜**: ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ถ„์„ํ•˜์—ฌ, ์—๋„ˆ์ง€ ์†Œ๋น„๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.
22
+ - **MLOps**: ์ž๋™ํ™”๋œ ๋ชจ๋ธ ํ•™์Šต ๋ฐ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ตํ•ด AI ๋ชจ๋ธ์˜ ํšจ์œจ์ ์ธ ์šด์˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
23
+
24
+ ##### ํ”„๋กœ์ ํŠธ์˜ ๊ฐ€์น˜
25
+ - **์—๋„ˆ์ง€ ์ ˆ๊ฐ**: ์—๋„ˆ์ง€ ์ ˆ์•ฝ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์ „๊ธฐ ์š”๊ธˆ์„ ์ ˆ๊ฐํ•˜๊ณ , ๊ณ ๊ฐ์—๊ฒŒ ์ตœ์ƒ์˜ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
26
+ """
27
+ )
28
+
29
+ if __name__ == "__main__":
30
+ run()
pages/Dashboard.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit_folium import folium_static
3
+ import pandas as pd
4
+ import data
5
+ import map
6
+ import js
7
+ import chart
8
+
9
+ st.set_page_config(page_title="Dashboard",
10
+ layout="wide",
11
+ page_icon="๐Ÿ—บ๏ธ")
12
+
13
+ if not st.session_state.get('authentication_status', False):
14
+ st.write("### ๐Ÿšจ **์ ‘๊ทผ ๋ถˆ๊ฐ€** ๐Ÿšจ")
15
+ st.write("์ด ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.<br>๋กœ๊ทธ์ธํ•ด ์ฃผ์„ธ์š”.", unsafe_allow_html=True)
16
+ st.stop()
17
+
18
+ df, df_map = data.load_data()
19
+
20
+ cell_map = map.create_map(df_map)
21
+
22
+ if 'selected_cell' not in st.session_state:
23
+ st.session_state['selected_cell'] = ""
24
+
25
+ if 'selected_rbs' not in st.session_state:
26
+ st.session_state['selected_rbs'] = ['RB_800', 'RB_1800', 'RB_2100', 'RB_2600_10', 'RB_2600_20']
27
+
28
+ def main():
29
+ st.markdown("# Dashboard")
30
+
31
+ show_map = st.sidebar.checkbox("์ง€๋„ ๋ณด๊ธฐ", True)
32
+ if show_map:
33
+ st.markdown("### ๐Ÿ—บ๏ธ ๋ถ€์‚ฐ PoC ์…€ ์‚ฌ์ดํŠธ")
34
+
35
+ folium_static(cell_map)
36
+
37
+ st.write("""
38
+ <style>
39
+ iframe {
40
+ max-width: 2000px;
41
+ width: 100%;
42
+ height: 600px;
43
+ border-radius: 10px;
44
+ border: 1px solid #d3d3d3;
45
+ }
46
+ </style>
47
+ """, unsafe_allow_html=True)
48
+
49
+ js.set_marker_click_template()
50
+
51
+ unique_cells = df['enbid_pci'].unique().tolist()
52
+
53
+ show_chart = st.sidebar.checkbox("์ฐจํŠธ ๋ณด๊ธฐ", True)
54
+ if show_chart:
55
+ selected_cell = st.selectbox("์กฐํšŒํ•  ์…€ ID:", unique_cells, index=unique_cells.index(st.session_state['selected_cell']) if st.session_state['selected_cell'] in unique_cells else 0)
56
+ st.session_state['selected_cell'] = selected_cell
57
+
58
+ cell_data = df[df['enbid_pci'] == st.session_state['selected_cell']].copy()
59
+
60
+ if not cell_data.empty:
61
+ rb_options = []
62
+ if cell_data['Equip_800'].eq(1).any():
63
+ rb_options.append('RB_800')
64
+ if cell_data['Equip_1800'].eq(1).any():
65
+ rb_options.append('RB_1800')
66
+ if cell_data['Equip_2100'].eq(1).any():
67
+ rb_options.append('RB_2100')
68
+ if cell_data['Equip_2600_10'].eq(1).any():
69
+ rb_options.append('RB_2600_10')
70
+ if cell_data['Equip_2600_20'].eq(1).any():
71
+ rb_options.append('RB_2600_20')
72
+
73
+ selected_rbs = st.multiselect("RB ์ปฌ๋Ÿผ:", rb_options, default=[rb for rb in st.session_state['selected_rbs'] if rb in rb_options])
74
+ st.session_state['selected_rbs'] = selected_rbs
75
+
76
+ cell_data['timestamp'] = pd.to_datetime(cell_data['timestamp'])
77
+
78
+ min_date = cell_data['timestamp'].min().to_pydatetime()
79
+ max_date = cell_data['timestamp'].max().to_pydatetime()
80
+
81
+ start_date, end_date = st.slider(
82
+ "๋‚ ์งœ ๋ฒ”์œ„:",
83
+ min_value=min_date,
84
+ max_value=max_date,
85
+ value=(min_date, max_date),
86
+ format="MM/DD/YY"
87
+ )
88
+
89
+ filtered_data = cell_data[(cell_data['timestamp'] >= start_date) & (cell_data['timestamp'] <= end_date)]
90
+
91
+ filtered_data_long = pd.melt(
92
+ filtered_data,
93
+ id_vars=['timestamp'],
94
+ value_vars=st.session_state['selected_rbs'],
95
+ var_name='RB',
96
+ value_name='Value'
97
+ )
98
+
99
+ chart_obj = chart.create_area_chart(filtered_data_long, st.session_state['selected_cell'])
100
+
101
+ # ์ฐจํŠธ ํ‘œ์‹œ
102
+ st.altair_chart(chart_obj, use_container_width=True)
103
+ else:
104
+ st.write("์„ ํƒํ•œ ์…€ ID์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
105
+
106
+ if __name__ == "__main__":
107
+ main()
pages/Recommendation System.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ from datetime import datetime, time
5
+ import tensorflow as tf
6
+ from streamlit_folium import folium_static
7
+ import map_recommend
8
+ import data
9
+
10
+ st.set_page_config(page_title="Frequency Off Recommendation System",
11
+ layout="wide",
12
+ page_icon="๐Ÿ“ก")
13
+
14
+ if not st.session_state.get('authentication_status', False):
15
+ st.write("### ๐Ÿšจ **์ ‘๊ทผ ๋ถˆ๊ฐ€** ๐Ÿšจ")
16
+ st.write("์ด ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.<br>๋กœ๊ทธ์ธํ•ด ์ฃผ์„ธ์š”.", unsafe_allow_html=True)
17
+ st.stop()
18
+
19
+ st.title('Cell Off Recommendation System')
20
+
21
+ date_input = st.date_input('๋‚ ์งœ ์„ ํƒ:', datetime(2024, 8, 6))
22
+ time_input = st.time_input('์‹œ๊ฐ„ ์„ ํƒ:', time(0, 0))
23
+
24
+ timestamp_input = datetime.combine(date_input, time_input)
25
+
26
+ model_options = ['๋ชจ๋ธ 1: Rule-based']
27
+ selected_model = st.selectbox('๋ชจ๋ธ ์„ ํƒ:', model_options)
28
+
29
+ run_button = st.button('Run')
30
+
31
+ input_data = pd.DataFrame({
32
+ 'hour': [timestamp_input.hour],
33
+ 'is_weekend': [timestamp_input.weekday() >= 5]
34
+ })
35
+
36
+ def load_and_predict(model_name, input_data, df_map, progress_callback=None):
37
+ recommended_cell_states = {}
38
+
39
+ if progress_callback:
40
+ progress_callback(10)
41
+
42
+ if model_name == '๋ชจ๋ธ 1: Rule-based':
43
+ for idx, row in df_map.iterrows():
44
+ if timestamp_input.hour < 6 or timestamp_input.hour > 22:
45
+ recommended_cell_states[row['enbid_pci']] = 'OFF'
46
+ else:
47
+ recommended_cell_states[row['enbid_pci']] = 'ON'
48
+ if progress_callback:
49
+ progress_callback(10 + 80 * (idx + 1) // len(df_map))
50
+
51
+ return recommended_cell_states
52
+
53
+ if run_button:
54
+
55
+ # with st.sidebar:
56
+ # with st.spinner('๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์ค‘...'):
57
+ # df, df_map = data.load_data()
58
+ # st.sidebar.success('๋ฐ์ดํ„ฐ ๋กœ๋“œ ์™„๋ฃŒ')
59
+ df, df_map = data.load_data()
60
+
61
+ progress_bar = st.sidebar.progress(0)
62
+
63
+ timestamp_input = pd.to_datetime(timestamp_input)
64
+
65
+ recommended_cell_states = load_and_predict(
66
+ selected_model,
67
+ input_data,
68
+ df_map,
69
+ progress_callback=progress_bar.progress
70
+ )
71
+
72
+ m = map_recommend.create_map(df_map, recommended_cell_states)
73
+
74
+ progress_bar.progress(100)
75
+ st.sidebar.success('๋ถ„์„ ์™„๋ฃŒ')
76
+
77
+ progress_bar.empty()
78
+
79
+ folium_static(m)
80
+
81
+ st.write("""
82
+ <style>
83
+ iframe {
84
+ max-width: 2000px;
85
+ width: 100%;
86
+ height: 600px;
87
+ border-radius: 10px;
88
+ border: 1px solid #d3d3d3;
89
+ }
90
+ </style>
91
+ """, unsafe_allow_html=True)
requirements.txt ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ extra-streamlit-components==0.1.71
2
+ Flask==3.0.3
3
+ Flask-Cors==4.0.1
4
+ Flask-SocketIO==5.3.6
5
+ flatbuffers==24.3.25
6
+ folium==0.17.0
7
+ google-api-core==2.19.1
8
+ google-api-python-client==2.139.0
9
+ google-auth==2.32.0
10
+ google-auth-httplib2==0.2.0
11
+ google-auth-oauthlib==1.2.1
12
+ google-pasta==0.2.0
13
+ googleapis-common-protos==1.63.2
14
+ gspread==5.12.4
15
+ gspread-dataframe==4.0.0
16
+ gspread-formatting==1.2.0
17
+ gspread-pandas==3.3.0
18
+ keras==3.4.1
19
+ matplotlib==3.9.1
20
+ matplotlib-inline==0.1.7
21
+ numpy==1.26.4
22
+ pandas==1.5.3
23
+ pip==24.2
24
+ scikit-learn==1.5.1
25
+ scipy==1.14.0
26
+ seaborn==0.13.2
27
+ streamlit==1.37.1
28
+ streamlit-authenticator==0.3.3
29
+ streamlit-cookies-controller==0.0.4
30
+ streamlit-cookies-manager==0.2.0
31
+ streamlit_folium==0.22.0
32
+ streamlit-javascript==0.1.5
33
+ tensorboard==2.17.0
34
+ tensorboard-data-server==0.7.2
35
+ tensorflow==2.17.0
36
+ tensorflow-io-gcs-filesystem==0.37.1
37
+ tqdm==4.66.5