File size: 16,188 Bytes
bfcf5a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
import streamlit as st
import re
import altair as alt
from folder_management import create_folder, remove_files_folder

st.set_page_config('Product Recommendation Application', layout='wide', page_icon='airtory_logo.PNG')


# Functions/Pages
def intro():
    import streamlit as st

    st.markdown("## Welcome to the Product Recommendation Application! πŸ‘‹")
    st.sidebar.success("Select a page from above.")

    st.markdown(
        """
        **πŸ‘ˆ Select a page from the navigation bar to the left**

###  Functionality of Pages
#### Generate Recommendations Page
- This page allows you to generate recommendations for a particular keyword/publisherid combo.
- The recommendations for each keyword/publisherid combo, are stored in a separate SQLite Database Table.
- Ideally, for each keyword/publisherid combo, the recommendations should only be generated once per day. To mock this, you are only allowed to generate recommendations for a specific keyword/publisherid combo once.
#### Product Recommendations Page
- This page displays the Product Recommendations for each keyword/publisherid combo for which the recommendations were generated in the previous page.
- You can currently select the available keywords from the dropdown provided in the side bar.
- For the time being, the Publisher ID is restricted to a single known value. This can be easily updated later.
- Note: Since the click tracker I was using had issues, as a workaround I had to use a Button instead. So now, to register a click against a product, you need to click on the 'Select' button provided below each product. 
- For each session, once a product is clicked on, it is no longer displayed.
- You can choose the number of recommendations to be displayed, between 1 & 5.
- The maximum number of recommendations that are available for display for each keyword/publisherid combo is restricted to 50.
- The minumum number depends on the products available from bizrate.
- If/when all available recommendations for a keyword/publisherid combo has been clicked on, you can either choose a different keyword, reload the application to create a new session.
#### Analytics Page
- Displays a Line Chart and a Bar Chart, to show the distribution of clicks across Session ID, Keyword, Publisher ID, SKU or Date.
- Displays a table of the most clicked SKU's
    """
    )


def generate_recommendations():
    import os
    import string
    import random
    import streamlit as st
    import warnings
    warnings.filterwarnings('ignore')

    # custom module
    # from clickcounter import clickcounter
    from folder_management import create_folder, remove_files_folder
    from sqlite_database import create_insert_table, query_table, insert_clickdata_table, check_for_table
    from recommend import query_bizrate, recommend, generate_clickreport

    # Functions
    def random_string(N=7):
        res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=N))
        return str(res)

    def query_and_recommend(keyword, publisherid):
        query_bizrate(keyword, publisherid)
        recommend(keyword, publisherid)
        generate_clickreport()

    # Main Program

    # st.set_page_config('Generate Recommendations', layout='wide')

    st.title('Generate Recommendations')
    st.markdown('''<pre style="text-align:center">
    <strong><span style="color:#6a8759">
    Generate Recommendations for any Keyword - Publisher ID Combo. <br><br> </span></strong></pre>''',
                unsafe_allow_html=True)

    col1, col2 = st.columns(2)

    selected_keyword = ''
    publisher_id = ''

    with col1:
        selected_keyword = st.text_input('Enter a single word as keyword:', 'bed')
        selected_keyword = selected_keyword.lower()
        selected_keyword = selected_keyword.replace('-', '')
        selected_keyword = ''.join(re.split(r"[ \|\\\/,.]", selected_keyword))
        # selected_keyword = ''.join(selected_keyword.split())
        st.write(selected_keyword)

    with col2:
        publisher_id = st.text_input("Enter a Publisher ID: ", '726189')
        # st.write(publisher_id)

    keyword_pubid_list = []
    for file in os.listdir('bizrate'):
        keyword_pubid_list.append(file.replace(".xml", ""))

    if selected_keyword + "_" + publisher_id in keyword_pubid_list:
        st.error('Keyword - Publisher ID Combo Exists!')
    else:
        st.info("Keyword - Publisher ID Combo doesn't exist. Must be queried")
        st.button('Generate Recommendations', key=random_string(), on_click=query_and_recommend,
                  args=([selected_keyword, publisher_id]))


def display_recommendations():
    import pandas as pd
    import numpy as np
    import requests
    from bs4 import BeautifulSoup
    import urllib.parse
    import os
    import string
    import random

    import time

    import streamlit as st
    import uuid

    import warnings
    import sys

    warnings.filterwarnings('ignore')

    # custom module
    # from clickcounter import clickcounter
    from folder_management import create_folder, remove_files_folder
    from sqlite_database import create_insert_table, query_table, insert_clickdata_table, check_for_table

    # Functions
    def random_string(N=7):
        res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=N))
        return str(res)

    # def display_products(dfp):
    #     product_list = list(dfp['title'])
    #     image_list = list(dfp['Image'])
    #     price_list = list(dfp['price'])
    #     org_price = list(dfp['originalPrice'])
    #     disc_list = list(dfp['markdownPercent'])
    #     dfp['Skus'] = dfp['Skus'].astype('object')
    #     sku_list = list(dfp['Skus'])
    #     url_list = list(dfp['url'])
    #     clicked_sku, counter_dict = clickcounter(image_list, sku_list, price_list, disc_list, org_price, url_list, product_list)
    #     return clicked_sku, counter_dict

    # Main Program
    # st.set_page_config('Product Recommender System', layout='wide')
    st.title('Product Recommender System')
    st.markdown('''<pre style="text-align:center">
    <strong><span style="color:#6a8759">
    It will take as inputs: Keyword and Publisher ID. 
    Displays (upto) Top 5 Recommendations &amp; Collects Click Information. <br><br> </span></strong></pre>''',
                unsafe_allow_html=True)

    # Generating Session ID:
    if 'store' not in st.session_state:
        st.session_state.store = False

        try:
            df_session = pd.read_excel('df_session.xlsx')
            df_row = pd.DataFrame({'ID': uuid.uuid4()}, index=[0])
            df_session = pd.concat([df_session, df_row], ignore_index=True)
            df_session.to_excel('df_session.xlsx', index=False)
            df_sku = pd.DataFrame({'SessionID': pd.Series(dtype='object'), 'Keyword': pd.Series(dtype='object'),
                                   'Skus': pd.Series(dtype='object'),
                                   'Count': pd.Series(dtype='int')})  # Initializing the SKU-Count DataFrame
            df_sku.to_excel('df_sku.xlsx', index=False)

        except FileNotFoundError:
            df_session = pd.DataFrame({'ID': uuid.uuid4()}, index=[0])  # Initializing the SKU-Count DataFrame
            df_session.to_excel('df_session.xlsx', index=False)

    df_session = pd.read_excel('df_session.xlsx')
    session_id = list(df_session['ID'])[-1]
    # st.sidebar.write(session_id) # Uncomment to display the Session ID

    # Inputs

    # selected_keyword = st.sidebar.text_input("Enter a single word as Keyword: ", 'aquaman')
    # publisher_id = st.sidebar.text_input("Enter Publisher ID: ", '725895')
    list_keywords = []
    list_publisherid = []
    for file in os.listdir('bizrate'):
        keyword_publisherid = file.replace(".xml", "")
        list_keywords.append(keyword_publisherid.split("_")[0])
        list_publisherid.append(keyword_publisherid.split("_")[1])
    # list_keywords = ['aquaman', 'superman', 'batman', 'shoes', 'electronics', 'wallet', 'movies', 'books']  # Temporary
    list_publisherid = ['726189']  # For the time being Publisher ID is being HardCoded.
    selected_keyword = st.sidebar.selectbox("Select a Keyword:", set(sorted(list_keywords)))
    publisher_id = st.sidebar.selectbox("Select a Publisher ID:", set(list_publisherid))

    # st.write(selected_keyword)
    # st.write(publisher_id)

    # Query clickReport.db, aggregate clicks and sort most clicked
    clickreport_df = query_table('clickReport', 'clickReport')
    clicked_df = clickreport_df[clickreport_df['keyword'] == selected_keyword]
    clicked_df = clicked_df[['keyword', 'Skus', 'clicks']].groupby(['keyword', 'Skus']).sum().reset_index()
    clicked_df = clicked_df.sort_values(by='clicks', ascending=False)
    to_display_df = clicked_df.copy()
    clicked_df = clicked_df[['Skus', 'clicks']]
    print("LINE 202: Most Clicked: \n {}".format(clicked_df.head()))
    # Query Recommended Data as per Keyword and Publisher ID

    try:
        rec_df = query_table('RecSysData', selected_keyword + "_" + publisher_id)
        rec_df = pd.merge(clicked_df, rec_df, how='right', on=['Skus'])
        rec_df = rec_df.sort_values(by='clicks', ascending=False)
        print("LINE 209: \n {}".format(rec_df.head()))
        print("LINE 210: \n {}".format(rec_df.columns))
    except pd.errors.DatabaseError:
        # st.error('This Keyword Publisher ID Combo Doesnt Exist!')
        rec_df = pd.DataFrame({}, columns=['title', 'Brand', 'url', 'Image', 'Skus', 'price', 'originalPrice',
                                           'markdownPercent', 'totalPrice', 'condition', 'stock', 'relevancy'])
        rec_df = pd.merge(clicked_df, rec_df, how='left', on=['Skus'])
        rec_df = rec_df.sort_values(by='clicks', ascending=False)

    # Logic to Decide which SKU's to Display

    # 1. If a SKU has already been clicked on. It cannot be displayed again.

    try:
        click_data_df = query_table('session_data', 'session_data')

        if click_data_df.empty:
            # df_top_rec = rec_df.head(5)
            rec_df = rec_df.head(5)
        else:
            displayed_skus = list(click_data_df[click_data_df['session_id'] == session_id][
                                      'Skus'])  # List of SKU's already displayed in the current session
            # st.write("Clicked SKUs in this Session: ")
            # st.write(displayed_skus)
            rec_df = rec_df[~rec_df['Skus'].isin(displayed_skus)]
    except pd.errors.DatabaseError as e:
        print(e)

    # Top 5 Recommendations
    # top_df = rec_df.head(5).reset_index()
    try:
        top_df = rec_df.head().sample(5).reset_index()  # random 5 recommendations
    except Exception as e:
        # st.error(e)
        top_df = rec_df.head(5).reset_index()

    recs_to_display = 0
    if len(top_df) > 5:
        recs_to_display = st.sidebar.slider('Recommendations to Display', 1, 5)
    elif len(top_df) > 1:
        recs_to_display = st.sidebar.slider('Recommendations to Display', 1, len(top_df), len(top_df))
    else:
        recs_to_display = 1

    # recs_to_display image width dictionary
    image_width_dictionary = {
        5: 200,
        4: 240,
        3: 280,
        2: 320,
        1: 400}

    if recs_to_display > 0:
        idx = 0
        cols = st.columns(recs_to_display)
        for col in cols:
            with col:
                try:
                    title = top_df['title'][idx]
                    img_link = top_df['url'][idx]
                    sku = top_df['Skus'][idx]
                    list_price = top_df['originalPrice'][idx]
                    selling_price = top_df['price'][idx]
                    discount = top_df['markdownPercent'][idx]
                    st.image(top_df['Image'][idx], width=image_width_dictionary[recs_to_display])
                    # st.write('SKU: {}'.format(sku))
                    # st.write('SKU: {}'.format(sku))
                    # st.write('SKU: {}'.format(sku))
                    content = '''<p><strong> <a href={}>{}</a> </strong> <br>
                                    <strong>SKU:</strong> {} <br>
                                    <strong>S.P:</strong> $ {}<br>
                                    <strong>Discount:</strong> % {} <br>
                                    <strong>L.P:</strong> $ {} <br>
                                    </p>'''.format(img_link, title, sku, selling_price, discount, list_price)
                    st.markdown(content, unsafe_allow_html=True)
                    st.button('Select', key=random_string(), on_click=insert_clickdata_table,
                              args=([session_id, selected_keyword, publisher_id, sku, 1]))
                except KeyError:
                    st.info('No more recommendations to display for this Keyword-PublisherID Combo!')
                    st.info('You can search for another keyword or reload the page!')
            idx += 1
    else:
        st.text(
            'No more recommendations to display for this Keyword-PublisherID Combo! You can search for another keyword or reload the page!')

    # Display Click Table showing total clicks and clicks in current session
    st.write("\n")
    st.write("\n")
    st.write("Most Clicked SKUs for keyword : {}".format(selected_keyword))
    st.dataframe(to_display_df.reset_index(drop=True).head(10))
    st.write("Clicked SKUs in this Session: ")
    st.dataframe(click_data_df[click_data_df['session_id'] == session_id].reset_index(drop=True))


def display_analytics():
    import pandas as pd
    import numpy as np
    import requests
    from bs4 import BeautifulSoup
    import urllib.parse
    import os
    import string
    import random

    import time

    import streamlit as st
    import uuid

    import warnings

    warnings.filterwarnings('ignore')

    # custom module
    # from clickcounter import clickcounter
    from folder_management import create_folder, remove_files_folder
    from sqlite_database import create_insert_table, query_table, insert_clickdata_table, check_for_table

    # Main Program
    # st.set_page_config('Analytics', layout='wide')
    st.title('Analytics')

    df = query_table('session_data', 'session_data')
    # print(pd.Timestamp(df['clicked_at'][0]).date())
    df['date'] = df['clicked_at'].map(lambda x: pd.Timestamp(x).date())
    x_col_list = list(df.columns)
    x_col_list.remove('count')
    x_col_list.remove('clicked_at')
    print(x_col_list)
    column = st.selectbox('Select a Dimension:', x_col_list)

    # Grouping the DataFrame
    if column:
        grouped_df = df.groupby([column]).sum().reset_index()
        if column != 'date':
            grouped_df = grouped_df.sort_values(by='count', ascending=False)
        grouped_df.rename(columns={'count': 'clicks'}, inplace=True)
        # st.dataframe(grouped_df.head())
        col1, col2 = st.columns(2)
        with col1:
            # st.line_chart(grouped_df, x=column, y='clicks')
            alt_line_chart = alt.Chart(grouped_df).mark_line(color='#3ac81e').encode(x=column, y='clicks')
            st.altair_chart(alt_line_chart, use_container_width=True)

        with col2:
            # st.bar_chart(grouped_df, x=column, y='clicks')
            alt_bar_chart = alt.Chart(grouped_df).mark_bar(color='#3ac81e').encode(x=column, y='clicks')
            st.altair_chart(alt_bar_chart, use_container_width=True)

    st.title("Top Products")
    agg_df = df[['keyword', 'publisherid', 'Skus', 'count']]
    agg_df.rename(columns={'keyword': 'Keywords', 'publisherid': 'PublisherID', 'count': 'Clicks'}, inplace=True)
    agg_df = agg_df.groupby(['Skus', 'Keywords', 'PublisherID']).sum().reset_index()
    agg_df = agg_df.sort_values(by='Clicks', ascending=False).reset_index(drop=True)
    st.dataframe(agg_df.head(20), width=1000)


create_folder('bizrate')
create_folder('sqlite_databases')

page_names_to_funcs = {
    "β€”": intro,
    "Generate Recommendations": generate_recommendations,
    "Product Recommendations": display_recommendations,
    "Analytics": display_analytics
}

page_name = st.sidebar.selectbox("Choose a Page", page_names_to_funcs.keys())
page_names_to_funcs[page_name]()