|
|
|
|
|
|
|
|
|
import random |
|
|
|
import pandas as pd |
|
|
|
import numpy as np |
|
import altair as alt |
|
import plotly.figure_factory as ff |
|
from bokeh.plotting import figure |
|
import pydeck as pdk |
|
import graphviz |
|
import scipy |
|
import datetime |
|
import requests |
|
|
|
|
|
import streamlit as st |
|
import time |
|
import sys |
|
from pathlib import Path |
|
script_dir = Path(__file__).resolve().parent |
|
project_root = script_dir.parent |
|
sys.path.append(str(project_root)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def altair(): |
|
chart_data = pd.DataFrame(np.random.randn(20, 3), columns=["a", "b", "c"]) |
|
|
|
c = ( |
|
alt.Chart(chart_data) |
|
.mark_circle() |
|
.encode(x="a", y="b", size="c", color="c", tooltip=["a", "b", "c"]) |
|
) |
|
|
|
st.altair_chart(c, use_container_width=True) |
|
|
|
def vega_chart(): |
|
chart_data = pd.DataFrame(np.random.randn(200, 3), columns=["a", "b", "c"]) |
|
|
|
st.vega_lite_chart( |
|
chart_data, |
|
{ |
|
"mark": {"type": "circle", "tooltip": True}, |
|
"encoding": { |
|
"x": {"field": "a", "type": "quantitative"}, |
|
"y": {"field": "b", "type": "quantitative"}, |
|
"size": {"field": "c", "type": "quantitative"}, |
|
"color": {"field": "c", "type": "quantitative"}, |
|
}, |
|
}, |
|
) |
|
|
|
def plotly(): |
|
|
|
x1 = np.random.randn(200) - 2 |
|
x2 = np.random.randn(200) |
|
x3 = np.random.randn(200) + 2 |
|
|
|
|
|
hist_data = [x1, x2, x3] |
|
|
|
group_labels = ['Group 1', 'Group 2', 'Group 3'] |
|
|
|
|
|
fig = ff.create_distplot( |
|
hist_data, group_labels, bin_size=[.1, .25, .5]) |
|
|
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
def bokeh(): |
|
|
|
|
|
x = [1, 2, 3, 4, 5] |
|
y = [6, 7, 2, 4, 5] |
|
|
|
p = figure( |
|
title='simple line example', |
|
x_axis_label='x', |
|
y_axis_label='y') |
|
|
|
p.line(x, y, legend_label='Trend', line_width=2) |
|
|
|
st.bokeh_chart(p, use_container_width=True) |
|
|
|
def pydeck(): |
|
|
|
|
|
|
|
|
|
chart_data = pd.DataFrame( |
|
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4], |
|
columns=['lat', 'lon']) |
|
|
|
st.pydeck_chart(pdk.Deck( |
|
map_style=None, |
|
initial_view_state=pdk.ViewState( |
|
latitude=37.76, |
|
longitude=-122.4, |
|
zoom=11, |
|
pitch=50, |
|
), |
|
layers=[ |
|
pdk.Layer( |
|
'HexagonLayer', |
|
data=chart_data, |
|
get_position='[lon, lat]', |
|
radius=200, |
|
elevation_scale=4, |
|
elevation_range=[0, 1000], |
|
pickable=True, |
|
extruded=True, |
|
), |
|
pdk.Layer( |
|
'ScatterplotLayer', |
|
data=chart_data, |
|
get_position='[lon, lat]', |
|
get_color='[200, 30, 0, 160]', |
|
get_radius=200, |
|
), |
|
], |
|
)) |
|
|
|
def graphviz1(): |
|
|
|
|
|
|
|
graph = graphviz.Digraph() |
|
graph.edge('run', 'intr') |
|
graph.edge('intr', 'runbl') |
|
graph.edge('runbl', 'run') |
|
graph.edge('run', 'kernel') |
|
graph.edge('kernel', 'zombie') |
|
graph.edge('kernel', 'sleep') |
|
graph.edge('kernel', 'runmem') |
|
graph.edge('sleep', 'swap') |
|
graph.edge('swap', 'runswap') |
|
graph.edge('runswap', 'new') |
|
graph.edge('runswap', 'runmem') |
|
graph.edge('new', 'runmem') |
|
graph.edge('sleep', 'runmem') |
|
|
|
st.graphviz_chart(graph) |
|
|
|
def map(): |
|
df = pd.DataFrame( |
|
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4], |
|
columns=['lat', 'lon']) |
|
|
|
st.map(df) |
|
|
|
|
|
|
|
|
|
def button(): |
|
st.button("Tushar", type="primary") |
|
if st.button('Saying hello'): |
|
st.write('Why hello there') |
|
else: |
|
st.write('Goodbye') |
|
|
|
def download(): |
|
text_contents = '''This is some text''' |
|
st.download_button('Download some text', text_contents) |
|
|
|
def link(): |
|
st.link_button("Go to Tushar-Aggarwal.com", "https://tushar-aggarwal.com") |
|
|
|
def checkbox(): |
|
agree = st.checkbox('Tushar is great') |
|
|
|
if agree: |
|
st.write('Yes indeed!') |
|
|
|
def toggle(): |
|
on = st.toggle('Activate feature') |
|
|
|
if on: |
|
st.write('Feature activated!') |
|
|
|
def radio(): |
|
|
|
genre = st.radio( |
|
"What's your favorite movie genre", |
|
[":rainbow[Comedy]", "***Drama***", "Documentary :movie_camera:"], |
|
captions = ["Laugh out loud.", "Get the popcorn.", "Never stop learning."]) |
|
|
|
if genre == ':rainbow[Comedy]': |
|
st.write('You selected comedy.') |
|
else: |
|
st.write("You didn\'t select comedy.") |
|
|
|
def option(): |
|
option = st.selectbox( |
|
"How would you like to be contacted?", |
|
("Email", "Home phone", "Mobile phone"), |
|
index=None, |
|
placeholder="Select contact method...", |
|
) |
|
|
|
st.write('You selected:', option) |
|
|
|
def multiselect(): |
|
options = st.multiselect( |
|
'What are your favorite colors', |
|
['Green', 'Yellow', 'Red', 'Blue'], |
|
['Yellow', 'Red']) |
|
|
|
st.write('You selected:', options) |
|
|
|
def slider(): |
|
values = st.slider( |
|
'Select a range of values', |
|
0.0, 100.0, (25.0, 75.0)) |
|
st.write('Values:', values) |
|
|
|
def select_slider(): |
|
start_color, end_color = st.select_slider( |
|
'Select a range of color wavelength', |
|
options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'], |
|
value=('red', 'blue')) |
|
st.write('You selected wavelengths between', start_color, 'and', end_color) |
|
|
|
def text_input(): |
|
title = st.text_input('Movie title', 'Life of Brian') |
|
st.write('The current movie title is', title) |
|
|
|
def number_input(): |
|
number = st.number_input('Insert a number') |
|
st.write('The current number is ', number) |
|
|
|
def text_area(): |
|
txt = st.text_area( |
|
"Text to analyze", |
|
"It was the best of times, it was the worst of times, it was the age of " |
|
"wisdom, it was the age of foolishness, it was the epoch of belief, it " |
|
"was the epoch of incredulity, it was the season of Light, it was the " |
|
"season of Darkness, it was the spring of hope, it was the winter of " |
|
"despair, (...)", |
|
) |
|
st.write(f'You wrote {len(txt)} characters.') |
|
|
|
def date_input(): |
|
|
|
|
|
today = datetime.datetime.now() |
|
next_year = today.year + 1 |
|
jan_1 = datetime.date(next_year, 1, 1) |
|
dec_31 = datetime.date(next_year, 12, 31) |
|
|
|
d = st.date_input( |
|
"Select your vacation for next year", |
|
(jan_1, datetime.date(next_year, 1, 7)), |
|
jan_1, |
|
dec_31, |
|
format="MM.DD.YYYY", |
|
) |
|
d |
|
|
|
def time_input(): |
|
t = st.time_input('Set an alarm for', datetime.time(8, 45)) |
|
|
|
st.write('Alarm is set for', t) |
|
|
|
def file_upload(): |
|
uploaded_files = st.file_uploader("Choose a CSV file", accept_multiple_files=True) |
|
for uploaded_file in uploaded_files: |
|
bytes_data = uploaded_file.read() |
|
st.write("filename:", uploaded_file.name) |
|
st.write(bytes_data) |
|
|
|
def camera_input(): |
|
picture = st.camera_input("Take a picture") |
|
|
|
if picture: |
|
st.image(picture) |
|
|
|
def color_picker(): |
|
color = st.color_picker('Pick A Color', '#00f900') |
|
st.write('The current color is', color) |
|
|
|
|
|
|
|
def image(): |
|
image_url = "https://images.unsplash.com/photo-1561564723-570b270e7c36" |
|
st.image(image_url, caption='Amazing Sunrise', use_column_width=True) |
|
|
|
def audio(): |
|
def get_random_fma_track(): |
|
base_url = "https://files.freemusicarchive.org/" |
|
endpoint = "random/track" |
|
response = requests.get(f"{base_url}{endpoint}") |
|
if response.status_code == 200: |
|
track_url = response.url |
|
return track_url |
|
return None |
|
|
|
|
|
random_audio_url = get_random_fma_track() |
|
|
|
|
|
if random_audio_url: |
|
st.audio(random_audio_url, format="audio/mp3") |
|
else: |
|
st.write("Failed to fetch a random audio track. Please try again later.") |
|
|
|
def video(): |
|
video_urls = [ |
|
"https://www.youtube.com/watch?v=VIDEO_ID_1", |
|
"https://www.youtube.com/watch?v=VIDEO_ID_2", |
|
"https://www.youtube.com/watch?v=VIDEO_ID_3", |
|
|
|
] |
|
|
|
|
|
random_video_url = random.choice(video_urls) |
|
|
|
|
|
st.video(random_video_url) |
|
|
|
def sidebar(): |
|
|
|
|
|
|
|
add_selectbox = st.sidebar.selectbox( |
|
"How would you like to be contacted?", |
|
("Email", "Home phone", "Mobile phone") |
|
) |
|
|
|
|
|
with st.sidebar: |
|
add_radio = st.radio( |
|
"Choose a shipping method", |
|
("Standard (5-15 days)", "Express (2-5 days)") |
|
) |
|
|
|
|
|
|
|
|
|
def columns(): |
|
cola, colb, colc = st.columns(3) |
|
|
|
with cola: |
|
st.header("A cat") |
|
st.image("https://static.streamlit.io/examples/cat.jpg") |
|
|
|
with colb: |
|
st.header("A dog") |
|
st.image("https://static.streamlit.io/examples/dog.jpg") |
|
|
|
with colc: |
|
st.header("An owl") |
|
st.image("https://static.streamlit.io/examples/owl.jpg") |
|
|
|
def tab(): |
|
tab1, tab2, tab3 = st.tabs(["Cat", "Dog", "Owl"]) |
|
|
|
with tab1: |
|
st.header("A cat") |
|
st.image("https://static.streamlit.io/examples/cat.jpg", width=200) |
|
|
|
with tab2: |
|
st.header("A dog") |
|
st.image("https://static.streamlit.io/examples/dog.jpg", width=200) |
|
|
|
with tab3: |
|
st.header("An owl") |
|
st.image("https://static.streamlit.io/examples/owl.jpg", width=200) |
|
|
|
def expander(): |
|
chart = st.bar_chart({"data": [1, 5, 2, 6, 2, 1]}) |
|
|
|
|
|
chart |
|
st.write("The chart above shows some randon numbers. st.expander help to hide elements by default and show ony when expanded") |
|
|
|
def container(): |
|
with st.container(): |
|
st.write("This is inside the container") |
|
|
|
|
|
st.bar_chart(np.random.randn(50, 3)) |
|
|
|
|
|
st.write("This is outside the container") |
|
|
|
def empty(): |
|
placeholder = st.empty() |
|
|
|
|
|
placeholder.text("Hello") |
|
|
|
|
|
placeholder.line_chart({"data": [1, 5, 2, 6]}) |
|
|
|
|
|
with placeholder.container(): |
|
st.write("This is one element") |
|
st.write("This is another") |
|
|
|
|
|
placeholder.empty() |
|
|
|
|
|
|
|
def chat_message(): |
|
with st.chat_message("user"): |
|
st.write("🤖 Hello 👋") |
|
st.write("How may I help you today?") |
|
|
|
def chat_input(): |
|
prompt = st.chat_input("How may I help you today?") |
|
if prompt: |
|
st.write(f"User has sent the following prompt: {prompt}") |
|
|
|
|
|
|
|
|
|
|
|
def progress(): |
|
progress_text = "Operation in progress. Please wait." |
|
my_bar = st.progress(0, text=progress_text) |
|
|
|
for percent_complete in range(100): |
|
time.sleep(0.01) |
|
my_bar.progress(percent_complete + 1, text=progress_text) |
|
time.sleep(1) |
|
my_bar.empty() |
|
|
|
st.button("Rerun") |
|
|
|
def spinner(): |
|
with st.spinner('Wait for it...'): |
|
time.sleep(2) |
|
st.success('Done!') |
|
|
|
def status(): |
|
st.status("Downloading data...") |
|
st.write("Searching for data...") |
|
time.sleep(1) |
|
st.write("Found URL.") |
|
time.sleep(1) |
|
st.write("Downloading data...") |
|
time.sleep(1) |
|
|
|
st.button('Rerun', key='1') |
|
|
|
def toast(): |
|
st.toast('Your prompt was send for processing!', icon='😍') |
|
|
|
def error(): |
|
st.error('There is an error', icon="🚨") |
|
|
|
def warning(): |
|
st.warning('This task will utilize multiple resources, expect time delay', icon="⚠️") |
|
|
|
def info(): |
|
st.info('This task will utilize paid API', icon="💵") |
|
|
|
def success(): |
|
st.success('This is a success message!', icon="✅") |
|
|
|
def exception(): |
|
e = RuntimeError('This is an exception of type RuntimeError') |
|
st.exception(e) |
|
|
|
|
|
|
|
|
|
|
|
def form(): |
|
form = st.form("Try Form") |
|
form.slider("Inside the form") |
|
|
|
st.slider("Outside the form") |
|
|
|
|
|
form.form_submit_button("Submit") |
|
|
|
|
|
|
|
|
|
|
|
def echo(): |
|
with st.echo(): |
|
st.write('Tushar is the best') |
|
|
|
def help(): |
|
st.help(st.write) |
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_rows(): |
|
df1 = pd.DataFrame(np.random.randn(50, 20), columns=("col %d" % i for i in range(20))) |
|
|
|
my_table = st.table(df1) |
|
|
|
df2 = pd.DataFrame(np.random.randn(50, 20), columns=("col %d" % i for i in range(20))) |
|
|
|
my_table.add_rows(df2) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|