Yujie Chen commited on
Commit
871160f
·
1 Parent(s): a31fc52
Files changed (5) hide show
  1. Dockerfile +2 -2
  2. README.md +41 -10
  3. app.py +23 -7
  4. data/courses_seed.json +16 -1
  5. requirements.txt +1 -0
Dockerfile CHANGED
@@ -11,6 +11,6 @@ RUN pip install --no-cache-dir -r requirements.txt
11
  COPY . .
12
  # Expose the port expected by Hugging Face Spaces (default: 7860, but $PORT is set by HF)
13
  EXPOSE 7860
14
- # Use $PORT for Flask
15
  ENV PORT=7860
16
- CMD ["python", "app.py"]
 
11
  COPY . .
12
  # Expose the port expected by Hugging Face Spaces (default: 7860, but $PORT is set by HF)
13
  EXPOSE 7860
14
+ # Use gunicorn for production WSGI server
15
  ENV PORT=7860
16
+ CMD gunicorn -b 0.0.0.0:$PORT app:APP
README.md CHANGED
@@ -8,17 +8,48 @@ app_file: app.py
8
  pinned: false
9
  ---
10
 
11
- # Minerva Lite
12
 
13
- A lightweight course registration system for demonstration and testing purposes. Runs as a Flask app in a Docker container.
14
 
15
- ## Features
16
- - Simple course registration and schedule management
17
- - Minimal dependencies
18
- - Ready for Hugging Face Spaces deployment
19
 
20
- ## Usage
21
- This app is designed to be run as a Docker container or on Hugging Face Spaces.
22
 
23
- ## License
24
- MIT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  pinned: false
9
  ---
10
 
11
+ # Minerva Lite: Registration
12
 
13
+ Minerva Lite is a simplified web-based simulation of course registration. It is designed for demonstration, testing, and educational purposes.
14
 
15
+ ## Key Features
 
 
 
16
 
17
+ - **Term Selection:**
18
+ - Choose from multiple academic terms (Fall 2025, Winter 2026, Summer 2026, Fall 2026).
19
 
20
+ - **Course Search:**
21
+ - Search for courses by subject, number, title, or campus.
22
+ - View available courses for the selected term, including seat availability and schedule details.
23
+
24
+ - **Add/Drop Courses:**
25
+ - Register for courses by entering a CRN (Course Reference Number).
26
+ - Drop registered courses.
27
+ - Registration is simulated for a single demo student.
28
+
29
+ - **Student Schedule:**
30
+ - View your current course registrations for the selected term.
31
+ - See a weekly grid view of your schedule, with time blocks for each class.
32
+
33
+ - **Accounts:**
34
+ - View a placeholder page for tuition fee and legal status (for demonstration).
35
+
36
+ - **Database Reset:**
37
+ - Use the `/reset` endpoint to reseed the database with demo data (useful for testing or restoring the initial state).
38
+
39
+ ## Demo Data
40
+
41
+ - The app comes preloaded with a variety of courses across multiple terms and departments (COMP, MATH, PHYS, ECON, ENGL, etc.).
42
+ - Each course includes details such as subject, number, title, credits, days, time, campus, and seat availability.
43
+
44
+ ## Intended Use
45
+
46
+ - This app is for demonstration and educational purposes only.
47
+ - No real student data is used or stored.
48
+
49
+ ## How to Use
50
+
51
+ 1. **Select a term** to begin.
52
+ 2. **Search for courses** or browse available options.
53
+ 3. **Add or drop courses** using CRNs.
54
+ 4. **View your schedule** in list or weekly grid format.
55
+ 5. **Reset the database** if you want to restore the original demo data.
app.py CHANGED
@@ -1,10 +1,9 @@
1
- import sqlite3, pathlib
2
- from functools import wraps
3
-
4
-
5
- #
6
  import os
 
 
 
7
  from flask import Flask, render_template, request, jsonify, redirect, url_for, session
 
8
  APP = Flask(__name__)
9
  # Use environment variable for secret key (required for Spaces)
10
  APP.secret_key = os.environ.get("SECRET_KEY", "dev-minerva-lite")
@@ -46,8 +45,25 @@ def require_term(step_key):
46
  return wrapper
47
  return decorator
48
 
49
- if not DB_PATH.exists():
50
- import seed # side effect: creates DB
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  def q(sql, *params):
53
  con = sqlite3.connect(DB_PATH)
 
 
 
 
 
 
1
  import os
2
+ import sqlite3
3
+ import pathlib
4
+ from functools import wraps
5
  from flask import Flask, render_template, request, jsonify, redirect, url_for, session
6
+
7
  APP = Flask(__name__)
8
  # Use environment variable for secret key (required for Spaces)
9
  APP.secret_key = os.environ.get("SECRET_KEY", "dev-minerva-lite")
 
45
  return wrapper
46
  return decorator
47
 
48
+
49
+ # Always ensure DB is seeded: if DB file is missing or 'courses' table is missing, run seed
50
+ def ensure_db_seeded():
51
+ need_seed = False
52
+ if not DB_PATH.exists():
53
+ need_seed = True
54
+ else:
55
+ try:
56
+ con = sqlite3.connect(DB_PATH)
57
+ cur = con.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='courses'")
58
+ if not cur.fetchone():
59
+ need_seed = True
60
+ con.close()
61
+ except Exception:
62
+ need_seed = True
63
+ if need_seed:
64
+ import seed # side effect: creates DB
65
+
66
+ ensure_db_seeded()
67
 
68
  def q(sql, *params):
69
  con = sqlite3.connect(DB_PATH)
data/courses_seed.json CHANGED
@@ -18,6 +18,21 @@
18
  {"crn": "10016", "subject": "ECON", "number": "340", "title": "Macroeconomic Theory", "credits": 3, "days": "MW", "time": "15:05-16:25", "campus": "Downtown", "seats_total": 100, "seats_taken": 85},
19
  {"crn": "10017", "subject": "HIST", "number": "210", "title": "Modern World History", "credits": 3, "days": "MWF", "time": "13:35-14:25", "campus": "Downtown", "seats_total": 140, "seats_taken": 95},
20
  {"crn": "10018", "subject": "PHYS", "number": "230", "title": "Electricity and Magnetism", "credits": 3, "days": "TR", "time": "16:05-17:25", "campus": "Downtown", "seats_total": 110, "seats_taken": 60},
21
- {"crn": "10019", "subject": "ENGL", "number": "315", "title": "Creative Writing Workshop", "credits": 3, "days": "MW", "time": "09:05-10:25", "campus": "Downtown", "seats_total": 60, "seats_taken": 45}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  ]
23
  }
 
18
  {"crn": "10016", "subject": "ECON", "number": "340", "title": "Macroeconomic Theory", "credits": 3, "days": "MW", "time": "15:05-16:25", "campus": "Downtown", "seats_total": 100, "seats_taken": 85},
19
  {"crn": "10017", "subject": "HIST", "number": "210", "title": "Modern World History", "credits": 3, "days": "MWF", "time": "13:35-14:25", "campus": "Downtown", "seats_total": 140, "seats_taken": 95},
20
  {"crn": "10018", "subject": "PHYS", "number": "230", "title": "Electricity and Magnetism", "credits": 3, "days": "TR", "time": "16:05-17:25", "campus": "Downtown", "seats_total": 110, "seats_taken": 60},
21
+ {"crn": "10019", "subject": "ENGL", "number": "315", "title": "Creative Writing Workshop", "credits": 3, "days": "MW", "time": "09:05-10:25", "campus": "Downtown", "seats_total": 60, "seats_taken": 45},
22
+ {"crn": "20001", "subject": "COMP", "number": "303", "title": "Software Engineering", "credits": 3, "days": "TR", "time": "10:00-11:20", "campus": "Downtown", "seats_total": 100, "seats_taken": 80, "term": "Winter 2026"},
23
+ {"crn": "20002", "subject": "MATH", "number": "315", "title": "Ordinary Differential Equations", "credits": 3, "days": "MWF", "time": "12:00-12:50", "campus": "Downtown", "seats_total": 120, "seats_taken": 100, "term": "Winter 2026"},
24
+ {"crn": "20003", "subject": "PHYS", "number": "204", "title": "Waves and Optics", "credits": 3, "days": "TR", "time": "13:00-14:20", "campus": "Downtown", "seats_total": 90, "seats_taken": 60, "term": "Winter 2026"},
25
+ {"crn": "20004", "subject": "ECON", "number": "208", "title": "Microeconomic Theory", "credits": 3, "days": "MWF", "time": "09:00-09:50", "campus": "Downtown", "seats_total": 110, "seats_taken": 90, "term": "Winter 2026"},
26
+ {"crn": "20005", "subject": "ENGL", "number": "220", "title": "Shakespeare", "credits": 3, "days": "TR", "time": "14:00-15:20", "campus": "Downtown", "seats_total": 60, "seats_taken": 40, "term": "Winter 2026"},
27
+ {"crn": "30001", "subject": "COMP", "number": "310", "title": "Computer Systems", "credits": 3, "days": "MWF", "time": "11:00-11:50", "campus": "Downtown", "seats_total": 80, "seats_taken": 50, "term": "Summer 2026"},
28
+ {"crn": "30002", "subject": "MATH", "number": "327", "title": "Probability", "credits": 3, "days": "TR", "time": "13:00-14:20", "campus": "Downtown", "seats_total": 90, "seats_taken": 70, "term": "Summer 2026"},
29
+ {"crn": "30003", "subject": "PHYS", "number": "205", "title": "Modern Physics", "credits": 3, "days": "MW", "time": "15:00-16:20", "campus": "Downtown", "seats_total": 60, "seats_taken": 30, "term": "Summer 2026"},
30
+ {"crn": "30004", "subject": "ECON", "number": "256", "title": "International Economics", "credits": 3, "days": "TR", "time": "10:00-11:20", "campus": "Downtown", "seats_total": 70, "seats_taken": 40, "term": "Summer 2026"},
31
+ {"crn": "30005", "subject": "ENGL", "number": "250", "title": "Canadian Literature", "credits": 3, "days": "MWF", "time": "13:00-13:50", "campus": "Downtown", "seats_total": 50, "seats_taken": 20, "term": "Summer 2026"},
32
+ {"crn": "40001", "subject": "COMP", "number": "302", "title": "Programming Languages and Paradigms", "credits": 3, "days": "TR", "time": "09:00-10:20", "campus": "Downtown", "seats_total": 110, "seats_taken": 80, "term": "Fall 2026"},
33
+ {"crn": "40002", "subject": "MATH", "number": "314", "title": "Advanced Calculus", "credits": 3, "days": "MWF", "time": "10:00-10:50", "campus": "Downtown", "seats_total": 100, "seats_taken": 90, "term": "Fall 2026"},
34
+ {"crn": "40003", "subject": "PHYS", "number": "206", "title": "Thermodynamics", "credits": 3, "days": "TR", "time": "11:00-12:20", "campus": "Downtown", "seats_total": 80, "seats_taken": 60, "term": "Fall 2026"},
35
+ {"crn": "40004", "subject": "ECON", "number": "330", "title": "Public Finance", "credits": 3, "days": "MWF", "time": "12:00-12:50", "campus": "Downtown", "seats_total": 90, "seats_taken": 70, "term": "Fall 2026"},
36
+ {"crn": "40005", "subject": "ENGL", "number": "260", "title": "World Literature", "credits": 3, "days": "TR", "time": "14:00-15:20", "campus": "Downtown", "seats_total": 60, "seats_taken": 30, "term": "Fall 2026"}
37
  ]
38
  }
requirements.txt CHANGED
@@ -5,3 +5,4 @@ itsdangerous==2.2.0
5
  click==8.1.7
6
  werkzeug==3.0.1
7
  markupsafe==2.1.3
 
 
5
  click==8.1.7
6
  werkzeug==3.0.1
7
  markupsafe==2.1.3
8
+ gunicorn