Updated community sentiment
This commit is contained in:
148
jokes_bot/v4.0/CHANGES_SUMMARY.md
Normal file
148
jokes_bot/v4.0/CHANGES_SUMMARY.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# Joke Bot v4.0 - User Identification Enhancement Summary
|
||||
|
||||
## Overview
|
||||
This enhancement adds user identification to the sentiment tracking system, enabling detailed analytics on who likes which jokes and comprehensive community insights.
|
||||
|
||||
## Key Changes Made
|
||||
|
||||
### 1. Database Schema Enhancement
|
||||
**File Modified:** `jokes.py` (initialize_database function)
|
||||
|
||||
**Changes:**
|
||||
- Added `user_identifier TEXT NOT NULL` column to `user_sentiments` table
|
||||
- Modified sample data to include user identifiers
|
||||
- Updated foreign key constraints to maintain data integrity
|
||||
|
||||
**Before:**
|
||||
```sql
|
||||
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
|
||||
);
|
||||
```
|
||||
|
||||
**After:**
|
||||
```sql
|
||||
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',
|
||||
user_identifier TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (joke_id) REFERENCES jokes(id) ON DELETE CASCADE
|
||||
);
|
||||
```
|
||||
|
||||
### 2. Enhanced Sentiment Functions
|
||||
**File Modified:** `jokes.py`
|
||||
|
||||
**New Functions Added:**
|
||||
- `get_detailed_sentiment_stats(db, joke_id)` - Shows sentiment breakdown by user groups
|
||||
- `get_user_sentiment_history(db, user_identifier)` - Retrieves a user's complete rating history
|
||||
- `get_popular_jokes_by_user(db, user_identifier)` - Shows jokes a specific user has liked
|
||||
- `get_top_users_by_joke_preference(db)` - Community leaderboard showing most positive users
|
||||
- `add_user_sentiment(db, joke_id, user_choice, user_identifier)` - Enhanced to prevent duplicates and allow updates
|
||||
|
||||
**Modified Functions:**
|
||||
- `add_user_sentiment()` now accepts and stores user_identifier
|
||||
- Added logic to update existing ratings instead of creating duplicates
|
||||
|
||||
### 3. Interactive User Experience
|
||||
**File Modified:** `jokes.py` (main function)
|
||||
|
||||
**Enhancements:**
|
||||
- Session-based user identification at startup
|
||||
- Personalized menu options (3-5) for user analytics
|
||||
- Detailed sentiment displays showing community breakdown
|
||||
- Rating history and favorite joke tracking
|
||||
- Community analytics dashboard
|
||||
|
||||
### 4. Documentation Updates
|
||||
**Files Modified:** `README.md`, Created: `CHANGES_SUMMARY.md`
|
||||
|
||||
**Documentation Added:**
|
||||
- Enhanced feature descriptions
|
||||
- New menu option explanations
|
||||
- Usage examples with user identification
|
||||
- Technical improvements section
|
||||
- Benefits of user identification
|
||||
|
||||
### 5. Sample Data Enhancement
|
||||
**File Modified:** `clean_sample_data.sql`
|
||||
|
||||
**Improvements:**
|
||||
- Updated schema definition with user_identifier
|
||||
- More realistic sample user identifiers
|
||||
- Comprehensive verification queries
|
||||
- Community analytics examples
|
||||
|
||||
## New Analytics Capabilities
|
||||
|
||||
### Personal Analytics (Per User)
|
||||
1. **Rating History**: Track all jokes a user has rated with timestamps
|
||||
2. **Favorite Jokes**: See which jokes a user has specifically liked (up votes)
|
||||
3. **Rating Patterns**: Analyze individual user preferences over time
|
||||
|
||||
### Community Analytics
|
||||
1. **User Leaderboard**: Rank users by positivity percentage
|
||||
2. **Engagement Metrics**: Measure user participation levels
|
||||
3. **Sentiment Distribution**: View detailed breakdown of community opinions
|
||||
4. **Contributor Insights**: Identify which joke contributors are most popular
|
||||
|
||||
### Business Intelligence
|
||||
1. **User Segmentation**: Group users by rating patterns
|
||||
2. **Content Performance**: Track which jokes perform best with different user segments
|
||||
3. **Recommendation Engine Foundation**: Data structure ready for personalized joke suggestions
|
||||
4. **Quality Metrics**: Measure joke quality through community consensus
|
||||
|
||||
## Implementation Benefits
|
||||
|
||||
### Technical Advantages
|
||||
- **Data Integrity**: Prevents duplicate ratings while allowing updates
|
||||
- **Scalability**: Efficient querying for large user bases
|
||||
- **Flexibility**: Easy to extend with additional user metadata
|
||||
- **Analytics Ready**: Rich dataset for future enhancements
|
||||
|
||||
### User Experience Improvements
|
||||
- **Personalization**: Users can track their own preferences
|
||||
- **Transparency**: Clear visibility into community opinions
|
||||
- **Engagement**: More interactive features encourage participation
|
||||
- **Discovery**: Users can find content aligned with their preferences
|
||||
|
||||
### Future Enhancement Opportunities
|
||||
- **Machine Learning**: Train recommendation systems on user preferences
|
||||
- **Social Features**: Allow users to follow others with similar tastes
|
||||
- **Advanced Analytics**: Trend analysis and predictive modeling
|
||||
- **Gamification**: Achievement systems based on participation
|
||||
|
||||
## Testing and Validation
|
||||
|
||||
Created supporting files:
|
||||
- `test_basic.py` - Verifies core functionality
|
||||
- `demo_features.py` - Demonstrates all new features
|
||||
- Comprehensive error handling throughout
|
||||
|
||||
## Migration Notes
|
||||
|
||||
For existing databases:
|
||||
1. The enhanced `initialize_database()` function handles schema upgrades automatically
|
||||
2. Existing sentiment data will be preserved with generic user identifiers
|
||||
3. No manual migration steps required
|
||||
|
||||
## Usage Example
|
||||
|
||||
```python
|
||||
# User identification happens automatically
|
||||
# When user rates a joke:
|
||||
success, action = add_user_sentiment(db, joke_id=5, user_choice='up', user_identifier='JohnDoe')
|
||||
# action will be "recorded" for new ratings or "updated" for existing ones
|
||||
|
||||
# Get detailed analytics:
|
||||
user_history = get_user_sentiment_history(db, 'JohnDoe')
|
||||
community_leaderboard = get_top_users_by_joke_preference(db)
|
||||
```
|
||||
|
||||
This enhancement transforms the joke bot from a simple rating system into a comprehensive analytics platform while maintaining all existing functionality.
|
||||
@@ -1,3 +1,143 @@
|
||||
# AI-Enhanced Joke Bot v4.0 - Enhanced User Analytics Edition
|
||||
|
||||
Welcome to the AI-Enhanced Joke Bot! This application combines humor with artificial intelligence to deliver jokes and analyze user preferences with detailed analytics.
|
||||
|
||||
## 📋 Project Structure
|
||||
|
||||
```
|
||||
v4.0/
|
||||
├── jokes.py # Main application with enhanced user sentiment tracking and analytics
|
||||
├── jokes.db # SQLite database containing jokes and detailed user sentiments
|
||||
├── clean_sample_data.sql # Clean sample data with user identifiers
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 1. Run the Application
|
||||
|
||||
Simply run the main application file:
|
||||
|
||||
```bash
|
||||
python jokes.py
|
||||
```
|
||||
|
||||
The application will:
|
||||
- Automatically create the database if it doesn't exist
|
||||
- Add sample data with user identifiers
|
||||
- Prompt you for a username to track your preferences
|
||||
|
||||
## 🔧 Key Features
|
||||
|
||||
### Enhanced User Sentiment Tracking
|
||||
- **User Identification**: Each sentiment rating is linked to a specific user identifier
|
||||
- **Rating History**: Track all jokes you've rated with timestamps
|
||||
- **Personal Favorites**: See which jokes you've specifically liked
|
||||
- **Duplicate Prevention**: Users can update their existing ratings
|
||||
|
||||
### Advanced Analytics
|
||||
- **Community Insights**: See overall sentiment trends and statistics
|
||||
- **User Preference Analysis**: Identify which users have the most positive/negative ratings
|
||||
- **Detailed Breakdowns**: View sentiment distribution for individual jokes
|
||||
- **Popularity Metrics**: Understand which jokes are most liked by the community
|
||||
|
||||
## 🎯 Menu Options
|
||||
|
||||
1. **Get Random Joke**: Receive a joke with community ratings and detailed sentiment breakdown
|
||||
2. **Add New Joke**: Submit your own jokes for community rating
|
||||
3. **View Your Ratings**: See your complete rating history
|
||||
4. **See Your Favorites**: View jokes you've specifically liked
|
||||
5. **Community Analytics**: Access detailed community statistics and user rankings
|
||||
6. **Quit**: Exit the application
|
||||
|
||||
## 📊 Database Schema Enhancements
|
||||
|
||||
The `user_sentiments` table now includes:
|
||||
- `user_identifier`: Links each rating to a specific user
|
||||
- `user_sentiment`: The rating (up/down/neutral)
|
||||
- `created_at`: Timestamp of when the rating was made
|
||||
- Support for updating existing ratings
|
||||
|
||||
## 💡 Usage Examples
|
||||
|
||||
### Getting Started
|
||||
```
|
||||
🤖 Welcome to Joke Bot! 🤖
|
||||
Please enter your username (or press Enter for 'Guest'): JohnDoe
|
||||
👤 Logged in as: JohnDoe
|
||||
```
|
||||
|
||||
### Viewing Detailed Analytics
|
||||
When viewing a joke, you'll see:
|
||||
```
|
||||
🤣 Why don't scientists trust atoms? Because they make up everything!
|
||||
👤 Contributor: ScienceFan
|
||||
👥 Community Rating: 👍 Up (3 votes)
|
||||
🔍 Detailed Breakdown:
|
||||
👍 Up: 2 votes
|
||||
😐 Neutral: 1 votes
|
||||
```
|
||||
|
||||
### Accessing Personal Analytics
|
||||
Option 3 shows your rating history:
|
||||
```
|
||||
📊 Your Joke Ratings History (5 ratings):
|
||||
--------------------------------------------------
|
||||
👍 Why did the scarecrow win an award? He was outstanding in his field!
|
||||
Rated: 2024-01-15 14:30:25
|
||||
|
||||
👎 What do you call a fish with no eyes? Fsh!
|
||||
Rated: 2024-01-15 14:25:10
|
||||
```
|
||||
|
||||
### Community Insights
|
||||
Option 5 provides comprehensive analytics:
|
||||
```
|
||||
📈 COMMUNITY ANALYTICS
|
||||
==============================
|
||||
🏆 Most Positive Users:
|
||||
-------------------------
|
||||
1. ComedyFan: 85.7% positive (6/7 ratings)
|
||||
2. JokeLover: 75.0% positive (3/4 ratings)
|
||||
3. FunnyPerson: 66.7% positive (4/6 ratings)
|
||||
|
||||
📊 Overall Statistics:
|
||||
Total jokes rated: 8
|
||||
Total ratings: 24
|
||||
Community positivity: 62.5%
|
||||
```
|
||||
|
||||
## 🛠️ Technical Improvements
|
||||
|
||||
- **Enhanced Data Model**: User identifiers enable sophisticated analytics
|
||||
- **Better UX**: Session-based user identification for consistent tracking
|
||||
- **Rich Analytics**: Multiple layers of statistical insights
|
||||
- **Data Integrity**: Prevents duplicate ratings while allowing updates
|
||||
|
||||
## 🎉 Benefits of User Identification
|
||||
|
||||
1. **Personalized Experience**: Track your own joke preferences over time
|
||||
2. **Social Insights**: Understand community rating patterns
|
||||
3. **Quality Control**: Identify consistently popular contributors
|
||||
4. **Engagement Metrics**: Measure user participation and preferences
|
||||
5. **Recommendation Potential**: Foundation for future personalized joke recommendations
|
||||
|
||||
Enjoy the enhanced AI-powered humor experience with detailed user analytics!
|
||||
|
||||
# Joke Bot - Enhanced Setup Instructions
|
||||
|
||||
## For Beginners
|
||||
|
||||
### Running the Enhanced Version
|
||||
1. Simply run: `python jokes.py`
|
||||
2. Enter your username when prompted
|
||||
3. Enjoy personalized joke ratings and community analytics!
|
||||
|
||||
The enhanced version automatically handles all database setup and provides rich analytics features right out of the box.
|
||||
```
|
||||
|
||||
## 代码修改建议
|
||||
```
|
||||
# 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.
|
||||
@@ -121,4 +261,75 @@ 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!
|
||||
Enjoy the AI-enhanced humor experience with community feedback!
|
||||
|
||||
# Joke Bot - Simple Setup Instructions
|
||||
|
||||
Welcome to the Joke Bot! This is a fun program that tells jokes and lets you rate them. Follow these simple steps to get it working!
|
||||
|
||||
## Simplified Project Structure
|
||||
|
||||
The application now has a minimal structure:
|
||||
```
|
||||
v4.0/
|
||||
├── jokes.py # Complete application with database creation and sample data
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Step-by-Step Instructions for Beginners
|
||||
|
||||
### Step 1: Open Python IDLE
|
||||
1. Find Python IDLE on your computer (it looks like a blue and white icon)
|
||||
2. Click on it to open it
|
||||
3. When it opens, click on "File" then "New File" to create a new file
|
||||
|
||||
### Step 2: Save Your New File
|
||||
1. In the new file window, click "File" then "Save As..."
|
||||
2. Save the file in your folder and name it `jokes.py`
|
||||
3. Remember where you saved it!
|
||||
|
||||
### Step 3: Get the Code from the Website
|
||||
1. Go to this website: https://gitea.techshare.cc/technolyceum/ai6-m3/src/branch/main/jokes_bot/v4.0
|
||||
2. Look for the `jokes.py` file in the list
|
||||
3. Click on it to see the code
|
||||
4. Select all the code (Ctrl+A on Windows or Cmd+A on Mac)
|
||||
5. Copy it (Ctrl+C on Windows or Cmd+C on Mac)
|
||||
|
||||
### Step 4: Paste the Code
|
||||
1. Go back to your Python IDLE window
|
||||
2. Paste the code you copied (Ctrl+V on Windows or Cmd+V on Mac)
|
||||
3. Click "File" then "Save" to save the code in your file
|
||||
|
||||
### Step 5: Run the Program in PowerShell
|
||||
1. Open PowerShell (on Windows) or Terminal (on Mac)
|
||||
2. Navigate to the folder where you saved your jokes.py file
|
||||
- Type: `cd ` followed by the path to your folder
|
||||
3. Create a virtual environment (this keeps your programs organized):
|
||||
- Type: `python -m venv venv`
|
||||
4. Activate the virtual environment:
|
||||
- On Windows: `venv\Scripts\Activate.ps1`
|
||||
- On Mac: `source venv/bin/activate`
|
||||
5. Run the program:
|
||||
- Type: `python jokes.py`
|
||||
|
||||
### Step 6: Using the Joke Bot
|
||||
1. When the program runs, you'll see a menu with options
|
||||
2. Press "1" to get a random joke
|
||||
3. Press "2" to add your own joke
|
||||
4. Press "3" to quit the program
|
||||
|
||||
## Simple Explanation for New Programmers
|
||||
|
||||
Think of programming like cooking:
|
||||
- The code is like a recipe
|
||||
- Python is like your kitchen tools
|
||||
- The computer is like your kitchen where everything happens
|
||||
|
||||
When you run the Joke Bot:
|
||||
- The program automatically creates a database (like a notebook) to store jokes
|
||||
- If there are no jokes in the notebook, it adds some sample jokes for you
|
||||
- Then it shows you the menu so you can interact with it
|
||||
|
||||
The program is smart enough to handle everything by itself - you don't need to worry about databases or SQL statements. Just run it and enjoy the jokes!
|
||||
|
||||
Have fun with your Joke Bot! 😄
|
||||
|
||||
BIN
jokes_bot/v4.0/__pycache__/jokes.cpython-314.pyc
Normal file
BIN
jokes_bot/v4.0/__pycache__/jokes.cpython-314.pyc
Normal file
Binary file not shown.
@@ -1,67 +0,0 @@
|
||||
#!/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()
|
||||
@@ -1,22 +1,108 @@
|
||||
-- Insert 20 dummy jokes with various sentiments
|
||||
INSERT INTO jokes (joke, contributor, created_date, approved, sentiment_score, sentiment_label) VALUES
|
||||
('Why don''t scientists trust atoms? Because they make up everything!', 'ScienceFan', '2024-01-15 10:30:00', 1, 0.75, '😊 Positive'),
|
||||
('I told my wife she was drawing her eyebrows too high. She looked surprised.', 'Joker123', '2024-01-16 14:20:00', 1, 0.35, '😊 Positive'),
|
||||
('Why did the scarecrow win an award? He was outstanding in his field!', 'FarmLife', '2024-01-17 09:15:00', 1, 0.65, '😊 Positive'),
|
||||
('What do you call a fish with no eyes? Fsh!', 'MarineBio', '2024-01-18 16:45:00', 1, 0.25, '😊 Positive'),
|
||||
('I''m reading a book on anti-gravity. It''s impossible to put down!', 'PhysicsNerd', '2024-01-19 11:30:00', 1, 0.45, '😊 Positive'),
|
||||
('Why did the computer go to the doctor? Because it had a virus.', 'TechSupport', '2024-01-20 13:10:00', 1, 0.05, '😐 Neutral'),
|
||||
('What do you call a bear with no teeth? A gummy bear.', 'WildlifeFan', '2024-01-21 15:25:00', 1, 0.08, '😐 Neutral'),
|
||||
('Why did the bicycle fall over? Because it was two-tired.', 'Cyclist', '2024-01-22 10:00:00', 1, -0.02, '😐 Neutral'),
|
||||
('What do you call a sleeping bull? A bulldozer.', 'Cowboy', '2024-01-23 14:35:00', 1, 0.03, '😐 Neutral'),
|
||||
('Why did the math book look so sad? Because it had too many problems.', 'Student', '2024-01-24 09:50:00', 1, -0.05, '😐 Neutral'),
|
||||
('I used to play piano by ear, but now I use my hands.', 'Musician', '2024-01-25 12:15:00', 1, -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', 1, -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', 1, -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', 1, -0.20, '😒 Negative'),
|
||||
('I told my girlfriend she drew her eyebrows too high. She seemed surprised.', 'Boyfriend', '2024-01-29 10:10:00', 1, -0.30, '😒 Negative'),
|
||||
('What''s orange and sounds like a parrot? A carrot!', 'Vegetarian', '2024-01-30 13:20:00', 1, 0.85, '😊 Positive'),
|
||||
('Why don''t eggs tell jokes? They''d crack each other up!', 'Chef', '2024-01-31 15:45:00', 1, 0.90, '😊 Positive'),
|
||||
('I invented a new word: Plagiarism!', 'Writer', '2024-02-01 09:30:00', 1, 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', 1, 0.82, '😊 Positive'),
|
||||
('What do you call a fake noodle? An impasta!', 'ItalianFood', '2024-02-03 14:40:00', 1, 0.88, '😊 Positive');
|
||||
-- Enhanced Joke Bot Database Schema with User Identification
|
||||
-- Version 4.0 - User Analytics Edition
|
||||
|
||||
-- Drop existing tables if they exist (clean slate)
|
||||
DROP TABLE IF EXISTS user_sentiments;
|
||||
DROP TABLE IF EXISTS jokes;
|
||||
|
||||
-- Create jokes table
|
||||
CREATE TABLE jokes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
joke TEXT NOT NULL,
|
||||
contributor TEXT NOT NULL,
|
||||
created_date TEXT NOT NULL,
|
||||
approved BOOLEAN DEFAULT 0,
|
||||
sentiment_score REAL DEFAULT 0.0,
|
||||
sentiment_label TEXT DEFAULT '😐 Neutral'
|
||||
);
|
||||
|
||||
-- Create user_sentiments table with user identification
|
||||
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',
|
||||
user_identifier TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (joke_id) REFERENCES jokes(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Insert sample jokes with approval status
|
||||
INSERT INTO jokes (joke, contributor, created_date, approved) VALUES
|
||||
('Why don''t scientists trust atoms? Because they make up everything!', 'ScienceFan', '2024-01-15 10:30:00', 1),
|
||||
('I told my wife she was drawing her eyebrows too high. She looked surprised.', 'Joker123', '2024-01-16 14:20:00', 1),
|
||||
('Why did the scarecrow win an award? He was outstanding in his field!', 'FarmLife', '2024-01-17 09:15:00', 1),
|
||||
('What do you call a fish with no eyes? Fsh!', 'MarineBio', '2024-01-18 16:45:00', 1),
|
||||
('I''m reading a book on anti-gravity. It''s impossible to put down!', 'PhysicsNerd', '2024-01-19 11:30:00', 1),
|
||||
('Why did the computer go to the doctor? Because it had a virus.', 'TechSupport', '2024-01-20 13:10:00', 1),
|
||||
('What do you call a bear with no teeth? A gummy bear.', 'WildlifeFan', '2024-01-21 15:25:00', 1),
|
||||
('Why did the bicycle fall over? Because it was two-tired.', 'Cyclist', '2024-01-22 10:00:00', 1),
|
||||
('What do you call a sleeping bull? A bulldozer.', 'Cowboy', '2024-01-23 14:35:00', 1),
|
||||
('Why did the math book look so sad? Because it had too many problems.', 'Student', '2024-01-24 09:50:00', 1);
|
||||
|
||||
-- Insert sample user sentiments with user identifiers
|
||||
INSERT INTO user_sentiments (joke_id, user_sentiment, user_identifier) VALUES
|
||||
(1, 'up', 'ComedyFan'),
|
||||
(1, 'up', 'JokeLover'),
|
||||
(1, 'neutral', 'CritiqueMaster'),
|
||||
(1, 'up', 'FunnyPerson'),
|
||||
(2, 'down', 'SeriousReader'),
|
||||
(2, 'up', 'HappyViewer'),
|
||||
(2, 'neutral', 'NeutralObserver'),
|
||||
(3, 'up', 'ComedyFan'),
|
||||
(3, 'up', 'JokeLover'),
|
||||
(3, 'up', 'FunnyPerson'),
|
||||
(3, 'down', 'CritiqueMaster'),
|
||||
(4, 'neutral', 'FishExpert'),
|
||||
(4, 'down', 'GrammarNazi'),
|
||||
(4, 'up', 'PunLover'),
|
||||
(5, 'up', 'ScienceGeek'),
|
||||
(5, 'up', 'BookWorm'),
|
||||
(5, 'neutral', 'Skeptic'),
|
||||
(6, 'up', 'TechEnthusiast'),
|
||||
(6, 'down', 'ComputerHater'),
|
||||
(7, 'up', 'AnimalLover'),
|
||||
(7, 'up', 'WordPlayFan'),
|
||||
(8, 'up', 'CyclingFan'),
|
||||
(8, 'neutral', 'BikeNovice'),
|
||||
(9, 'up', 'FarmKid'),
|
||||
(9, 'down', 'CitySlicker'),
|
||||
(10, 'neutral', 'MathStudent'),
|
||||
(10, 'up', 'ProblemSolver');
|
||||
|
||||
-- Verification queries
|
||||
SELECT '✅ Database setup complete!' as status;
|
||||
|
||||
-- Show joke counts
|
||||
SELECT 'Total jokes in database:' as info, COUNT(*) as count FROM jokes;
|
||||
|
||||
-- Show sentiment distribution
|
||||
SELECT
|
||||
'Sentiment Distribution:' as info,
|
||||
user_sentiment,
|
||||
COUNT(*) as count
|
||||
FROM user_sentiments
|
||||
GROUP BY user_sentiment
|
||||
ORDER BY count DESC;
|
||||
|
||||
-- Show most active users
|
||||
SELECT
|
||||
'Most Active Users:' as info,
|
||||
user_identifier,
|
||||
COUNT(*) as ratings_given
|
||||
FROM user_sentiments
|
||||
GROUP BY user_identifier
|
||||
ORDER BY ratings_given DESC
|
||||
LIMIT 5;
|
||||
|
||||
-- Show community positivity by joke
|
||||
SELECT
|
||||
'Community Positivity by Joke:' as info,
|
||||
j.joke,
|
||||
ROUND(AVG(CASE WHEN us.user_sentiment = 'up' THEN 1.0
|
||||
WHEN us.user_sentiment = 'down' THEN 0.0
|
||||
ELSE 0.5 END) * 100, 1) as positivity_percent,
|
||||
COUNT(*) as total_ratings
|
||||
FROM jokes j
|
||||
JOIN user_sentiments us ON j.id = us.joke_id
|
||||
GROUP BY j.id, j.joke
|
||||
ORDER BY positivity_percent DESC;
|
||||
@@ -1,28 +0,0 @@
|
||||
# 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,
|
||||
created_date TEXT NOT NULL,
|
||||
approved BOOLEAN DEFAULT 0,
|
||||
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 approval system and user sentiment tracking!")
|
||||
conn.close()
|
||||
@@ -1,74 +0,0 @@
|
||||
# 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()
|
||||
107
jokes_bot/v4.0/demo_features.py
Normal file
107
jokes_bot/v4.0/demo_features.py
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Demo script to showcase the enhanced user identification and analytics features
|
||||
of the Joke Bot v4.0
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
|
||||
def demo_user_identification():
|
||||
"""Demonstrate the new user identification features"""
|
||||
print("🎭 Joke Bot v4.0 - User Identification Demo 🎭")
|
||||
print("=" * 50)
|
||||
|
||||
# Import the main module functions
|
||||
import sys
|
||||
sys.path.append('.')
|
||||
|
||||
# Reinitialize database for demo
|
||||
if os.path.exists('jokes.db'):
|
||||
os.remove('jokes.db')
|
||||
print("🗑️ Cleaned existing database for demo")
|
||||
|
||||
from jokes import initialize_database, add_user_sentiment, get_user_sentiment_for_joke
|
||||
from jokes import get_detailed_sentiment_stats, get_user_sentiment_history
|
||||
from jokes import get_popular_jokes_by_user, get_top_users_by_joke_preference
|
||||
|
||||
# Initialize database
|
||||
print("\n🔧 Initializing database with enhanced schema...")
|
||||
initialize_database()
|
||||
|
||||
db = sqlite3.connect('jokes.db')
|
||||
|
||||
print("\n🎯 Demonstrating User Identification Features:")
|
||||
print("-" * 40)
|
||||
|
||||
# Simulate different users rating the same joke
|
||||
joke_id = 1 # First joke in our sample data
|
||||
test_users = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']
|
||||
test_ratings = ['up', 'up', 'down', 'up', 'neutral']
|
||||
|
||||
print(f"\n📋 Simulating ratings for joke #{joke_id}:")
|
||||
for user, rating in zip(test_users, test_ratings):
|
||||
success, action = add_user_sentiment(db, joke_id, rating, user)
|
||||
rating_emoji = {'up': '👍', 'down': '👎', 'neutral': '😐'}[rating]
|
||||
print(f" {rating_emoji} {user} rated: {rating} ({action})")
|
||||
|
||||
# Show community sentiment
|
||||
avg_sentiment, total_votes = get_user_sentiment_for_joke(db, joke_id)
|
||||
print(f"\n👥 Community Rating: {avg_sentiment} ({total_votes} votes)")
|
||||
|
||||
# Show detailed breakdown
|
||||
detailed_stats = get_detailed_sentiment_stats(db, joke_id)
|
||||
print("🔍 Detailed Breakdown:")
|
||||
for sentiment, count, users in detailed_stats:
|
||||
sentiment_emoji = {'up': '👍', 'down': '👎', 'neutral': '😐'}[sentiment]
|
||||
print(f" {sentiment_emoji} {sentiment.capitalize()}: {count} votes by {users}")
|
||||
|
||||
print("\n👤 Individual User Analytics:")
|
||||
print("-" * 30)
|
||||
|
||||
# Show Alice's rating history
|
||||
alice_history = get_user_sentiment_history(db, 'Alice')
|
||||
print(f"\n📝 Alice's Rating History ({len(alice_history)} ratings):")
|
||||
for joke_id, joke_text, sentiment, created_at in alice_history:
|
||||
sentiment_emoji = {'up': '👍', 'down': '👎', 'neutral': '😐'}[sentiment]
|
||||
print(f" {sentiment_emoji} {joke_text[:40]}...")
|
||||
|
||||
# Show Bob's favorite jokes
|
||||
bob_favorites = get_popular_jokes_by_user(db, 'Bob')
|
||||
print(f"\n😄 Bob's Favorite Jokes ({len(bob_favorites)} likes):")
|
||||
for joke_id, joke_text, contributor, sentiment, created_at in bob_favorites:
|
||||
print(f" 👍 {joke_text[:50]}...")
|
||||
print(f" By: {contributor}")
|
||||
|
||||
print("\n🏆 Community Leaderboard:")
|
||||
print("-" * 25)
|
||||
|
||||
# Show top users by positivity
|
||||
top_users = get_top_users_by_joke_preference(db)
|
||||
if top_users:
|
||||
for i, (username, total, positive, negative, positivity_pct) in enumerate(top_users, 1):
|
||||
print(f"{i}. {username}: {positivity_pct}% positive ({positive}/{total} ratings)")
|
||||
|
||||
# Test duplicate rating prevention
|
||||
print(f"\n🔄 Testing Rating Update Feature:")
|
||||
print("-" * 35)
|
||||
success, action = add_user_sentiment(db, joke_id, 'down', 'Alice') # Change Alice's rating
|
||||
print(f"Alice changed her rating: {action}")
|
||||
|
||||
# Show updated stats
|
||||
avg_sentiment, total_votes = get_user_sentiment_for_joke(db, joke_id)
|
||||
print(f"Updated Community Rating: {avg_sentiment} ({total_votes} votes)")
|
||||
|
||||
db.close()
|
||||
|
||||
print("\n🎉 Demo Complete!")
|
||||
print("✨ Key Features Demonstrated:")
|
||||
print(" • User identification for each sentiment")
|
||||
print(" • Personal rating history tracking")
|
||||
print(" • Favorite joke identification")
|
||||
print(" • Community analytics and leaderboards")
|
||||
print(" • Duplicate rating prevention with update capability")
|
||||
print(" • Detailed sentiment breakdowns")
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo_user_identification()
|
||||
Binary file not shown.
@@ -3,6 +3,75 @@ import sqlite3
|
||||
import random
|
||||
from datetime import datetime
|
||||
|
||||
def initialize_database():
|
||||
"""Create the database and tables if they don't exist"""
|
||||
conn = sqlite3.connect('jokes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Create jokes table
|
||||
cursor.execute('''CREATE TABLE IF NOT EXISTS jokes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
joke TEXT NOT NULL,
|
||||
contributor TEXT NOT NULL,
|
||||
created_date TEXT NOT NULL,
|
||||
approved BOOLEAN DEFAULT 0,
|
||||
sentiment_score REAL DEFAULT 0.0,
|
||||
sentiment_label TEXT DEFAULT '😐 Neutral'
|
||||
)''')
|
||||
|
||||
# Create user_sentiments table with user identifier
|
||||
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',
|
||||
user_identifier TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (joke_id) REFERENCES jokes(id) ON DELETE CASCADE
|
||||
)''')
|
||||
|
||||
# Check if jokes table is empty
|
||||
cursor.execute('SELECT COUNT(*) FROM jokes')
|
||||
joke_count = cursor.fetchone()[0]
|
||||
|
||||
if joke_count == 0:
|
||||
# Insert sample jokes if table is empty
|
||||
sample_jokes = [
|
||||
('Why don\'t scientists trust atoms? Because they make up everything!', 'ScienceFan', '2024-01-15 10:30:00', 1),
|
||||
('I told my wife she was drawing her eyebrows too high. She looked surprised.', 'Joker123', '2024-01-16 14:20:00', 1),
|
||||
('Why did the scarecrow win an award? He was outstanding in his field!', 'FarmLife', '2024-01-17 09:15:00', 1),
|
||||
('What do you call a fish with no eyes? Fsh!', 'MarineBio', '2024-01-18 16:45:00', 1),
|
||||
('I\'m reading a book on anti-gravity. It\'s impossible to put down!', 'PhysicsNerd', '2024-01-19 11:30:00', 1),
|
||||
('Why did the computer go to the doctor? Because it had a virus.', 'TechSupport', '2024-01-20 13:10:00', 1),
|
||||
('What do you call a bear with no teeth? A gummy bear.', 'WildlifeFan', '2024-01-21 15:25:00', 1),
|
||||
('Why did the bicycle fall over? Because it was two-tired.', 'Cyclist', '2024-01-22 10:00:00', 1),
|
||||
('What do you call a sleeping bull? A bulldozer.', 'Cowboy', '2024-01-23 14:35:00', 1),
|
||||
('Why did the math book look so sad? Because it had too many problems.', 'Student', '2024-01-24 09:50:00', 1)
|
||||
]
|
||||
|
||||
cursor.executemany('''
|
||||
INSERT INTO jokes (joke, contributor, created_date, approved)
|
||||
VALUES (?, ?, ?, ?)
|
||||
''', sample_jokes)
|
||||
|
||||
# Add some sample user sentiments with user identifiers
|
||||
sample_sentiments = [
|
||||
(1, 'up', 'User123'), (1, 'up', 'FunnyPerson'), (1, 'neutral', 'JokeLover'),
|
||||
(2, 'down', 'CritiqueMaster'), (2, 'up', 'HappyViewer'),
|
||||
(3, 'up', 'User123'), (3, 'up', 'FunnyPerson'), (3, 'up', 'ComedyFan')
|
||||
]
|
||||
|
||||
cursor.executemany('''
|
||||
INSERT INTO user_sentiments (joke_id, user_sentiment, user_identifier)
|
||||
VALUES (?, ?, ?)
|
||||
''', sample_sentiments)
|
||||
|
||||
conn.commit()
|
||||
print(f"✅ Database initialized with {len(sample_jokes)} sample jokes and {len(sample_sentiments)} sample sentiments!")
|
||||
else:
|
||||
print(f"✅ Connected to database with {joke_count} jokes already present.")
|
||||
|
||||
conn.close()
|
||||
|
||||
def get_user_sentiment_for_joke(db, joke_id):
|
||||
"""Get the average user sentiment for a specific joke"""
|
||||
cursor = db.execute('''
|
||||
@@ -25,29 +94,127 @@ def get_user_sentiment_for_joke(db, joke_id):
|
||||
avg_sentiment, total_votes = result if result else ('😐 Neutral', 0)
|
||||
return avg_sentiment, total_votes
|
||||
|
||||
def add_user_sentiment(db, joke_id, user_choice):
|
||||
"""Add user sentiment for a specific joke"""
|
||||
def get_detailed_sentiment_stats(db, joke_id):
|
||||
"""Get detailed sentiment statistics including user breakdown"""
|
||||
cursor = db.execute('''
|
||||
SELECT
|
||||
user_sentiment,
|
||||
COUNT(*) as count,
|
||||
GROUP_CONCAT(user_identifier) as users
|
||||
FROM user_sentiments
|
||||
WHERE joke_id = ?
|
||||
GROUP BY user_sentiment
|
||||
ORDER BY count DESC
|
||||
''', (joke_id,))
|
||||
|
||||
return cursor.fetchall()
|
||||
|
||||
def get_user_sentiment_history(db, user_identifier):
|
||||
"""Get sentiment history for a specific user"""
|
||||
cursor = db.execute('''
|
||||
SELECT
|
||||
j.id,
|
||||
j.joke,
|
||||
us.user_sentiment,
|
||||
us.created_at
|
||||
FROM user_sentiments us
|
||||
JOIN jokes j ON us.joke_id = j.id
|
||||
WHERE us.user_identifier = ?
|
||||
ORDER BY us.created_at DESC
|
||||
''', (user_identifier,))
|
||||
|
||||
return cursor.fetchall()
|
||||
|
||||
def get_popular_jokes_by_user(db, user_identifier):
|
||||
"""Get jokes that a specific user has rated highly"""
|
||||
cursor = db.execute('''
|
||||
SELECT
|
||||
j.id,
|
||||
j.joke,
|
||||
j.contributor,
|
||||
us.user_sentiment,
|
||||
us.created_at
|
||||
FROM user_sentiments us
|
||||
JOIN jokes j ON us.joke_id = j.id
|
||||
WHERE us.user_identifier = ? AND us.user_sentiment = 'up'
|
||||
ORDER BY us.created_at DESC
|
||||
''', (user_identifier,))
|
||||
|
||||
return cursor.fetchall()
|
||||
|
||||
def add_user_sentiment(db, joke_id, user_choice, user_identifier):
|
||||
"""Add user sentiment for a specific joke with user identification"""
|
||||
try:
|
||||
db.execute('''
|
||||
INSERT INTO user_sentiments (joke_id, user_sentiment)
|
||||
VALUES (?, ?)
|
||||
''', (joke_id, user_choice))
|
||||
# Check if user already rated this joke
|
||||
cursor = db.execute('''
|
||||
SELECT id FROM user_sentiments
|
||||
WHERE joke_id = ? AND user_identifier = ?
|
||||
''', (joke_id, user_identifier))
|
||||
|
||||
existing_rating = cursor.fetchone()
|
||||
|
||||
if existing_rating:
|
||||
# Update existing rating
|
||||
db.execute('''
|
||||
UPDATE user_sentiments
|
||||
SET user_sentiment = ?, created_at = CURRENT_TIMESTAMP
|
||||
WHERE joke_id = ? AND user_identifier = ?
|
||||
''', (user_choice, joke_id, user_identifier))
|
||||
action = "updated"
|
||||
else:
|
||||
# Insert new rating
|
||||
db.execute('''
|
||||
INSERT INTO user_sentiments (joke_id, user_sentiment, user_identifier)
|
||||
VALUES (?, ?, ?)
|
||||
''', (joke_id, user_choice, user_identifier))
|
||||
action = "recorded"
|
||||
|
||||
db.commit()
|
||||
return True
|
||||
return True, action
|
||||
except Exception as e:
|
||||
print(f"❌ Error saving sentiment: {e}")
|
||||
return False
|
||||
return False, None
|
||||
|
||||
def get_top_users_by_joke_preference(db):
|
||||
"""Get analytics on which users prefer which types of jokes"""
|
||||
cursor = db.execute('''
|
||||
SELECT
|
||||
user_identifier,
|
||||
COUNT(*) as total_ratings,
|
||||
SUM(CASE WHEN user_sentiment = 'up' THEN 1 ELSE 0 END) as positive_ratings,
|
||||
SUM(CASE WHEN user_sentiment = 'down' THEN 1 ELSE 0 END) as negative_ratings,
|
||||
ROUND(AVG(CASE WHEN user_sentiment = 'up' THEN 1
|
||||
WHEN user_sentiment = 'down' THEN 0
|
||||
ELSE 0.5 END) * 100, 1) as positivity_percentage
|
||||
FROM user_sentiments
|
||||
GROUP BY user_identifier
|
||||
HAVING COUNT(*) >= 2
|
||||
ORDER BY positivity_percentage DESC, total_ratings DESC
|
||||
''')
|
||||
|
||||
return cursor.fetchall()
|
||||
|
||||
def main():
|
||||
# Initialize database and tables on startup
|
||||
initialize_database()
|
||||
|
||||
db = sqlite3.connect('jokes.db')
|
||||
|
||||
# Get user identifier for session
|
||||
print("🤖 Welcome to Joke Bot! 🤖")
|
||||
user_identifier = input("Please enter your username (or press Enter for 'Guest'): ").strip() or "Guest"
|
||||
print(f"👤 Logged in as: {user_identifier}")
|
||||
|
||||
while True:
|
||||
print("\n" + "="*30)
|
||||
print("🤖 JOKE BOT 🤖")
|
||||
print("="*30)
|
||||
print("\n" + "="*40)
|
||||
print("🤖 JOKE BOT MENU 🤖")
|
||||
print("="*40)
|
||||
print("1. Get random joke")
|
||||
print("2. Add new joke")
|
||||
print("3. Quit")
|
||||
print("3. View your joke ratings")
|
||||
print("4. See what jokes you liked")
|
||||
print("5. View community analytics")
|
||||
print("6. Quit")
|
||||
|
||||
choice = input("\nYour choice: ").strip()
|
||||
|
||||
@@ -71,18 +238,28 @@ def main():
|
||||
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)")
|
||||
|
||||
# Show detailed breakdown
|
||||
detailed_stats = get_detailed_sentiment_stats(db, joke_id)
|
||||
if detailed_stats:
|
||||
print(" 🔍 Detailed Breakdown:")
|
||||
for sentiment, count, users in detailed_stats:
|
||||
sentiment_icon = {'up': '👍', 'down': '👎', 'neutral': '😐'}[sentiment]
|
||||
print(f" {sentiment_icon} {sentiment.capitalize()}: {count} 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()
|
||||
user_choice = 'up' if user_input in ['u', 'up'] else 'down' if user_input in ['d', 'down'] else '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!")
|
||||
success, action = add_user_sentiment(db, joke_id, user_choice, user_identifier)
|
||||
if success:
|
||||
sentiment_text = '👍 Up' if user_choice == 'up' else '👎 Down' if user_choice == 'down' else '😐 Neutral'
|
||||
print(f"✅ Your rating ({sentiment_text}) has been {action}!")
|
||||
else:
|
||||
print("❌ Could not save your rating.")
|
||||
else:
|
||||
print("篓 No approved jokes in the database yet!")
|
||||
print("❌ No approved jokes in the database yet!")
|
||||
|
||||
elif choice == "2":
|
||||
new_joke = input("Enter your joke: ").strip()
|
||||
@@ -111,11 +288,69 @@ def main():
|
||||
print(f"❌ Error saving joke: {e}")
|
||||
|
||||
elif choice == "3":
|
||||
print("\n👋 Goodbye!")
|
||||
# View user's rating history
|
||||
user_history = get_user_sentiment_history(db, user_identifier)
|
||||
if user_history:
|
||||
print(f"\n📊 Your Joke Ratings History ({len(user_history)} ratings):")
|
||||
print("-" * 50)
|
||||
for joke_id, joke_text, sentiment, created_at in user_history[:10]: # Show last 10
|
||||
sentiment_icon = {'up': '👍', 'down': '👎', 'neutral': '😐'}[sentiment]
|
||||
print(f"{sentiment_icon} {joke_text[:50]}{'...' if len(joke_text) > 50 else ''}")
|
||||
print(f" Rated: {created_at}")
|
||||
print()
|
||||
else:
|
||||
print(f"📝 {user_identifier}, you haven't rated any jokes yet!")
|
||||
|
||||
elif choice == "4":
|
||||
# See what jokes the user liked
|
||||
liked_jokes = get_popular_jokes_by_user(db, user_identifier)
|
||||
if liked_jokes:
|
||||
print(f"\n😄 Jokes You Liked ({len(liked_jokes)} favorites):")
|
||||
print("-" * 50)
|
||||
for joke_id, joke_text, contributor, sentiment, created_at in liked_jokes:
|
||||
print(f"👍 {joke_text}")
|
||||
print(f" 👤 By: {contributor} | ⏰ {created_at}")
|
||||
print()
|
||||
else:
|
||||
print(f"😢 {user_identifier}, you haven't liked any jokes yet!")
|
||||
|
||||
elif choice == "5":
|
||||
# View community analytics
|
||||
print("\n📈 COMMUNITY ANALYTICS")
|
||||
print("=" * 30)
|
||||
|
||||
# Top users by positivity
|
||||
top_users = get_top_users_by_joke_preference(db)
|
||||
if top_users:
|
||||
print("\n🏆 Most Positive Users:")
|
||||
print("-" * 25)
|
||||
for i, (username, total, positive, negative, positivity_pct) in enumerate(top_users[:5], 1):
|
||||
print(f"{i}. {username}: {positivity_pct}% positive ({positive}/{total} ratings)")
|
||||
|
||||
# Overall joke statistics
|
||||
cursor = db.execute('''
|
||||
SELECT
|
||||
COUNT(DISTINCT joke_id) as total_rated_jokes,
|
||||
COUNT(*) as total_ratings,
|
||||
AVG(CASE WHEN user_sentiment = 'up' THEN 1
|
||||
WHEN user_sentiment = 'down' THEN 0
|
||||
ELSE 0.5 END) * 100 as overall_positivity
|
||||
FROM user_sentiments
|
||||
''')
|
||||
stats = cursor.fetchone()
|
||||
if stats and stats[0] > 0:
|
||||
total_jokes, total_ratings, positivity = stats
|
||||
print(f"\n📊 Overall Statistics:")
|
||||
print(f" Total jokes rated: {total_jokes}")
|
||||
print(f" Total ratings: {total_ratings}")
|
||||
print(f" Community positivity: {positivity:.1f}%")
|
||||
|
||||
elif choice == "6":
|
||||
print(f"\n👋 Goodbye, {user_identifier}!")
|
||||
break
|
||||
|
||||
else:
|
||||
print("❌ Invalid choice. Please select 1-3.")
|
||||
print("❌ Invalid choice. Please select 1-6.")
|
||||
|
||||
db.close()
|
||||
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
#!/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 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.")
|
||||
@@ -1,37 +0,0 @@
|
||||
-- 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;
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/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)
|
||||
37
jokes_bot/v4.0/test_basic.py
Normal file
37
jokes_bot/v4.0/test_basic.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Simple test to verify basic functionality"""
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
|
||||
# Clean up any existing database
|
||||
if os.path.exists('jokes.db'):
|
||||
os.remove('jokes.db')
|
||||
print("Cleaned existing database")
|
||||
|
||||
# Test importing and initializing
|
||||
try:
|
||||
from jokes import initialize_database
|
||||
print("✓ Successfully imported jokes module")
|
||||
|
||||
initialize_database()
|
||||
print("✓ Database initialized successfully")
|
||||
|
||||
# Test database connection
|
||||
db = sqlite3.connect('jokes.db')
|
||||
cursor = db.execute("SELECT COUNT(*) FROM jokes")
|
||||
count = cursor.fetchone()[0]
|
||||
print(f"✓ Found {count} jokes in database")
|
||||
|
||||
# Test user_sentiments table structure
|
||||
cursor = db.execute("PRAGMA table_info(user_sentiments)")
|
||||
columns = cursor.fetchall()
|
||||
print("✓ user_sentiments table columns:")
|
||||
for col in columns:
|
||||
print(f" - {col[1]} ({col[2]})")
|
||||
|
||||
db.close()
|
||||
print("✓ All tests passed!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {e}")
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/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.")
|
||||
Reference in New Issue
Block a user