Skip to content

Commit

Permalink
Merge pull request #29 from TEAM-7-SAD/new
Browse files Browse the repository at this point in the history
SPD-81 - feat: add the apriori algo and its data visualization on the…
  • Loading branch information
Carl-Tabuso authored May 28, 2024
2 parents e4cfca6 + 21d47bd commit c70acac
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 14 deletions.
99 changes: 99 additions & 0 deletions src/apriori/apriori_algo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import warnings
import mysql.connector
import pandas as pd
from mlxtend.frequent_patterns import apriori, association_rules
import datetime

# Suppress specific warnings
warnings.filterwarnings('ignore', category=DeprecationWarning)

# Database connection details
db_config = {
'user': 'root',
'password': '',
'host': 'localhost',
'database': 'sweet_avenue_db'
}

# Connect to the database
cnx = mysql.connector.connect(**db_config)
cursor = cnx.cursor()

# Create the table if it doesn't exist
create_table_query = """
CREATE TABLE IF NOT EXISTS frequent_items (
id INT AUTO_INCREMENT PRIMARY KEY,
antecedent VARCHAR(255),
consequent VARCHAR(255),
support FLOAT,
confidence FLOAT,
lift FLOAT,
conviction FLOAT
)
"""
cursor.execute(create_table_query)

# Fetch transaction data for today
today = datetime.datetime.now().strftime('2024-05-01') # Corrected the date format
query = """
SELECT ip.transaction_id, d.name AS item_name
FROM items_purchased ip
JOIN drink_item d ON ip.item_id = d.id
JOIN transaction t ON ip.transaction_id = t.id
WHERE DATE(t.timestamp) = %s
UNION
SELECT ip.transaction_id, f.name AS item_name
FROM items_purchased ip
JOIN food_item f ON ip.item_id = f.id
JOIN transaction t ON ip.transaction_id = t.id
WHERE DATE(t.timestamp) = %s
"""
cursor.execute(query, (today, today))
rows = cursor.fetchall()

# Convert data to a DataFrame
df = pd.DataFrame(rows, columns=['transaction_id', 'item_name'])

# Create the basket format needed for Apriori
basket = df.pivot_table(index='transaction_id', columns='item_name', aggfunc=len, fill_value=0)

# Debug: Print the basket DataFrame
print("Basket DataFrame:")
print(basket.head())

# Run Apriori algorithm with lower min_support
freq_items = apriori(basket, min_support=0.5, use_colnames=True)

# Debug: Print the frequent itemsets DataFrame
print("Frequent Itemsets DataFrame:")
print(freq_items.head())

# Check if freq_items is empty
if freq_items.empty:
print("No frequent itemsets found. Adjust the min_support value or check the data.")
else:
# Run association rules
rules = association_rules(freq_items, metric="conviction", min_threshold=0.01)

# Filter out rules with inf values for conviction
rules = rules.replace([float('inf'), -float('inf')], float('nan')).dropna(subset=['conviction'])
rules = rules.sort_values('conviction', ascending=False)

# Debug: Print the rules DataFrame
print("Association Rules DataFrame:")
print(rules.head())

# Insert results into the database
cursor.execute("TRUNCATE TABLE frequent_items")
insert_query = "INSERT INTO frequent_items (antecedent, consequent, support, confidence, lift, conviction) VALUES (%s, %s, %s, %s, %s, %s)"
for _, row in rules.iterrows():
antecedents = ', '.join(list(row['antecedents']))
consequents = ', '.join(list(row['consequents']))
cursor.execute(insert_query, (antecedents, consequents, row['support'], row['confidence'], row['lift'], row['conviction']))

# Commit the transaction
cnx.commit()

# Close the cursor and connection
cursor.close()
cnx.close()
72 changes: 59 additions & 13 deletions src/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
<link rel="stylesheet" href="styles/main.css" />
<!--Site Icon-->
<link rel="icon" href="images/sweet-avenue-logo.png" type="image/png"/>
<link rel="stylesheet" href="styles/main.scss" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">

<style>
.card-gradient {
Expand Down Expand Up @@ -223,24 +225,56 @@
</div>

<!-- Third Quarter: Larger Container -->
<div class="col-md-6 mt-2"> <!-- Increased py-4 for more padding -->
<div class="col-md-12 mb-3 bg-rose-white rounded-3 p-4" style="box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); height: 410px;"> <!-- Added box-shadow style for drop shadow -->
<div class="col-md-12 mt-2"> <!-- Increased py-4 for more padding -->
<div class="col-md-12 mb-3 bg-rose-white rounded-3 p-4" style="box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); height: 390px;"> <!-- Added box-shadow style for drop shadow -->
<!-- Larger Container 2 -->
<div class="p-2 mb-2 fw-bold text-uppercase text-muted">
weekly top sold products
</div>
<div id="chartdiv1"></div>
<div class="table-container">
<table id="example" class="styled-table">
<thead>
<tr>
<th>Top Pick</th>
<th></th>
<th>Popular Combo</th>
</tr>
</thead>
<tbody>
<?php
// Run the apriori_algo.py script
$output = shell_exec('python apriori/apriori_algo.py 2>&1');

// Fetch the specific item with ID 1 from the database
$sql = "SELECT antecedent, consequent FROM frequent_items WHERE id = 1";
$result = $db->query($sql);

if ($row = $result->fetch_assoc()) {
echo "<tr>
<td>
<div class='product-info'>
<img class='pt-2 card-img-top' src='images/coffee-img-placeholder.png'>
<span class='spaced-text'>" . htmlspecialchars($row["antecedent"]) . "</span>
</div>
</td>
<td class='plus-sign'>+</td>
<td>
<div class='product-info'>
<img class='pt-2 card-img-top' src='images/coffee-img-placeholder.png'>
<span class='spaced-text'>" . htmlspecialchars($row["consequent"]) . "</span>
</div>
</td>
</tr>";
}

$db->close();
?>
</tbody>
</table>
</div>
</div>

<!-- Fourth Quarter: Larger Container -->
<div class="col-md-6 mt-2"> <!-- Increased py-4 for more padding -->
<div class="col-md-12 mb-3 bg-rose-white rounded-3 p-4" style="box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); height: 410px;"> <!-- Added box-shadow style for drop shadow -->
<!-- Larger Container 3 -->
<div class="p-2 mb-2 fw-bold text-uppercase text-muted fs-6">
weekly top sold category
</div>
<div id="chartdiv2"></div>

</div>
</div>
</div>
Expand All @@ -250,7 +284,19 @@
<!--Bootstrap JavaScript-->
<script src="../vendor/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="javascript/index.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://cdn.datatables.net/2.0.3/js/dataTables.js"></script>
<script src="https://cdn.datatables.net/2.0.3/js/dataTables.bootstrap5.js"></script>
<script src="script_save_product.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.2/js/dataTables.buttons.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.2/js/buttons.dataTables.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.2/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.2/js/buttons.print.min.js"></script>
<script src="javascript/preloader.js"></script>


</body>
</html>
76 changes: 75 additions & 1 deletion src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,79 @@ $theme-colors: map-merge($theme-colors, $custom-colors);
--bs-btn-active-border-color: #C57C47;
}

.table-container {
width: 100%;
overflow-x: hidden;
background-color: #FFF0E9; /* Set to match the table background */
padding: 0; /* Remove any padding */
margin: 0; /* Remove any margin */
}

.styled-table {
width: 100%;
border-collapse: collapse;
font-size: 0.9em;
font-family: 'Montserrat', sans-serif;
background-color: #FFF0E9; /* Changed background color */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.599);
text-align: center;
margin: 0; /* Ensure no extra margin */
}

.styled-table thead tr {
background-color: #FFF0E9; /* Changed background color */
color: #343a40;
}

.styled-table th,
.styled-table td {
padding: 5px 5px;
text-align: center;
background-color: #FFF0E9;
}

.styled-table tbody tr {
border-bottom: 1px solid #FFF0E9;
background-color: #FFF0E9;
}

.styled-table tbody tr:nth-of-type(even) {
background-color: #FFF0E9;
}

.styled-table tbody tr:last-of-type {
border-bottom: none;
background-color: #FFF0E9;
}

.styled-table tbody tr.active-row {
font-weight: bold;
color: #343a40;
}

.plus-sign {
font-weight: bold;
font-size: 5em;
}

.product-info {
display: flex;
flex-direction: column;
align-items: center;
}

.product-info img {
width: 200px; /* Set a fixed width to make the image square */
height: 200px; /* Set a fixed height to make the image square */
border-radius: 15px; /* Adjust as needed for rounded corners */
object-fit: cover; /* Ensure the image covers the square area without distortion */
}

.spaced-text {
margin-top: 20px; /* Adjust this value as needed for more or less space */
display: block;
}

.font-13 {
font-size: 13px;
}
Expand Down Expand Up @@ -191,4 +264,5 @@ $theme-colors: map-merge($theme-colors, $custom-colors);
font-weight: 600;
position: relative;
left: -28px;
}
}

0 comments on commit c70acac

Please sign in to comment.