Added version 4
This commit is contained in:
BIN
jokes-bot-v3.0/.DS_Store → jokes_bot/.DS_Store
vendored
BIN
jokes-bot-v3.0/.DS_Store → jokes_bot/.DS_Store
vendored
Binary file not shown.
207
jokes_bot/README.md
Normal file
207
jokes_bot/README.md
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# Step-by-Step Complete Setup Guide
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before starting, ensure you have Python 3.x installed on your system.
|
||||||
|
|
||||||
|
## Check Your Python Installation
|
||||||
|
|
||||||
|
Open PowerShell or Terminal:
|
||||||
|
|
||||||
|
Press Windows + R, type `powershell`, press Enter (on Windows)
|
||||||
|
|
||||||
|
Check Python Version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python --version
|
||||||
|
# Should show: Python 3.x.x
|
||||||
|
|
||||||
|
# If that doesn't work, try:
|
||||||
|
python3 --version
|
||||||
|
# Or on some systems:
|
||||||
|
py --version
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create Your Project Folder
|
||||||
|
|
||||||
|
Organize your files properly from the start.
|
||||||
|
|
||||||
|
Open PowerShell, Terminal, or Command Prompt:
|
||||||
|
|
||||||
|
Make sure you're not in the Python shell (should see C:\> or PS C:\>).
|
||||||
|
|
||||||
|
Navigate to Desktop or Documents:
|
||||||
|
|
||||||
|
Let's create a folder on your Desktop for easy access:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Go to Desktop (Windows)
|
||||||
|
cd Desktop
|
||||||
|
|
||||||
|
# Create a new folder for your project
|
||||||
|
mkdir project_folder
|
||||||
|
|
||||||
|
# Go into your new folder
|
||||||
|
cd project_folder
|
||||||
|
|
||||||
|
# Verify you're in the right place
|
||||||
|
pwd
|
||||||
|
# Should show: C:\Users\YourName\Desktop\project_folder
|
||||||
|
# Or use 'ls' to see files (should be empty)
|
||||||
|
ls
|
||||||
|
```
|
||||||
|
|
||||||
|
**Best Practice:** Keep all related files in one folder for easy management.
|
||||||
|
|
||||||
|
## Set Up Virtual Environment (venv)
|
||||||
|
|
||||||
|
Isolate project dependencies for clean development.
|
||||||
|
|
||||||
|
### Why Virtual Environment?
|
||||||
|
|
||||||
|
- Keeps project dependencies separate
|
||||||
|
- Avoids version conflicts between projects
|
||||||
|
- Makes sharing and deployment easier
|
||||||
|
|
||||||
|
### Create Virtual Environment:
|
||||||
|
|
||||||
|
Make sure you're in your [project_folder](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict/Year/2025/ai/ai6/ai6-m3/ai6-m3/jokes_bot/v4.0/database..py#L1-L45), then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create virtual environment named 'venv'
|
||||||
|
python -m venv venv
|
||||||
|
|
||||||
|
# or
|
||||||
|
|
||||||
|
python3 -m venv venv
|
||||||
|
|
||||||
|
# Check if venv folder was created
|
||||||
|
ls
|
||||||
|
# You should see a 'venv' folder in the list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Activate Virtual Environment:
|
||||||
|
|
||||||
|
#### On Windows (PowerShell):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
venv\Scripts\Activate.ps1
|
||||||
|
# If you get an error about execution policy, run this first:
|
||||||
|
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
venv\Scripts\Activate.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
#### On Windows (Command Prompt):
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
venv\Scripts\activate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### On Mac/Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Indicator:** You should see `(venv)` at the start of your command line.
|
||||||
|
|
||||||
|
## Install Required Libraries
|
||||||
|
|
||||||
|
Get the Python packages needed for this project.
|
||||||
|
|
||||||
|
First, activate your venv:
|
||||||
|
|
||||||
|
Make sure you see `(venv)` before the prompt.
|
||||||
|
|
||||||
|
Install required packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install the required library
|
||||||
|
pip install package-name==version.number
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
pip show package-name
|
||||||
|
# Should show the installed version
|
||||||
|
```
|
||||||
|
|
||||||
|
Create Requirements File:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip freeze > requirements.txt
|
||||||
|
|
||||||
|
# View the requirements file
|
||||||
|
type requirements.txt
|
||||||
|
# (Mac/Linux: use 'cat requirements.txt' instead of 'type')
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why this matters:** Anyone can install exact same versions with `pip install -r requirements.txt`
|
||||||
|
|
||||||
|
## Using IDLE Editor
|
||||||
|
|
||||||
|
To open Python IDLE editor:
|
||||||
|
|
||||||
|
### On Windows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Launch IDLE (blank new file)
|
||||||
|
py -m idlelib.idle
|
||||||
|
|
||||||
|
# OR (depending on your Python installation)
|
||||||
|
python -m idlelib.idle
|
||||||
|
|
||||||
|
# Open an existing file
|
||||||
|
py -m idlelib.idle "C:\path\to\your\file.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Mac:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Launch IDLE (blank new file)
|
||||||
|
python3 -m idlelib.idle
|
||||||
|
|
||||||
|
# OR (if installed)
|
||||||
|
idle3
|
||||||
|
|
||||||
|
# Open an existing file
|
||||||
|
python3 -m idlelib.idle ~/path/to/your/file.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Launch IDLE (blank new file)
|
||||||
|
python3 -m idlelib.idle
|
||||||
|
|
||||||
|
# OR (if installed)
|
||||||
|
idle3
|
||||||
|
|
||||||
|
# Open an existing file
|
||||||
|
python3 -m idlelib.idle /path/to/your/file.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Copy Existing Code
|
||||||
|
|
||||||
|
Start with our working code and modify it.
|
||||||
|
|
||||||
|
### Create main file:
|
||||||
|
|
||||||
|
In your [project_folder](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict/Year/2025/ai/ai6/ai6-m3/ai6-m3/jokes_bot/v4.0/database..py#L1-L45), create a new file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using Python IDLE or any text editor:
|
||||||
|
notepad app.py
|
||||||
|
# (Or use VS Code, Sublime Text, or Python's IDLE)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Expected Folder Structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
project_folder/
|
||||||
|
├── app.py # Main file
|
||||||
|
├── requirements.txt # Python dependencies
|
||||||
|
└── venv/ # Virtual environment
|
||||||
|
```
|
||||||
|
|
||||||
|
## Final Steps
|
||||||
|
|
||||||
|
Once you have completed all the steps above, you'll have a properly configured Python development environment ready for your project. Remember to always activate your virtual environment (`source venv/bin/activate` on Mac/Linux or `venv\Scripts\Activate.ps1` on Windows) before starting work on your project.
|
||||||
Binary file not shown.
Binary file not shown.
BIN
jokes_bot/v4.0/.DS_Store
vendored
Normal file
BIN
jokes_bot/v4.0/.DS_Store
vendored
Normal file
Binary file not shown.
969
jokes_bot/v4.0/AI Joke Bot v2 - Community Ratings Added!.html
Normal file
969
jokes_bot/v4.0/AI Joke Bot v2 - Community Ratings Added!.html
Normal file
@@ -0,0 +1,969 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- saved from url=(0063)file:///Users/home/Downloads/deepseek_html_20260130_cd57ee.html -->
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>AI Joke Bot v2 - Community Ratings Added!</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 30px 40px;
|
||||||
|
margin: 10px 0;
|
||||||
|
display: none;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 82vh;
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide.active {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #2c3e50;
|
||||||
|
font-size: 2.2rem;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #2c3e50;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #2c3e50;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lesson-title {
|
||||||
|
color: #2980b9;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subject-topic {
|
||||||
|
color: #27ae60;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subject-title {
|
||||||
|
text-align: center;
|
||||||
|
color: #7f8c8d;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 15px 0;
|
||||||
|
color: #34495e;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
margin: 15px 0 20px 30px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #34495e;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rules-container {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 25px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-left: 4px solid #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outcomes-container {
|
||||||
|
background-color: #e8f4fd;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 25px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why-container {
|
||||||
|
background-color: #f0f7ff;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 25px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal {
|
||||||
|
background-color: #2c3e50;
|
||||||
|
color: #ecf0f1;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
margin: 20px 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-command {
|
||||||
|
color: #2ecc71;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-comment {
|
||||||
|
color: #95a5a6;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
font-weight: 500;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
background-color: #bdc3c7;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-counter {
|
||||||
|
text-align: center;
|
||||||
|
color: #7f8c8d;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #7f8c8d;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: #f1f2f3;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-box {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-demo {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-item {
|
||||||
|
text-align: center;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.positive {
|
||||||
|
background-color: #d4edda;
|
||||||
|
border: 2px solid #c3e6cb;
|
||||||
|
color: #155724;
|
||||||
|
}
|
||||||
|
|
||||||
|
.neutral {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
border: 2px solid #ffeaa7;
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
|
||||||
|
.negative {
|
||||||
|
background-color: #f8d7da;
|
||||||
|
border: 2px solid #f5c6cb;
|
||||||
|
color: #721c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simple-explanation {
|
||||||
|
background-color: #e8f4fd;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-left: 5px solid #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.simple-explanation h3 {
|
||||||
|
color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.analogy-box {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border: 2px dashed #f39c12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cool-fact {
|
||||||
|
background-color: #d5f4e6;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 15px 0;
|
||||||
|
border-left: 4px solid #27ae60;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comparison-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comparison-table th, .comparison-table td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comparison-table th {
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comparison-table tr:nth-child(even) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.database-diagram {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border: 2px solid #3498db;
|
||||||
|
font-family: monospace;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating-demo {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating-button {
|
||||||
|
font-size: 2rem;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating-button:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.upvote {
|
||||||
|
background-color: #d4edda;
|
||||||
|
color: #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.neutral-vote {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
color: #ffc107;
|
||||||
|
}
|
||||||
|
|
||||||
|
.downvote {
|
||||||
|
background-color: #f8d7da;
|
||||||
|
color: #dc3545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-box {
|
||||||
|
background-color: #e3f2fd;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border: 2px solid #2196f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
height: calc(100vh - 40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide {
|
||||||
|
padding: 20px 25px;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lesson-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subject-topic {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, ul, ol {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-demo, .rating-demo {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-item {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="slide-counter" id="slide-counter">Slide 1 of 12</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<!-- Slide 1: Title Slide -->
|
||||||
|
<div class="slide active" id="slide1">
|
||||||
|
<div style="flex: 1; display: flex; flex-direction: column; justify-content: center;">
|
||||||
|
<div class="ai-icon">🤖✨</div>
|
||||||
|
<div class="lesson-title">Joke Bot v2.0 Launch!</div>
|
||||||
|
<div class="subject-topic">AI + Community = Super Smart Bot!</div>
|
||||||
|
<div class="subject-title">Now with community ratings and smarter AI!</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn1" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn1">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 2: Rules -->
|
||||||
|
<div class="slide" id="slide2">
|
||||||
|
<h2>Class Rules</h2>
|
||||||
|
|
||||||
|
<div class="rules-container">
|
||||||
|
<h3>How to Earn Points Today:</h3>
|
||||||
|
|
||||||
|
<p><strong>+2 Points</strong> - You're here and ready to learn!</p>
|
||||||
|
<p><strong>+1 Point</strong> - You listen during instruction</p>
|
||||||
|
<p><strong>+1 Point</strong> - You try all the activities</p>
|
||||||
|
<p><strong>+1 Point</strong> - You complete all the work</p>
|
||||||
|
|
||||||
|
<div class="cool-fact">
|
||||||
|
<p><strong>✨ Cool Fact:</strong> You helped build this bot! Your ratings make it smarter!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn2" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn2">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 3: Learning Outcomes -->
|
||||||
|
<div class="slide" id="slide3">
|
||||||
|
<h2>What's New in v2.0?</h2>
|
||||||
|
<p class="subject-title">Our joke bot got a MAJOR upgrade!</p>
|
||||||
|
|
||||||
|
<div class="outcomes-container">
|
||||||
|
<ol>
|
||||||
|
<li><strong>🎭 Community Voting:</strong> Rate jokes with 👍, 👎, or 😐</li>
|
||||||
|
<li><strong>🧠 AI vs Humans:</strong> Compare computer guesses with real votes</li>
|
||||||
|
<li><strong>🗳️ Many-to-One:</strong> Many people can rate each joke</li>
|
||||||
|
<li><strong>📊 Smart Statistics:</strong> See what jokes are REALLY popular</li>
|
||||||
|
<li><strong>💾 Database Upgrade:</strong> New table for storing all votes</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<p><strong>🎮 Think of it like this:</strong> Our joke bot was good, but now it's like adding multiplayer mode to a game!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn3" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn3">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 4: The Big Upgrade -->
|
||||||
|
<div class="slide" id="slide4">
|
||||||
|
<h2>The Big Upgrade: Community Ratings!</h2>
|
||||||
|
|
||||||
|
<div class="simple-explanation">
|
||||||
|
<h3>v1.0: Just AI Guesses</h3>
|
||||||
|
<p>Old system: Only the computer guessed if jokes were funny.</p>
|
||||||
|
<div class="sentiment-demo">
|
||||||
|
<div class="sentiment-item positive">
|
||||||
|
<h4>AI Says: 😊 Positive</h4>
|
||||||
|
<p>"Why don't eggs tell jokes?"</p>
|
||||||
|
<small>Score: +0.90</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="feature-box">
|
||||||
|
<h3>v2.0: AI + REAL People!</h3>
|
||||||
|
<p>New system: Both computer AND humans vote on jokes!</p>
|
||||||
|
|
||||||
|
<div class="rating-demo">
|
||||||
|
<div class="rating-button upvote">👍 85%</div>
|
||||||
|
<div class="rating-button neutral-vote">😐 10%</div>
|
||||||
|
<div class="rating-button downvote">👎 5%</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><strong>Example Joke:</strong> "Why don't scientists trust atoms?"</p>
|
||||||
|
<p><strong>AI Thinks:</strong> 😊 Positive (Score: +0.75)</p>
|
||||||
|
<p><strong>Community Says:</strong> 👍 92% funny! (46 votes)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cool-fact">
|
||||||
|
<p><strong>🤯 Mind Blown Fact:</strong> This is how YouTube, TikTok, and Netflix work - they combine AI guesses with real user ratings!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn4" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn4">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 5: How It Works Now -->
|
||||||
|
<div class="slide" id="slide5">
|
||||||
|
<h2>Try It Yourself! 🎯</h2>
|
||||||
|
|
||||||
|
<div class="simple-explanation">
|
||||||
|
<h3>Step-by-Step Demo:</h3>
|
||||||
|
<ol>
|
||||||
|
<li><strong>Step 1:</strong> Bot shows you a joke</li>
|
||||||
|
<li><strong>Step 2:</strong> You see AI's guess (😊/😐/😒)</li>
|
||||||
|
<li><strong>Step 3:</strong> YOU get to vote! 👍, 👎, or 😐</li>
|
||||||
|
<li><strong>Step 4:</strong> Your vote gets saved with everyone else's</li>
|
||||||
|
<li><strong>Step 5:</strong> Next person sees the community score</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="community-box">
|
||||||
|
<h3>📱 What You See Now:</h3>
|
||||||
|
<div style="background-color: #2c3e50; color: white; padding: 20px; border-radius: 8px; margin: 15px 0;">
|
||||||
|
<p>🤣 "Why don't eggs tell jokes? They'd crack each other up!"</p>
|
||||||
|
<p>🤖 AI Mood: 😊 Positive (Score: +0.90)</p>
|
||||||
|
<p>👥 Community Rating: 👍 85% | 😐 10% | 👎 5%</p>
|
||||||
|
<p>🗳️ 124 people voted</p>
|
||||||
|
<hr style="margin: 15px 0; border-color: #444;">
|
||||||
|
<p><strong>Was this joke funny to YOU?</strong></p>
|
||||||
|
<p>1. 👍 Upvote 2. 😐 Neutral 3. 👎 Downvote</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<p><strong>💡 This is like:</strong> YouTube comments + TikTok likes + Netflix ratings all in one joke bot!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn5" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn5">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 6: Database Upgrade -->
|
||||||
|
<div class="slide" id="slide6">
|
||||||
|
<h2>Behind the Scenes: Database Magic 🗄️</h2>
|
||||||
|
|
||||||
|
<div class="simple-explanation">
|
||||||
|
<h3>OLD Database (v1.0):</h3>
|
||||||
|
<div class="database-diagram">
|
||||||
|
jokes table:
|
||||||
|
├── id
|
||||||
|
├── joke_text
|
||||||
|
├── contributor
|
||||||
|
├── published_date
|
||||||
|
├── ai_score ← Only AI's guess
|
||||||
|
└── ai_mood_label
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="feature-box">
|
||||||
|
<h3>NEW Database (v2.0):</h3>
|
||||||
|
<div class="database-diagram" style="background-color: #e8f4fd; border-color: #2196f3;">
|
||||||
|
jokes table: user_sentiments table:
|
||||||
|
├── id ├── id
|
||||||
|
├── joke_text ├── joke_id → Links to jokes
|
||||||
|
├── contributor ├── user_name
|
||||||
|
├── published_date ├── sentiment → 'up','down','neutral'
|
||||||
|
├── ai_score ← AI's guess └── timestamp
|
||||||
|
└── ai_mood_label └── ← MANY votes per joke!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<h3>🧩 Many-to-One Relationship:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><strong>One Joke</strong> can have <strong>MANY votes</strong></li>
|
||||||
|
<li>Like one YouTube video → many likes/comments</li>
|
||||||
|
<li>Like one TikTok → many hearts</li>
|
||||||
|
<li>This is called a "foreign key" relationship</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn6" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn6">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 7: The New Code -->
|
||||||
|
<div class="slide" id="slide7">
|
||||||
|
<h2>The Smart New Code ✨</h2>
|
||||||
|
|
||||||
|
<div class="content-container">
|
||||||
|
<h3>1. New Database Table:</h3>
|
||||||
|
<div class="terminal">
|
||||||
|
<span class="terminal-command">CREATE TABLE user_sentiments (</span>
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
joke_id INTEGER, <span class="terminal-comment"># Which joke</span>
|
||||||
|
user_name TEXT, <span class="terminal-comment"># Who voted</span>
|
||||||
|
sentiment TEXT, <span class="terminal-comment"># 'up','down','neutral'</span>
|
||||||
|
timestamp TEXT, <span class="terminal-comment"># When they voted</span>
|
||||||
|
FOREIGN KEY (joke_id) REFERENCES jokes(id) <span class="terminal-comment"># The magic link!</span>
|
||||||
|
<span class="terminal-command">);</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>2. Asking for Your Vote:</h3>
|
||||||
|
<div class="terminal">
|
||||||
|
<span class="terminal-comment"># After showing a joke...</span>
|
||||||
|
print("🤣 Why don't eggs tell jokes? They'd crack each other up!")
|
||||||
|
print("🤖 AI thinks: 😊 Positive (Score: +0.90)")
|
||||||
|
|
||||||
|
<span class="terminal-comment"># Get community rating</span>
|
||||||
|
<span class="terminal-command">community_score = get_community_rating(joke_id)</span>
|
||||||
|
print(f"👥 Community: 👍 {community_score['up']}%")
|
||||||
|
|
||||||
|
<span class="terminal-comment"># Ask for YOUR vote!</span>
|
||||||
|
print("🗳️ Was this funny to YOU?")
|
||||||
|
print("1. 👍 Upvote 2. 😐 Neutral 3. 👎 Downvote")
|
||||||
|
<span class="terminal-command">user_choice = input("Your choice: ")</span>
|
||||||
|
|
||||||
|
<span class="terminal-comment"># Save your vote</span>
|
||||||
|
<span class="terminal-command">save_user_vote(joke_id, your_name, user_choice)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cool-fact">
|
||||||
|
<p><strong>⚡ Pro Tip:</strong> The "FOREIGN KEY" is what links votes to specific jokes. It's like adding @mentions in social media!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn7" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn7">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 8: AI vs Humans - The Battle! -->
|
||||||
|
<div class="slide" id="slide8">
|
||||||
|
<h2>AI vs Humans - The Showdown! 🥊</h2>
|
||||||
|
|
||||||
|
<div class="simple-explanation">
|
||||||
|
<h3>Now We Can Compare:</h3>
|
||||||
|
<table class="comparison-table">
|
||||||
|
<tbody><tr>
|
||||||
|
<th>Joke</th>
|
||||||
|
<th>🤖 AI Guesses</th>
|
||||||
|
<th>👥 Humans Vote</th>
|
||||||
|
<th>Who's Right?</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"Why don't scientists trust atoms?"</td>
|
||||||
|
<td>😊 Positive (+0.75)</td>
|
||||||
|
<td>👍 92% funny</td>
|
||||||
|
<td>✅ Both agree!</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"Parallel lines have so much in common..."</td>
|
||||||
|
<td>😒 Negative (-0.35)</td>
|
||||||
|
<td>👍 78% funny</td>
|
||||||
|
<td>❌ AI wrong!</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"I told my computer I needed a break..."</td>
|
||||||
|
<td>😐 Neutral (0.05)</td>
|
||||||
|
<td>👎 65% not funny</td>
|
||||||
|
<td>❌ AI wrong!</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<h3>🎯 What This Teaches Us:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><strong>AI gets it right sometimes</strong> - Good at obvious jokes</li>
|
||||||
|
<li><strong>AI gets it wrong sometimes</strong> - Bad at sarcasm/complex jokes</li>
|
||||||
|
<li><strong>Humans are better judges</strong> - We understand context</li>
|
||||||
|
<li><strong>Community voting is powerful</strong> - Wisdom of the crowd!</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cool-fact">
|
||||||
|
<p><strong>🧠 Real AI Learning:</strong> Some AI systems use human votes like this to LEARN and get better! Your votes could train future AI!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn8" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn8">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 9: Real-World Examples -->
|
||||||
|
<div class="slide" id="slide9">
|
||||||
|
<h2>Where You've Seen This Before 🎬</h2>
|
||||||
|
|
||||||
|
<div class="simple-explanation">
|
||||||
|
<h3>Everywhere! This is how real apps work:</h3>
|
||||||
|
|
||||||
|
<div class="sentiment-demo">
|
||||||
|
<div class="sentiment-item positive" style="text-align: left;">
|
||||||
|
<h4>📱 YouTube</h4>
|
||||||
|
<p>👍👎 buttons</p>
|
||||||
|
<p>Comments + AI recommendations</p>
|
||||||
|
<small>Exactly like our joke bot!</small>
|
||||||
|
</div>
|
||||||
|
<div class="sentiment-item neutral" style="text-align: left;">
|
||||||
|
<h4>📸 TikTok/Instagram</h4>
|
||||||
|
<p>❤️ hearts = upvotes</p>
|
||||||
|
<p>AI suggests videos you'll like</p>
|
||||||
|
<small>Community + AI working together</small>
|
||||||
|
</div>
|
||||||
|
<div class="sentiment-item negative" style="text-align: left;">
|
||||||
|
<h4>🎮 Online Games</h4>
|
||||||
|
<p>Report systems</p>
|
||||||
|
<p>Player ratings</p>
|
||||||
|
<small>Community moderation</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="community-box">
|
||||||
|
<h3>🎯 The Big Idea:</h3>
|
||||||
|
<p><strong>Modern apps = AI + Community Feedback</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>AI starts the guess</strong> (like our TextBlob sentiment)</li>
|
||||||
|
<li><strong>Humans give feedback</strong> (your 👍/👎 votes)</li>
|
||||||
|
<li><strong>System gets smarter</strong> (learns from both)</li>
|
||||||
|
<li><strong>Better experience for everyone!</strong></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cool-fact">
|
||||||
|
<p><strong>🚀 Career Connection:</strong> Knowing how to build AI + community systems is a SUPER valuable skill for app developers!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn9" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn9">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 10: What You Built -->
|
||||||
|
<div class="slide" id="slide10">
|
||||||
|
<h2>What YOU Built Today 🏗️</h2>
|
||||||
|
|
||||||
|
<div class="content-container">
|
||||||
|
<p>Think about it - you helped build a system that:</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li><strong>🤖 Uses AI</strong> to analyze text feelings</li>
|
||||||
|
<li><strong>🗳️ Collects community votes</strong> from real people</li>
|
||||||
|
<li><strong>💾 Stores everything</strong> in a smart database</li>
|
||||||
|
<li><strong>🔗 Links votes to jokes</strong> with foreign keys</li>
|
||||||
|
<li><strong>📊 Shows statistics</strong> comparing AI vs humans</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="feature-box">
|
||||||
|
<p><strong>🌟 That's Professional-Level Work!</strong></p>
|
||||||
|
<p>Companies build apps the exact same way:</p>
|
||||||
|
<ul>
|
||||||
|
<li>YouTube = videos + likes/dislikes</li>
|
||||||
|
<li>Amazon = products + star ratings</li>
|
||||||
|
<li>Netflix = shows + thumbs up/down</li>
|
||||||
|
<li><strong>Our Joke Bot = jokes + 👍/👎 ratings!</strong></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<p><strong>💪 You're Not Just Learning - You're Building Real Stuff!</strong></p>
|
||||||
|
<p>The skills you learned today (AI + databases + user feedback) are exactly what tech companies look for!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn10" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn10">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 11: Next Steps & Ideas -->
|
||||||
|
<div class="slide" id="slide11">
|
||||||
|
<h2>What Could We Build Next? 🚀</h2>
|
||||||
|
|
||||||
|
<div class="content-container">
|
||||||
|
<h3>Discussion Time:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>What jokes did the AI get totally wrong? Why?</li>
|
||||||
|
<li>Should some people's votes count more? (Like joke experts?)</li>
|
||||||
|
<li>What if we could "train" the AI with our votes?</li>
|
||||||
|
<li>Could we predict which jokes will be popular?</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<h3>🎯 Cool Extension Ideas:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Personalized Jokes:</strong> "Show me jokes that people LIKE ME enjoyed!"</li>
|
||||||
|
<li><strong>Joke Leaderboard:</strong> Top 10 most-liked jokes</li>
|
||||||
|
<li><strong>AI Trainer:</strong> Use votes to make TextBlob smarter</li>
|
||||||
|
<li><strong>Meme Version:</strong> Same system but for memes!</li>
|
||||||
|
<li><strong>Class Poll System:</strong> Use this code for classroom votes</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="community-box">
|
||||||
|
<h3>🧠 The Real Magic:</h3>
|
||||||
|
<p>You now have a template for ANY voting system:</p>
|
||||||
|
<p>Song ratings, game reviews, teacher feedback, club elections...</p>
|
||||||
|
<p><strong>Change the jokes to something else, keep the voting system!</strong></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn11" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn11">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 12: Thank You -->
|
||||||
|
<div class="slide" id="slide12">
|
||||||
|
<div class="content-container">
|
||||||
|
<div class="ai-icon">🤖👥✨</div>
|
||||||
|
<h1>You Built Version 2.0!</h1>
|
||||||
|
|
||||||
|
<div class="analogy-box">
|
||||||
|
<p><strong>🎯 Remember What You Accomplished:</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li>Started with basic joke storage (v1.0)</li>
|
||||||
|
<li>Added AI mood detection (v1.5)</li>
|
||||||
|
<li>Now added COMMUNITY voting (v2.0!)</li>
|
||||||
|
<li>You built a system used by billion-dollar companies</li>
|
||||||
|
<li>You understand AI + Human collaboration</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cool-fact">
|
||||||
|
<p><strong>📈 Career Superpower:</strong> You now know how to build interactive, community-driven, AI-enhanced apps. That's literally what modern software development is all about!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="margin-top: 30px;"><strong>Next Challenge:</strong> Can we make the AI LEARN from our votes? 🤔</p>
|
||||||
|
|
||||||
|
<p style="margin-top: 30px; color: #7f8c8d;">
|
||||||
|
ICT & Digital Technologies<br>
|
||||||
|
Year 9 - Building Real Apps
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button id="prevBtn12" disabled="">Previous</button>
|
||||||
|
<button id="nextBtn12">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// ==================== CONFIGURATION ====================
|
||||||
|
const totalSlides = 12;
|
||||||
|
// =======================================================
|
||||||
|
|
||||||
|
let currentSlide = 1;
|
||||||
|
|
||||||
|
// Update slide counter
|
||||||
|
function updateSlideCounter() {
|
||||||
|
document.getElementById('slide-counter').textContent = `Slide ${currentSlide} of ${totalSlides}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slide navigation
|
||||||
|
function showSlide(slideNumber) {
|
||||||
|
// Hide all slides
|
||||||
|
for (let i = 1; i <= totalSlides; i++) {
|
||||||
|
const slide = document.getElementById(`slide${i}`);
|
||||||
|
if (slide) {
|
||||||
|
slide.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show current slide
|
||||||
|
const currentSlideElement = document.getElementById(`slide${slideNumber}`);
|
||||||
|
if (currentSlideElement) {
|
||||||
|
currentSlideElement.classList.add('active');
|
||||||
|
currentSlide = slideNumber;
|
||||||
|
updateSlideCounter();
|
||||||
|
|
||||||
|
// Update button states
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateButtons() {
|
||||||
|
// Update previous button
|
||||||
|
const prevButtons = document.querySelectorAll('[id^="prevBtn"]');
|
||||||
|
prevButtons.forEach(btn => {
|
||||||
|
btn.disabled = currentSlide === 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update next button text on last slide
|
||||||
|
const nextButtons = document.querySelectorAll('[id^="nextBtn"]');
|
||||||
|
nextButtons.forEach(btn => {
|
||||||
|
if (currentSlide === totalSlides) {
|
||||||
|
btn.textContent = 'Mission Complete! 🎉';
|
||||||
|
} else {
|
||||||
|
btn.textContent = 'Next';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next button functionality
|
||||||
|
document.querySelectorAll('[id^="nextBtn"]').forEach(button => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
if (currentSlide < totalSlides) {
|
||||||
|
showSlide(currentSlide + 1);
|
||||||
|
} else {
|
||||||
|
// Last slide - completion message
|
||||||
|
alert('🎉 INCREDIBLE WORK! You understand AI + Community systems - exactly how real apps work! Keep building amazing things! 🚀');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Previous button functionality
|
||||||
|
document.querySelectorAll('[id^="prevBtn"]').forEach(button => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
if (currentSlide > 1) {
|
||||||
|
showSlide(currentSlide - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize the presentation
|
||||||
|
updateSlideCounter();
|
||||||
|
updateButtons();
|
||||||
|
|
||||||
|
// Keyboard navigation
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'PageDown') {
|
||||||
|
if (currentSlide < totalSlides) {
|
||||||
|
showSlide(currentSlide + 1);
|
||||||
|
}
|
||||||
|
} else if (e.key === 'ArrowLeft' || e.key === 'PageUp') {
|
||||||
|
if (currentSlide > 1) {
|
||||||
|
showSlide(currentSlide - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize to first slide
|
||||||
|
showSlide(1);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
124
jokes_bot/v4.0/README.md
Normal file
124
jokes_bot/v4.0/README.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# AI-Enhanced Joke Bot v4.0
|
||||||
|
|
||||||
|
Welcome to the AI-Enhanced Joke Bot! This application combines humor with artificial intelligence to deliver jokes and analyze their sentiment.
|
||||||
|
|
||||||
|
## 📋 Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
v4.0/
|
||||||
|
├── database.py # Creates the SQLite database and jokes table with user sentiment tracking
|
||||||
|
├── jokes.py # Main application with AI sentiment analysis and user rating
|
||||||
|
├── jokes.db # SQLite database containing jokes and user sentiments
|
||||||
|
├── sample_data.sql # Sample jokes to populate the database
|
||||||
|
├── populate_db.py # Script to populate the database with sample data
|
||||||
|
├── check_db.py # Utility to check database content
|
||||||
|
├── upgrade_db.py # Utility to upgrade existing databases with new schema
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### 1. Install Dependencies
|
||||||
|
|
||||||
|
First, make sure you have Python installed and then install the required packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create and activate virtual environment (recommended)
|
||||||
|
python -m venv venv
|
||||||
|
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
pip install textblob
|
||||||
|
|
||||||
|
# Download required corpora for textblob
|
||||||
|
python -m textblob.download_corpora
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Set Up the Database
|
||||||
|
|
||||||
|
Run the database creation script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python database.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates the `jokes.db` file with the proper table structure, including a table for user sentiments.
|
||||||
|
|
||||||
|
### 3. (Optional) Upgrade Existing Database
|
||||||
|
|
||||||
|
If you have an existing database from a previous version, run the upgrade script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python upgrade_db.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This adds the `user_sentiments` table to your existing database.
|
||||||
|
|
||||||
|
### 4. Populate the Database with Sample Jokes
|
||||||
|
|
||||||
|
To add sample jokes to your database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python populate_db.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can use the SQL file directly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sqlite3 jokes.db < sample_data.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Run the Application
|
||||||
|
|
||||||
|
Start the Joke Bot:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python jokes.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Troubleshooting
|
||||||
|
|
||||||
|
### No Jokes in Database
|
||||||
|
|
||||||
|
If you're getting "No jokes in the database" message:
|
||||||
|
|
||||||
|
1. Make sure you've run `python database.py` to create the database
|
||||||
|
2. Run `python populate_db.py` to add sample jokes to the database
|
||||||
|
3. Verify the database content with `python check_db.py`
|
||||||
|
|
||||||
|
### Missing Dependencies
|
||||||
|
|
||||||
|
If you get an ImportError for textblob:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install textblob
|
||||||
|
python -m textblob.download_corpora
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Features
|
||||||
|
|
||||||
|
- **Random Joke Generator**: Get a random joke from the database
|
||||||
|
- **AI Sentiment Analysis**: Analyzes the sentiment of jokes using TextBlob
|
||||||
|
- **User Sentiment Rating**: After each joke, rate it with thumbs up/down/neutral
|
||||||
|
- **Community Ratings**: See how other users rated each joke
|
||||||
|
- **Mood-Based Joke Selection**: Filter jokes by sentiment (positive, negative, neutral)
|
||||||
|
- **Add New Jokes**: Contribute your own jokes to the database
|
||||||
|
- **Joke Management**: View all jokes in the database with community ratings
|
||||||
|
|
||||||
|
## 💡 Usage Tips
|
||||||
|
|
||||||
|
- Choose option 1 to get a random joke, then rate it with U(p)/D(own)/N(eutral)
|
||||||
|
- Choose option 2 to add a new joke with automatic sentiment analysis and rating
|
||||||
|
- Choose option 3 to analyze the sentiment of any text
|
||||||
|
- Choose option 4 to get jokes based on mood
|
||||||
|
- Choose option 5 to view all jokes in the database with community ratings
|
||||||
|
- Choose option 6 to exit the application
|
||||||
|
|
||||||
|
## 🗂️ Database Schema
|
||||||
|
|
||||||
|
The application uses two tables:
|
||||||
|
|
||||||
|
- `jokes`: Contains the joke text, contributor, publication date, and AI-analyzed sentiment
|
||||||
|
- `user_sentiments`: Tracks user ratings for each joke with timestamps
|
||||||
|
|
||||||
|
Enjoy the AI-enhanced humor experience with community feedback!
|
||||||
67
jokes_bot/v4.0/check_db.py
Normal file
67
jokes_bot/v4.0/check_db.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Simple script to check the content of the jokes database
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
|
||||||
|
def check_database():
|
||||||
|
db_path = 'jokes.db'
|
||||||
|
|
||||||
|
if not os.path.exists(db_path):
|
||||||
|
print(f"❌ Database {db_path} does not exist!")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"🔍 Checking database: {db_path}")
|
||||||
|
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Count the number of jokes in the database
|
||||||
|
cursor.execute('SELECT COUNT(*) FROM jokes')
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
|
print(f"📊 Total jokes in database: {count}")
|
||||||
|
|
||||||
|
# Count the number of user sentiments
|
||||||
|
cursor.execute('SELECT COUNT(*) FROM user_sentiments')
|
||||||
|
sentiment_count = cursor.fetchone()[0]
|
||||||
|
print(f"📊 Total user sentiments recorded: {sentiment_count}")
|
||||||
|
|
||||||
|
# If there are jokes, show a few of them
|
||||||
|
if count > 0:
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT j.id, j.joke, j.contributor, j.sentiment_label,
|
||||||
|
(SELECT COUNT(*) FROM user_sentiments us WHERE us.joke_id = j.id) as sentiment_count
|
||||||
|
FROM jokes j
|
||||||
|
LIMIT 5
|
||||||
|
''')
|
||||||
|
jokes = cursor.fetchall()
|
||||||
|
print('\n📋 Sample of jokes in the database:')
|
||||||
|
for i, (joke_id, joke, contributor, sentiment, sentiment_count) in enumerate(jokes, 1):
|
||||||
|
print(f'{i:2d}. [{sentiment}] {joke[:60]}...')
|
||||||
|
print(f' 👤 {contributor} | {sentiment_count} user ratings')
|
||||||
|
|
||||||
|
# Show AI sentiment distribution
|
||||||
|
cursor.execute('SELECT sentiment_label, COUNT(*) FROM jokes GROUP BY sentiment_label')
|
||||||
|
distribution = cursor.fetchall()
|
||||||
|
print(f'\n📈 AI Sentiment distribution:')
|
||||||
|
for label, cnt in distribution:
|
||||||
|
print(f' {label}: {cnt} jokes')
|
||||||
|
|
||||||
|
# Show user sentiment distribution if any exist
|
||||||
|
if sentiment_count > 0:
|
||||||
|
cursor.execute('SELECT user_sentiment, COUNT(*) FROM user_sentiments GROUP BY user_sentiment')
|
||||||
|
user_distribution = cursor.fetchall()
|
||||||
|
print(f'\n👥 User Sentiment distribution:')
|
||||||
|
for sentiment, cnt in user_distribution:
|
||||||
|
emoji = {'up': '👍', 'down': '👎', 'neutral': '😐'}[sentiment]
|
||||||
|
print(f' {emoji} {sentiment.capitalize()}: {cnt} ratings')
|
||||||
|
else:
|
||||||
|
print("\n📭 No jokes found in the database!")
|
||||||
|
print("💡 Run populate_db.py to add sample jokes to the database.")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
check_database()
|
||||||
22
jokes_bot/v4.0/clean_sample_data.sql
Normal file
22
jokes_bot/v4.0/clean_sample_data.sql
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
-- Insert 20 dummy jokes with various sentiments
|
||||||
|
INSERT INTO jokes (joke, contributor, published, sentiment_score, sentiment_label) VALUES
|
||||||
|
('Why don''t scientists trust atoms? Because they make up everything!', 'ScienceFan', '2024-01-15 10:30:00', 0.75, '😊 Positive'),
|
||||||
|
('I told my wife she was drawing her eyebrows too high. She looked surprised.', 'Joker123', '2024-01-16 14:20:00', 0.35, '😊 Positive'),
|
||||||
|
('Why did the scarecrow win an award? He was outstanding in his field!', 'FarmLife', '2024-01-17 09:15:00', 0.65, '😊 Positive'),
|
||||||
|
('What do you call a fish with no eyes? Fsh!', 'MarineBio', '2024-01-18 16:45:00', 0.25, '😊 Positive'),
|
||||||
|
('I''m reading a book on anti-gravity. It''s impossible to put down!', 'PhysicsNerd', '2024-01-19 11:30:00', 0.45, '😊 Positive'),
|
||||||
|
('Why did the computer go to the doctor? Because it had a virus.', 'TechSupport', '2024-01-20 13:10:00', 0.05, '😐 Neutral'),
|
||||||
|
('What do you call a bear with no teeth? A gummy bear.', 'WildlifeFan', '2024-01-21 15:25:00', 0.08, '😐 Neutral'),
|
||||||
|
('Why did the bicycle fall over? Because it was two-tired.', 'Cyclist', '2024-01-22 10:00:00', -0.02, '😐 Neutral'),
|
||||||
|
('What do you call a sleeping bull? A bulldozer.', 'Cowboy', '2024-01-23 14:35:00', 0.03, '😐 Neutral'),
|
||||||
|
('Why did the math book look so sad? Because it had too many problems.', 'Student', '2024-01-24 09:50:00', -0.05, '😐 Neutral'),
|
||||||
|
('I used to play piano by ear, but now I use my hands.', 'Musician', '2024-01-25 12:15:00', -0.15, '😒 Negative'),
|
||||||
|
('I told my computer I needed a break, and now it won''t stop sending me Kit-Kat ads.', 'OfficeWorker', '2024-01-26 16:30:00', -0.25, '😒 Negative'),
|
||||||
|
('Parallel lines have so much in common. It''s a shame they''ll never meet.', 'MathTeacher', '2024-01-27 11:40:00', -0.35, '😒 Negative'),
|
||||||
|
('My wife told me to stop impersonating a flamingo. I had to put my foot down.', 'Husband', '2024-01-28 14:55:00', -0.20, '😒 Negative'),
|
||||||
|
('I told my girlfriend she drew her eyebrows too high. She seemed surprised.', 'Boyfriend', '2024-01-29 10:10:00', -0.30, '😒 Negative'),
|
||||||
|
('What''s orange and sounds like a parrot? A carrot!', 'Vegetarian', '2024-01-30 13:20:00', 0.85, '😊 Positive'),
|
||||||
|
('Why don''t eggs tell jokes? They''d crack each other up!', 'Chef', '2024-01-31 15:45:00', 0.90, '😊 Positive'),
|
||||||
|
('I invented a new word: Plagiarism!', 'Writer', '2024-02-01 09:30:00', 0.78, '😊 Positive'),
|
||||||
|
('Why did the golfer bring two pairs of pants? In case he got a hole in one!', 'Golfer', '2024-02-02 12:15:00', 0.82, '😊 Positive'),
|
||||||
|
('What do you call a fake noodle? An impasta!', 'ItalianFood', '2024-02-03 14:40:00', 0.88, '😊 Positive');
|
||||||
27
jokes_bot/v4.0/database.py
Normal file
27
jokes_bot/v4.0/database.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# database.py
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
conn = sqlite3.connect('jokes.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''CREATE TABLE IF NOT EXISTS jokes (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
joke TEXT NOT NULL,
|
||||||
|
contributor TEXT NOT NULL,
|
||||||
|
published TEXT NOT NULL,
|
||||||
|
sentiment_score REAL DEFAULT 0.0,
|
||||||
|
sentiment_label TEXT DEFAULT '😐 Neutral'
|
||||||
|
)''')
|
||||||
|
|
||||||
|
# Create a new table to store user sentiments for each joke
|
||||||
|
cursor.execute('''CREATE TABLE IF NOT EXISTS user_sentiments (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
joke_id INTEGER NOT NULL,
|
||||||
|
user_sentiment TEXT CHECK(user_sentiment IN ('up', 'down', 'neutral')) DEFAULT 'neutral',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (joke_id) REFERENCES jokes(id) ON DELETE CASCADE
|
||||||
|
)''')
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
print("✅ Database and tables created successfully with AI sentiment columns and user sentiment tracking!")
|
||||||
|
conn.close()
|
||||||
74
jokes_bot/v4.0/debug_db.py
Normal file
74
jokes_bot/v4.0/debug_db.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# debug_db.py
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
|
||||||
|
def check_database():
|
||||||
|
print("🔍 DATABASE DEBUG CHECK")
|
||||||
|
print("=" * 40)
|
||||||
|
|
||||||
|
# Check current directory
|
||||||
|
print(f"📁 Current directory: {os.getcwd()}")
|
||||||
|
print(f"📁 Database file exists: {os.path.exists('jokes.db')}")
|
||||||
|
|
||||||
|
if not os.path.exists('jokes.db'):
|
||||||
|
print("❌ ERROR: jokes.db file not found in current directory!")
|
||||||
|
print("💡 Try running: python3 database.py first")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Connect to database
|
||||||
|
conn = sqlite3.connect('jokes.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
print("✅ Connected to database successfully")
|
||||||
|
|
||||||
|
# Check what tables exist
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
||||||
|
tables = cursor.fetchall()
|
||||||
|
print(f"\n📋 Tables found: {[table[0] for table in tables]}")
|
||||||
|
|
||||||
|
if 'jokes' not in [table[0] for table in tables]:
|
||||||
|
print("❌ ERROR: 'jokes' table not found!")
|
||||||
|
print("💡 Try running: python3 database.py to create the table")
|
||||||
|
conn.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check number of jokes
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM jokes")
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
|
print(f"📊 Total jokes in database: {count}")
|
||||||
|
|
||||||
|
if count == 0:
|
||||||
|
print("⚠️ WARNING: Database is empty!")
|
||||||
|
print("💡 Load sample data with: sqlite3 jokes.db < sample_data.sql")
|
||||||
|
else:
|
||||||
|
# Show some sample data
|
||||||
|
print("\n🔍 Sample jokes (first 3):")
|
||||||
|
print("-" * 50)
|
||||||
|
cursor.execute("SELECT id, joke, contributor, sentiment_label FROM jokes LIMIT 3")
|
||||||
|
jokes = cursor.fetchall()
|
||||||
|
|
||||||
|
for joke in jokes:
|
||||||
|
print(f"\nID: {joke[0]}")
|
||||||
|
print(f"Joke: {joke[1]}")
|
||||||
|
print(f"Contributor: {joke[2]}")
|
||||||
|
print(f"Mood: {joke[3]}")
|
||||||
|
print("-" * 30)
|
||||||
|
|
||||||
|
# Check column names
|
||||||
|
print("\n📝 Table structure:")
|
||||||
|
cursor.execute("PRAGMA table_info(jokes)")
|
||||||
|
columns = cursor.fetchall()
|
||||||
|
for col in columns:
|
||||||
|
print(f" {col[1]} ({col[2]})")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
print("\n✅ Debug check completed!")
|
||||||
|
|
||||||
|
except sqlite3.Error as e:
|
||||||
|
print(f"❌ SQLite error: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ General error: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
check_database()
|
||||||
BIN
jokes_bot/v4.0/jokes.db
Normal file
BIN
jokes_bot/v4.0/jokes.db
Normal file
Binary file not shown.
288
jokes_bot/v4.0/jokes.py
Normal file
288
jokes_bot/v4.0/jokes.py
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
# jokes_v4.py
|
||||||
|
import sqlite3
|
||||||
|
import random
|
||||||
|
from datetime import datetime
|
||||||
|
from textblob import TextBlob # Simple NLP library
|
||||||
|
|
||||||
|
def analyze_joke_sentiment(joke_text):
|
||||||
|
"""Use AI to analyze the sentiment of a joke"""
|
||||||
|
analysis = TextBlob(joke_text)
|
||||||
|
polarity = analysis.sentiment.polarity
|
||||||
|
|
||||||
|
if polarity > 0.1:
|
||||||
|
label = "😊 Positive"
|
||||||
|
elif polarity < -0.1:
|
||||||
|
label = "😒 Negative"
|
||||||
|
else:
|
||||||
|
label = "😐 Neutral"
|
||||||
|
|
||||||
|
return polarity, label
|
||||||
|
|
||||||
|
def get_user_sentiment_for_joke(db, joke_id):
|
||||||
|
"""Get the average user sentiment for a specific joke"""
|
||||||
|
cursor = db.execute('''
|
||||||
|
SELECT
|
||||||
|
CASE
|
||||||
|
WHEN AVG(CASE WHEN user_sentiment = 'up' THEN 1
|
||||||
|
WHEN user_sentiment = 'down' THEN -1
|
||||||
|
ELSE 0 END) > 0.1 THEN '👍 Up'
|
||||||
|
WHEN AVG(CASE WHEN user_sentiment = 'up' THEN 1
|
||||||
|
WHEN user_sentiment = 'down' THEN -1
|
||||||
|
ELSE 0 END) < -0.1 THEN '👎 Down'
|
||||||
|
ELSE '😐 Neutral'
|
||||||
|
END as avg_sentiment,
|
||||||
|
COUNT(*) as total_votes
|
||||||
|
FROM user_sentiments
|
||||||
|
WHERE joke_id = ?
|
||||||
|
''', (joke_id,))
|
||||||
|
|
||||||
|
result = cursor.fetchone()
|
||||||
|
avg_sentiment, total_votes = result
|
||||||
|
return avg_sentiment, total_votes
|
||||||
|
|
||||||
|
def add_user_sentiment(db, joke_id, user_choice):
|
||||||
|
"""Add user sentiment for a specific joke"""
|
||||||
|
try:
|
||||||
|
db.execute('''
|
||||||
|
INSERT INTO user_sentiments (joke_id, user_sentiment)
|
||||||
|
VALUES (?, ?)
|
||||||
|
''', (joke_id, user_choice))
|
||||||
|
db.commit()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error saving sentiment: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
db = sqlite3.connect('jokes.db')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
print("\n" + "="*30)
|
||||||
|
print("🤖 AI-ENHANCED JOKE BOT 🤖")
|
||||||
|
print("="*30)
|
||||||
|
print("1. Get random joke")
|
||||||
|
print("2. Add new joke")
|
||||||
|
print("3. Analyze joke sentiment")
|
||||||
|
print("4. Get joke by mood")
|
||||||
|
print("5. View all jokes with sentiment")
|
||||||
|
print("6. Quit")
|
||||||
|
|
||||||
|
choice = input("\nYour choice: ").strip()
|
||||||
|
|
||||||
|
if choice == "1":
|
||||||
|
# Get random joke with sentiment info
|
||||||
|
cursor = db.execute('''
|
||||||
|
SELECT id, joke, contributor, published, sentiment_label
|
||||||
|
FROM jokes
|
||||||
|
ORDER BY RANDOM()
|
||||||
|
LIMIT 1
|
||||||
|
''')
|
||||||
|
joke_data = cursor.fetchone()
|
||||||
|
|
||||||
|
if joke_data:
|
||||||
|
joke_id, joke, contributor, published, sentiment = joke_data
|
||||||
|
print(f"\n🤣 {joke}")
|
||||||
|
print(f" 👤 Contributor: {contributor}")
|
||||||
|
print(f" 📅 Published: {published}")
|
||||||
|
print(f" 🧠 AI Mood Analysis: {sentiment}")
|
||||||
|
|
||||||
|
# Get and display user sentiment stats
|
||||||
|
avg_sentiment, total_votes = get_user_sentiment_for_joke(db, joke_id)
|
||||||
|
if total_votes > 0:
|
||||||
|
print(f" 👥 Community Rating: {avg_sentiment} ({total_votes} votes)")
|
||||||
|
|
||||||
|
# Ask user for their sentiment
|
||||||
|
print(f"\n🎯 Rate this joke: 👍 (U)p, 👎 (D)own, or (N)eutral?")
|
||||||
|
user_input = input("Your choice (u/d/n): ").strip().lower()
|
||||||
|
|
||||||
|
if user_input in ['u', 'up']:
|
||||||
|
user_choice = 'up'
|
||||||
|
elif user_input in ['d', 'down']:
|
||||||
|
user_choice = 'down'
|
||||||
|
else:
|
||||||
|
user_choice = 'neutral'
|
||||||
|
|
||||||
|
if add_user_sentiment(db, joke_id, user_choice):
|
||||||
|
print(f"✅ Your rating ({'👍 Up' if user_choice == 'up' else '👎 Down' if user_choice == 'down' else '😐 Neutral'}) recorded!")
|
||||||
|
else:
|
||||||
|
print("❌ Could not save your rating.")
|
||||||
|
else:
|
||||||
|
print("📭 No jokes in the database yet!")
|
||||||
|
|
||||||
|
elif choice == "2":
|
||||||
|
new_joke = input("Enter your joke: ").strip()
|
||||||
|
if not new_joke:
|
||||||
|
print("❌ Joke cannot be empty!")
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = input("Your name (or press Enter for 'Anonymous'): ").strip() or "Anonymous"
|
||||||
|
|
||||||
|
# AI Analysis
|
||||||
|
score, label = analyze_joke_sentiment(new_joke)
|
||||||
|
print(f"\n🤖 AI Analysis Results:")
|
||||||
|
print(f" Sentiment Score: {score:.2f}")
|
||||||
|
print(f" Mood Label: {label}")
|
||||||
|
|
||||||
|
# Get current date/time
|
||||||
|
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO jokes (joke, contributor, published, sentiment_score, sentiment_label)
|
||||||
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
''', (new_joke, name, current_time, score, label))
|
||||||
|
|
||||||
|
# Get the ID of the newly inserted joke
|
||||||
|
new_joke_id = cursor.lastrowid
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
print("✅ Joke saved with AI analysis!")
|
||||||
|
|
||||||
|
# Ask user for their sentiment on the new joke
|
||||||
|
print(f"\n🎯 Rate your own joke: 👍 (U)p, 👎 (D)own, or (N)eutral?")
|
||||||
|
user_input = input("Your choice (u/d/n): ").strip().lower()
|
||||||
|
|
||||||
|
if user_input in ['u', 'up']:
|
||||||
|
user_choice = 'up'
|
||||||
|
elif user_input in ['d', 'down']:
|
||||||
|
user_choice = 'down'
|
||||||
|
else:
|
||||||
|
user_choice = 'neutral'
|
||||||
|
|
||||||
|
if add_user_sentiment(db, new_joke_id, user_choice):
|
||||||
|
print(f"✅ Your rating ({'👍 Up' if user_choice == 'up' else '👎 Down' if user_choice == 'down' else '😐 Neutral'}) recorded!")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error saving joke: {e}")
|
||||||
|
|
||||||
|
elif choice == "3":
|
||||||
|
joke_text = input("Enter a joke to analyze: ").strip()
|
||||||
|
if joke_text:
|
||||||
|
score, label = analyze_joke_sentiment(joke_text)
|
||||||
|
print(f"\n📊 AI Analysis Results:")
|
||||||
|
print(f" Joke: '{joke_text}'")
|
||||||
|
print(f" Sentiment Score: {score:.2f}")
|
||||||
|
print(f" Mood Label: {label}")
|
||||||
|
|
||||||
|
# Interpretation
|
||||||
|
print(f"\n📈 Interpretation:")
|
||||||
|
if score > 0.5:
|
||||||
|
print(" Very positive joke! 😄")
|
||||||
|
elif score > 0.1:
|
||||||
|
print(" Positive joke! 😊")
|
||||||
|
elif score < -0.5:
|
||||||
|
print(" Very negative/sarcastic joke! 😠")
|
||||||
|
elif score < -0.1:
|
||||||
|
print(" Negative joke! 😒")
|
||||||
|
else:
|
||||||
|
print(" Neutral joke! 😐")
|
||||||
|
else:
|
||||||
|
print("❌ Please enter a joke to analyze.")
|
||||||
|
|
||||||
|
elif choice == "4":
|
||||||
|
print("\n🎭 Choose mood:")
|
||||||
|
print("1. 😊 Positive jokes")
|
||||||
|
print("2. 😒 Negative jokes")
|
||||||
|
print("3. 😐 Neutral jokes")
|
||||||
|
print("4. 😄 Very positive jokes (score > 0.5)")
|
||||||
|
print("5. 😠 Very negative jokes (score < -0.5)")
|
||||||
|
|
||||||
|
mood_choice = input("Your choice: ").strip()
|
||||||
|
|
||||||
|
mood_queries = {
|
||||||
|
"1": ("😊 Positive", "sentiment_label = '😊 Positive'"),
|
||||||
|
"2": ("😒 Negative", "sentiment_label = '😒 Negative'"),
|
||||||
|
"3": ("😐 Neutral", "sentiment_label = '😐 Neutral'"),
|
||||||
|
"4": ("😄 Very Positive", "sentiment_score > 0.5"),
|
||||||
|
"5": ("😠 Very Negative", "sentiment_score < -0.5")
|
||||||
|
}
|
||||||
|
|
||||||
|
if mood_choice in mood_queries:
|
||||||
|
mood_name, query = mood_queries[mood_choice]
|
||||||
|
|
||||||
|
cursor = db.execute(f'''
|
||||||
|
SELECT id, joke, contributor, sentiment_score
|
||||||
|
FROM jokes
|
||||||
|
WHERE {query}
|
||||||
|
ORDER BY RANDOM()
|
||||||
|
LIMIT 1
|
||||||
|
''')
|
||||||
|
|
||||||
|
joke_data = cursor.fetchone()
|
||||||
|
|
||||||
|
if joke_data:
|
||||||
|
joke_id, joke, contributor, score = joke_data
|
||||||
|
print(f"\n{mood_name} joke:")
|
||||||
|
print(f"🤣 {joke}")
|
||||||
|
print(f" 👤 Contributor: {contributor}")
|
||||||
|
print(f" 📊 Sentiment Score: {score:.2f}")
|
||||||
|
|
||||||
|
# Get and display user sentiment stats
|
||||||
|
avg_sentiment, total_votes = get_user_sentiment_for_joke(db, joke_id)
|
||||||
|
if total_votes > 0:
|
||||||
|
print(f" 👥 Community Rating: {avg_sentiment} ({total_votes} votes)")
|
||||||
|
|
||||||
|
# Ask user for their sentiment
|
||||||
|
print(f"\n🎯 Rate this joke: 👍 (U)p, 👎 (D)own, or (N)eutral?")
|
||||||
|
user_input = input("Your choice (u/d/n): ").strip().lower()
|
||||||
|
|
||||||
|
if user_input in ['u', 'up']:
|
||||||
|
user_choice = 'up'
|
||||||
|
elif user_input in ['d', 'down']:
|
||||||
|
user_choice = 'down'
|
||||||
|
else:
|
||||||
|
user_choice = 'neutral'
|
||||||
|
|
||||||
|
if add_user_sentiment(db, joke_id, user_choice):
|
||||||
|
print(f"✅ Your rating ({'👍 Up' if user_choice == 'up' else '👎 Down' if user_choice == 'down' else '😐 Neutral'}) recorded!")
|
||||||
|
else:
|
||||||
|
print(f"📭 No {mood_name.lower()} jokes yet!")
|
||||||
|
else:
|
||||||
|
print("❌ Invalid choice!")
|
||||||
|
|
||||||
|
elif choice == "5":
|
||||||
|
print("\n📋 ALL JOKES IN DATABASE:")
|
||||||
|
print("-" * 70)
|
||||||
|
|
||||||
|
cursor = db.execute('''
|
||||||
|
SELECT j.id, j.joke, j.contributor, j.sentiment_label, j.sentiment_score
|
||||||
|
FROM jokes j
|
||||||
|
ORDER BY j.id DESC
|
||||||
|
''')
|
||||||
|
|
||||||
|
jokes = cursor.fetchall()
|
||||||
|
|
||||||
|
if jokes:
|
||||||
|
for i, (joke_id, joke, contributor, label, score) in enumerate(jokes, 1):
|
||||||
|
print(f"\n{i}. {joke}")
|
||||||
|
print(f" 👤 {contributor} | AI: {label} | Score: {score:.2f}")
|
||||||
|
|
||||||
|
# Get and display user sentiment stats
|
||||||
|
avg_sentiment, total_votes = get_user_sentiment_for_joke(db, joke_id)
|
||||||
|
if total_votes > 0:
|
||||||
|
print(f" 👥 Community Rating: {avg_sentiment} ({total_votes} votes)")
|
||||||
|
|
||||||
|
print(f"\n📊 Total jokes: {len(jokes)}")
|
||||||
|
else:
|
||||||
|
print("📭 No jokes in the database yet!")
|
||||||
|
|
||||||
|
elif choice == "6":
|
||||||
|
print("\n👋 Goodbye! Thanks for using the AI Joke Bot!")
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("❌ Invalid choice. Please select 1-6.")
|
||||||
|
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Check if textblob is installed
|
||||||
|
try:
|
||||||
|
import textblob
|
||||||
|
main()
|
||||||
|
except ImportError:
|
||||||
|
print("❌ ERROR: textblob library is not installed!")
|
||||||
|
print("\n📦 Please install it using:")
|
||||||
|
print(" pip install textblob")
|
||||||
|
print(" python -m textblob.download_corpora")
|
||||||
|
print("\nThen run this script again.")
|
||||||
120
jokes_bot/v4.0/populate_db.py
Normal file
120
jokes_bot/v4.0/populate_db.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script to populate the jokes database with sample data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
|
||||||
|
def populate_database():
|
||||||
|
# Connect to the database
|
||||||
|
db_path = 'jokes.db'
|
||||||
|
if not os.path.exists(db_path):
|
||||||
|
print(f"❌ Database {db_path} does not exist!")
|
||||||
|
print("Please run database.py first to create the database.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Check if jokes table is empty before adding data
|
||||||
|
try:
|
||||||
|
cursor.execute('SELECT COUNT(*) FROM jokes')
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
print("❌ The jokes table does not exist. Please run database.py first.")
|
||||||
|
conn.close()
|
||||||
|
return False
|
||||||
|
|
||||||
|
if count > 0:
|
||||||
|
overwrite = input(f"⚠️ Database already contains {count} jokes. Overwrite? (y/N): ")
|
||||||
|
if overwrite.lower() != 'y':
|
||||||
|
print("❌ Operation cancelled.")
|
||||||
|
conn.close()
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Clear existing data first
|
||||||
|
# Only try to delete from user_sentiments if the table exists
|
||||||
|
try:
|
||||||
|
cursor.execute('DELETE FROM user_sentiments')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
# user_sentiments table doesn't exist, which is OK
|
||||||
|
print("ℹ️ user_sentiments table does not exist yet.")
|
||||||
|
pass
|
||||||
|
cursor.execute('DELETE FROM jokes')
|
||||||
|
|
||||||
|
# Use the clean SQL file without SELECT statements
|
||||||
|
sql_file = 'clean_sample_data.sql'
|
||||||
|
if not os.path.exists(sql_file):
|
||||||
|
print(f"❌ SQL file {sql_file} does not exist!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Execute the clean SQL file directly
|
||||||
|
with open(sql_file, 'r', encoding='utf-8') as f:
|
||||||
|
sql_commands = f.read()
|
||||||
|
|
||||||
|
cursor.executescript(sql_commands)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
print(f"✅ Successfully populated the jokes table with sample jokes!")
|
||||||
|
|
||||||
|
# Count the total number of jokes
|
||||||
|
cursor.execute('SELECT COUNT(*) FROM jokes')
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
|
print(f"📊 Total jokes in database: {count}")
|
||||||
|
|
||||||
|
# Add some sample user sentiments for the first few jokes
|
||||||
|
print("🎯 Adding sample user sentiments...")
|
||||||
|
jokes_with_sentiment = [(1, 'up'), (1, 'up'), (1, 'neutral'),
|
||||||
|
(2, 'down'), (2, 'up'),
|
||||||
|
(3, 'up'), (3, 'up'), (3, 'up')]
|
||||||
|
|
||||||
|
for joke_id, sentiment in jokes_with_sentiment:
|
||||||
|
try:
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO user_sentiments (joke_id, user_sentiment)
|
||||||
|
VALUES (?, ?)
|
||||||
|
''', (joke_id, sentiment))
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
# If user_sentiments table doesn't exist, skip adding sentiments
|
||||||
|
print("ℹ️ Skipping user sentiments as the table doesn't exist yet.")
|
||||||
|
break
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
print(f"✅ Added sample user sentiments for {len(jokes_with_sentiment)} joke entries")
|
||||||
|
|
||||||
|
# Show sentiment distribution
|
||||||
|
cursor.execute('SELECT sentiment_label, COUNT(*) FROM jokes GROUP BY sentiment_label')
|
||||||
|
distribution = cursor.fetchall()
|
||||||
|
print(f'\n📈 AI Sentiment distribution:')
|
||||||
|
for label, cnt in distribution:
|
||||||
|
print(f' {label}: {cnt} jokes')
|
||||||
|
|
||||||
|
# Show user sentiment distribution if the table exists
|
||||||
|
try:
|
||||||
|
cursor.execute('SELECT user_sentiment, COUNT(*) FROM user_sentiments GROUP BY user_sentiment')
|
||||||
|
user_distribution = cursor.fetchall()
|
||||||
|
if user_distribution:
|
||||||
|
print(f'\n👥 User Sentiment distribution:')
|
||||||
|
for sentiment, cnt in user_distribution:
|
||||||
|
emoji = {'up': '👍', 'down': '👎', 'neutral': '😐'}[sentiment]
|
||||||
|
print(f' {emoji} {sentiment.capitalize()}: {cnt} ratings')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
print("\nℹ️ User sentiment table not available yet.")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error executing SQL commands: {e}")
|
||||||
|
conn.rollback()
|
||||||
|
conn.close()
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("🔄 Populating jokes database with sample data...")
|
||||||
|
success = populate_database()
|
||||||
|
if success:
|
||||||
|
print("\n🎉 Database successfully populated! You can now run jokes.py to enjoy the jokes.")
|
||||||
|
else:
|
||||||
|
print("\n💥 Failed to populate the database.")
|
||||||
37
jokes_bot/v4.0/sample_data.sql
Normal file
37
jokes_bot/v4.0/sample_data.sql
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
-- Clear existing data first (optional - uncomment if needed)
|
||||||
|
-- DELETE FROM jokes;
|
||||||
|
|
||||||
|
-- Insert 20 dummy jokes with various sentiments
|
||||||
|
INSERT INTO jokes (joke, contributor, published, sentiment_score, sentiment_label) VALUES
|
||||||
|
('Why don''t scientists trust atoms? Because they make up everything!', 'ScienceFan', '2024-01-15 10:30:00', 0.75, '😊 Positive'),
|
||||||
|
('I told my wife she was drawing her eyebrows too high. She looked surprised.', 'Joker123', '2024-01-16 14:20:00', 0.35, '😊 Positive'),
|
||||||
|
('Why did the scarecrow win an award? He was outstanding in his field!', 'FarmLife', '2024-01-17 09:15:00', 0.65, '😊 Positive'),
|
||||||
|
('What do you call a fish with no eyes? Fsh!', 'MarineBio', '2024-01-18 16:45:00', 0.25, '😊 Positive'),
|
||||||
|
('I''m reading a book on anti-gravity. It''s impossible to put down!', 'PhysicsNerd', '2024-01-19 11:30:00', 0.45, '😊 Positive'),
|
||||||
|
('Why did the computer go to the doctor? Because it had a virus.', 'TechSupport', '2024-01-20 13:10:00', 0.05, '😐 Neutral'),
|
||||||
|
('What do you call a bear with no teeth? A gummy bear.', 'WildlifeFan', '2024-01-21 15:25:00', 0.08, '😐 Neutral'),
|
||||||
|
('Why did the bicycle fall over? Because it was two-tired.', 'Cyclist', '2024-01-22 10:00:00', -0.02, '😐 Neutral'),
|
||||||
|
('What do you call a sleeping bull? A bulldozer.', 'Cowboy', '2024-01-23 14:35:00', 0.03, '😐 Neutral'),
|
||||||
|
('Why did the math book look so sad? Because it had too many problems.', 'Student', '2024-01-24 09:50:00', -0.05, '😐 Neutral'),
|
||||||
|
('I used to play piano by ear, but now I use my hands.', 'Musician', '2024-01-25 12:15:00', -0.15, '😒 Negative'),
|
||||||
|
('I told my computer I needed a break, and now it won''t stop sending me Kit-Kat ads.', 'OfficeWorker', '2024-01-26 16:30:00', -0.25, '😒 Negative'),
|
||||||
|
('Parallel lines have so much in common. It''s a shame they''ll never meet.', 'MathTeacher', '2024-01-27 11:40:00', -0.35, '😒 Negative'),
|
||||||
|
('My wife told me to stop impersonating a flamingo. I had to put my foot down.', 'Husband', '2024-01-28 14:55:00', -0.20, '😒 Negative'),
|
||||||
|
('I told my girlfriend she drew her eyebrows too high. She seemed surprised.', 'Boyfriend', '2024-01-29 10:10:00', -0.30, '😒 Negative'),
|
||||||
|
('What''s orange and sounds like a parrot? A carrot!', 'Vegetarian', '2024-01-30 13:20:00', 0.85, '😊 Positive'),
|
||||||
|
('Why don''t eggs tell jokes? They''d crack each other up!', 'Chef', '2024-01-31 15:45:00', 0.90, '😊 Positive'),
|
||||||
|
('I invented a new word: Plagiarism!', 'Writer', '2024-02-01 09:30:00', 0.78, '😊 Positive'),
|
||||||
|
('Why did the golfer bring two pairs of pants? In case he got a hole in one!', 'Golfer', '2024-02-02 12:15:00', 0.82, '😊 Positive'),
|
||||||
|
('What do you call a fake noodle? An impasta!', 'ItalianFood', '2024-02-03 14:40:00', 0.88, '😊 Positive');
|
||||||
|
|
||||||
|
-- Show total count
|
||||||
|
SELECT '✅ Inserted ' || COUNT(*) || ' jokes!' as message FROM jokes;
|
||||||
|
|
||||||
|
-- Show distribution by sentiment
|
||||||
|
SELECT
|
||||||
|
sentiment_label,
|
||||||
|
COUNT(*) as count,
|
||||||
|
'📊' as chart
|
||||||
|
FROM jokes
|
||||||
|
GROUP BY sentiment_label
|
||||||
|
ORDER BY count DESC;
|
||||||
62
jokes_bot/v4.0/setup_db.py
Normal file
62
jokes_bot/v4.0/setup_db.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Setup script to properly initialize the database following the project specification.
|
||||||
|
This ensures the database has the correct schema and sample data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sqlite3
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def setup_database():
|
||||||
|
db_path = 'jokes.db'
|
||||||
|
|
||||||
|
print("🚀 Starting database setup process...")
|
||||||
|
|
||||||
|
# Step 1: Remove existing database file if it exists
|
||||||
|
if os.path.exists(db_path):
|
||||||
|
print(f"🗑️ Removing existing database: {db_path}")
|
||||||
|
os.remove(db_path)
|
||||||
|
print("✅ Old database removed")
|
||||||
|
else:
|
||||||
|
print("📋 No existing database to remove")
|
||||||
|
|
||||||
|
# Step 2: Create database with correct schema
|
||||||
|
print("\n🔧 Creating database with correct schema...")
|
||||||
|
result = subprocess.run([sys.executable, 'database.py'], capture_output=True, text=True)
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"❌ Error creating database: {result.stderr}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("✅ Database schema created successfully")
|
||||||
|
|
||||||
|
# Step 3: Populate database with sample data
|
||||||
|
print("\n📚 Populating database with sample data...")
|
||||||
|
result = subprocess.run([sys.executable, 'populate_db.py'], capture_output=True, text=True)
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"❌ Error populating database: {result.stderr}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("✅ Database populated with sample data")
|
||||||
|
|
||||||
|
# Step 4: Verify the database
|
||||||
|
print("\n🔍 Verifying database setup...")
|
||||||
|
result = subprocess.run([sys.executable, 'check_db.py'], capture_output=True, text=True)
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"❌ Error verifying database: {result.stderr}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("✅ Database verified successfully")
|
||||||
|
print(result.stdout)
|
||||||
|
|
||||||
|
print("\n🎉 Database setup completed successfully!")
|
||||||
|
print("You can now run 'python jokes.py' to start the Joke Bot.")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
success = setup_database()
|
||||||
|
if not success:
|
||||||
|
print("\n💥 Database setup failed. Please check the errors above.")
|
||||||
|
sys.exit(1)
|
||||||
51
jokes_bot/v4.0/upgrade_db.py
Normal file
51
jokes_bot/v4.0/upgrade_db.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script to upgrade an existing database with the new user_sentiments table.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
|
||||||
|
def upgrade_database():
|
||||||
|
db_path = 'jokes.db'
|
||||||
|
|
||||||
|
if not os.path.exists(db_path):
|
||||||
|
print(f"❌ Database {db_path} does not exist!")
|
||||||
|
print("Please run database.py first to create the database.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Check if user_sentiments table already exists
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='user_sentiments';")
|
||||||
|
table_exists = cursor.fetchone()
|
||||||
|
|
||||||
|
if table_exists:
|
||||||
|
print("✅ Database is already up to date!")
|
||||||
|
conn.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
print("🔄 Upgrading database schema...")
|
||||||
|
|
||||||
|
# Create the user_sentiments table
|
||||||
|
cursor.execute('''CREATE TABLE user_sentiments (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
joke_id INTEGER NOT NULL,
|
||||||
|
user_sentiment TEXT CHECK(user_sentiment IN ('up', 'down', 'neutral')) DEFAULT 'neutral',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (joke_id) REFERENCES jokes(id) ON DELETE CASCADE
|
||||||
|
)''')
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
print("✅ Database upgraded successfully! Added user_sentiments table.")
|
||||||
|
conn.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("🔄 Checking database schema...")
|
||||||
|
success = upgrade_database()
|
||||||
|
if success:
|
||||||
|
print("\n🎉 Database is ready for the enhanced application!")
|
||||||
|
else:
|
||||||
|
print("\n💥 Failed to upgrade the database.")
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user