-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
158 lines (129 loc) · 5.74 KB
/
bot.py
File metadata and controls
158 lines (129 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import discord
from discord.ext import commands
import matplotlib.pyplot as plt
import json
import os
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv("DISCORD_TOKEN")
print(f"TOKEN: {repr(TOKEN)}")
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)
def normalize_term(term):
"""Normalize term format to FA/SP + YY format"""
term = term.strip().upper()
if 'FALL' in term or term.startswith('F'):
# Handle both YYYY and YY year formats
year_part = ''.join(filter(str.isdigit, term))
if len(year_part) >= 2:
return f"FA{year_part[-2:]}"
elif 'SPRING' in term or term.startswith('S'):
# Handle both YYYY and YY year formats
year_part = ''.join(filter(str.isdigit, term))
if len(year_part) >= 2:
return f"SP{year_part[-2:]}"
return term
def create_chart(grades, name, course_name=None):
labels = list(grades.keys())
values = [grades[label] for label in labels]
plt.figure(figsize=(10, 6))
plt.bar(labels, values, color='skyblue')
title = f"{name} Grade Distribution"
if course_name:
title = f"{name} - {course_name} Grade Distribution"
plt.title(title)
plt.xlabel("Grade")
plt.ylabel("Number of Students")
plt.tight_layout()
plt.savefig("grade_chart.png")
plt.close()
@bot.command()
async def grades(ctx, *, args: str):
print(f"Received command: {args}")
parts = args.strip().split()
if len(parts) < 2:
await ctx.send("Please provide at least a course number and professor\'s last name (e.g., !grades 111 BOKLAN)")
return
# Parse arguments
course_nbr_input = parts[0].strip()
prof_last_name_input = parts[1].strip().upper()
# Store the raw term input if provided
term_input_raw = None
if len(parts) >= 3:
term_input_raw = parts[2].strip().upper()
# Load the JSON data
try:
with open('grades.json', 'r') as f:
data = json.load(f)
except Exception as e:
print(f"Error loading grades.json: {e}")
await ctx.send("Error loading grade data. Please try again later.")
return
# Find matching course data
matching_entries = []
available_terms = [] # Track available terms for error message
for key in data:
# Split from right to handle potential commas in professor names
parts_key = key.rsplit(', ', 2)
if len(parts_key) == 3:
prof, course, term = parts_key
elif len(parts_key) == 2: # Handle cases where there\'s no comma in prof name
prof, course_term = parts_key
course, term = course_term.rsplit(', ', 1)
else:
continue # Skip this key if format is unexpected
# Check if this matches the course and professor
if (course.strip() == course_nbr_input and
prof.split(',')[0].strip().upper() == prof_last_name_input):
matching_entries.append(data[key])
available_terms.append(term.strip())
if not matching_entries:
await ctx.send(f"No data found for CSCI {course_nbr_input} with Professor {prof_last_name_input} in any term.")
return
# If term is not provided, find the most recent term and display it
if len(parts) == 2:
# Sort entries by term to find the most recent
most_recent_entry = sorted(matching_entries, key=lambda x: x['term'])[-1]
course_data = most_recent_entry
await ctx.send(f"No term provided. Displaying data for Professor {course_data['name']}'s most recent semester for CSCI {course_data['course']}: {course_data['term']}")
# Create and send the chart and response message
create_chart(course_data['grades'], course_data['name'], f"CSCI {course_data['course']}")
file = discord.File("grade_chart.png")
grade_lines = [f"{grade}: {count}" for grade, count in course_data['grades'].items() if count > 0]
response = (
f"**Grade Distribution for CSCI {course_data['course']} - {course_data['name']} ({course_data['term']})**\n"
f"Average GPA: {course_data['avg_gpa']:.2f}\n\n" # Added Average GPA back
+ "\n".join(grade_lines)
)
await ctx.send(response, file=file)
return
# If term is provided, look for exact match
if term_input_raw:
for entry in matching_entries:
if entry['term'].upper() == term_input_raw:
course_data = entry
# Create and send the chart and response message
create_chart(course_data['grades'], course_data['name'], f"CSCI {course_data['course']}")
file = discord.File("grade_chart.png")
grade_lines = [f"{grade}: {count}" for grade, count in course_data['grades'].items() if count > 0]
response = (
f"**Grade Distribution for CSCI {course_data['course']} - {course_data['name']} ({course_data['term']})**\n"
f"Average GPA: {course_data['avg_gpa']:.2f}\n\n" # Added Average GPA back
+ "\n".join(grade_lines)
)
await ctx.send(response, file=file)
return
# If we get here, the term was not found
available_terms_unique = sorted(set(available_terms))
terms_list = ", ".join(available_terms_unique)
await ctx.send(f"No data found for CSCI {course_nbr_input} with Professor {prof_last_name_input} for term {term_input_raw}.\n"
f"Available terms for this professor and course: {terms_list}")
return
@bot.event
async def on_ready():
print(f'Logged in as {bot.user} (ID: {bot.user.id})')
print('------')
# keeping commented out for Railway
# keep_alive()
bot.run(TOKEN)