-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
178 lines (158 loc) · 6.93 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/env python
from flask import Flask, request, send_file, render_template_string
import io
from datetime import datetime, timedelta
import pytz
from icalendar import Calendar, Event
app = Flask(__name__)
# HTML form template with collapsible text area for input
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>Study Schedule Generator</title>
<!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script>
function toggleInputBox() {
var x = document.getElementById("inputBox");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
</head>
<body>
<div class="container mt-5">
<h2>Generate Study Schedule</h2>
<form method="post">
<div class="form-group">
<label>Start Date (YYYY-MM-DD):</label>
<input type="text" class="form-control" name="start_date" required>
</div>
<div class="form-group">
<label>Study Days (1=Monday, ..., 7=Sunday), separated by commas:</label>
<input type="text" class="form-control" name="study_days" required>
</div>
<div class="form-group">
<label>Start Time (HH:MM):</label>
<input type="text" class="form-control" name="start_time" required>
</div>
<div class="form-group">
<label>Daily Study Limit Hours:</label>
<input type="number" class="form-control" name="daily_study_limit_hours" required>
</div>
<div class="form-group">
<label>Multiplier:</label>
<input type="text" class="form-control" name="multiplier" required>
</div>
<button type="button" class="btn btn-info mb-3" onclick="toggleInputBox()">Toggle Class Input Box</button>
<div id="inputBox" class="form-group" style="display:none;">
<label>Class Input:</label>
<textarea class="form-control" name="class_input" rows="10"></textarea>
</div>
<input type="submit" class="btn btn-primary" value="Generate Schedule">
</form>
</div>
<!-- Include Bootstrap JS and its dependencies -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
"""
@app.route('/', methods=['GET'])
def form():
return render_template_string(HTML_TEMPLATE)
@app.route('/', methods=['POST'])
def generate_schedule():
start_date_str = request.form['start_date']
study_days_input = request.form['study_days']
start_time_str = request.form['start_time']
daily_study_limit_hours = int(request.form['daily_study_limit_hours'])
multiplier = float(request.form['multiplier'])
class_input = request.form['class_input']
classes = parse_class_input(class_input)
adjusted_classes = apply_multiplier(classes, multiplier)
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
study_days = [int(day) for day in study_days_input.split(',')]
study_schedule = schedule_classes(adjusted_classes, start_date, study_days, daily_study_limit_hours)
ical_data = create_calendar_events(study_schedule, start_time_str, 'America/Sao_Paulo', daily_study_limit_hours)
# Sending the file back to the client
ical_file = io.BytesIO(ical_data)
ical_file.seek(0)
return send_file(ical_file, as_attachment=True, download_name='study_schedule.ics', mimetype='text/calendar')
def parse_class_input(class_input):
"""Parses class input from a text area and returns a list of classes."""
classes = []
lines = class_input.split('\n')
i = 0
while i < len(lines):
status = lines[i].strip()
if i + 2 < len(lines):
subject = lines[i + 1].strip()
duration_line = lines[i + 2].strip()
if 'min' in duration_line:
duration_str = duration_line.replace('min', '')
try:
duration = int(duration_str)
classes.append([status, subject, duration])
i += 3
except ValueError:
i += 1 # Skip the problematic line
else:
i += 1
else:
break
return classes
def apply_multiplier(classes, multiplier):
"""Applies the multiplier to class durations."""
return [[cls[0], cls[1], cls[2] * multiplier] for cls in classes]
def schedule_classes(classes, start_date, study_days, daily_study_limit_hours):
"""Schedules classes into daily study blocks."""
study_schedule = {}
daily_study_limit_minutes = daily_study_limit_hours * 60
current_date = start_date
time_left = daily_study_limit_minutes
for cls in classes:
while cls[2] > 0:
if current_date.weekday() in study_days:
if time_left >= cls[2]:
if current_date not in study_schedule:
study_schedule[current_date] = []
study_schedule[current_date].append(cls)
time_left -= cls[2]
cls[2] = 0
else:
if current_date not in study_schedule:
study_schedule[current_date] = []
split_class = cls[:]
split_class[2] = time_left
study_schedule[current_date].append(split_class)
cls[2] -= time_left
time_left = 0
if time_left == 0 or current_date.weekday() not in study_days:
current_date += timedelta(days=1)
time_left = daily_study_limit_minutes
return study_schedule
def create_calendar_events(study_schedule, start_time_str, timezone, daily_study_limit_hours):
"""Creates calendar events for each study block."""
cal = Calendar()
cal.add('prodid', '-//Study Schedule Calendar//mxm.dk//')
cal.add('version', '2.0')
local_tz = pytz.timezone(timezone)
for day, classes in study_schedule.items():
start_datetime = datetime.combine(day, datetime.strptime(start_time_str, '%H:%M').time())
start_datetime = local_tz.localize(start_datetime)
end_datetime = start_datetime + timedelta(minutes=daily_study_limit_hours*60)
event = Event()
event.add('summary', f"Study Block {day.strftime('%Y-%m-%d')}")
event.add('dtstart', start_datetime)
event.add('dtend', end_datetime)
event.add('description', "Classes today:\n" + '\n'.join(cls[1] for cls in classes))
cal.add_component(event)
return cal.to_ical()
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')