Commit message (Collapse) | Author | Age | Files | Lines | |
---|---|---|---|---|---|
* | Allow staff to upload a CSV containing courses | Runxi Yu | 2024-10-10 | 1 | -3/+4 |
| | | | | Implements: https://todo.sr.ht/~runxiyu/cca/2 | ||||
* | *.go, tmpl/staff.html: Allow staff to export choices | Runxi Yu | 2024-10-09 | 1 | -0/+2 |
| | | | | Implements: https://todo.sr.ht/~runxiyu/cca/3 | ||||
* | {courses,wsc}.go: Atomic 64-bit alignment | Runxi Yu | 2024-10-09 | 1 | -3/+6 |
| | |||||
* | *.go: Update comments | Runxi Yu | 2024-10-09 | 1 | -9/+4 |
| | |||||
* | {courses,index}.go, student.html, style.css: Group by course group | Runxi Yu | 2024-10-09 | 1 | -9/+11 |
| | |||||
* | *.go: Use sync.Map instead of map[int]*courseT for courses | Runxi Yu | 2024-10-09 | 1 | -35/+18 |
| | | | | I'm not sure whether this is actually better than locking. | ||||
* | {courses,wsc,wsp}.go: Usems should be sync.Map | Runxi Yu | 2024-10-09 | 1 | -5/+2 |
| | | | | | This is a classic few-reads, many-writes situation where a sync.Map would lead to substantially less lock contention. | ||||
* | {courses,wsc,wsm}.go: map[courseGroupT](bool->struct{}) | Runxi Yu | 2024-10-08 | 1 | -3/+3 |
| | | | | | This makes it use slightly less memory. Approximately courseGroupT bits per connection! | ||||
* | *.go: Further wrap errors | Runxi Yu | 2024-10-08 | 1 | -8/+14 |
| | |||||
* | err.go: Create, and unify some error definitions | Runxi Yu | 2024-10-08 | 1 | -7/+0 |
| | |||||
* | {courses,wsm,wsp}.go: Make course.Selected atomic | Runxi Yu | 2024-10-07 | 1 | -4/+5 |
| | |||||
* | *.go: Limit to approximately 80 characters per line | Runxi Yu | 2024-10-06 | 1 | -12/+56 |
| | |||||
* | {courses,wsc,wsm,wsp}.go: Send course number immediately on user interaction | Runxi Yu | 2024-10-06 | 1 | -2/+9 |
| | |||||
* | *: Overhaul structure again and embed everything | Runxi Yu | 2024-10-06 | 1 | -0/+229 |
| | | | | | | | | - Remove sub-Makefiles; recursive make is annoying - Just use one top-level Makefile that builds everything - Embed templates and minified static resources into the binary - Embed all compiled documentation into the binary and serve - Embed all source into the binary and serve | ||||
* | *.go: Move to backend | Runxi Yu | 2024-10-05 | 1 | -229/+0 |
| | | | | And adjust Makefiles, admin handbook, and lint.sh accordingly. | ||||
* | {courses,wsm}.go: Use in-memory structure to fetch cgroup, not SQL | Runxi Yu | 2024-10-05 | 1 | -17/+6 |
| | |||||
* | {courses,sem,ws,wsm}.go: Second step towards an efficient state propagator | Runxi Yu | 2024-10-05 | 1 | -4/+6 |
| | | | | References: https://todo.sr.ht/~runxiyu/cca/7 | ||||
* | {courses,sem,ws}.go: First step towards an efficient state propagator | Runxi Yu | 2024-10-05 | 1 | -1/+10 |
| | | | | References: https://todo.sr.ht/~runxiyu/cca/7 | ||||
* | courses.go: Reformat | Runxi Yu | 2024-10-05 | 1 | -1/+1 |
| | |||||
* | {courses,wsm}.go: Add getCourseByID | Runxi Yu | 2024-10-05 | 1 | -0/+6 |
| | | | | This also deduplicates some code. | ||||
* | {courses,wsm}.go: Add (*courseT).decrementSelectedAndPropagate | Runxi Yu | 2024-10-05 | 1 | -0/+11 |
| | | | | This is being done quite a few times, so let's make it a function. | ||||
* | {courses,ws,wsm}.go: Update userCourseGroups during choose/unchoose | Runxi Yu | 2024-10-05 | 1 | -7/+18 |
| | |||||
* | {courses,ws}.go: Populate userCourseGroups in a separate function | Runxi Yu | 2024-10-05 | 1 | -0/+34 |
| | |||||
* | {courses,ws}.go: Populate userCourseGroups for each connection | Runxi Yu | 2024-10-04 | 1 | -5/+19 |
| | | | | | | | | | | | | | | | | | | It is way too expensive to query the database every time we need to check whether a user has chosen a course in a group. Since we can (hopefully) guarantee that there is only one usable connection for any given moment and user, we could store this data along with the connection as a local variable in handleConn, which would be eligible for garbage collection when handleConn exits. Here we create the data structures that globally represent courseTypes and courseGroups, and during the initial stages of handleConn, perform database queries to populate userCourseGroups with the groups that the user has already chosen. Note that the HELLO command handler does similar database queries, and as per the TODO listed in the comments, should be moved up here for efficiency. (HELLO also serves as some sort of an initial connection check; this should probably be replaced with WebSocket's native pings.) | ||||
* | courses.go, schema.sql: Validate course{Type,Group} in server, not SQL | Runxi Yu | 2024-10-04 | 1 | -10/+44 |
| | |||||
* | courses.go: Propagate course.Selected when setting up courses | Runxi Yu | 2024-10-01 | 1 | -2/+7 |
| | |||||
* | *: Change license to AGPL-3.0-or-later | Runxi Yu | 2024-09-30 | 1 | -21/+11 |
| | |||||
* | courses.go: courseT.{Lock->SelectedLock} | Runxi Yu | 2024-09-29 | 1 | -12/+12 |
| | |||||
* | courses.go: Add a RWMutex to courseT | Runxi Yu | 2024-09-28 | 1 | -8/+15 |
| | |||||
* | courses.go, etc: Make courses a map instead of a slice | Runxi Yu | 2024-09-26 | 1 | -3/+3 |
| | | | | | We need to refer to courses by their ID, and a map makes significantly more sense than a slice. | ||||
* | *.go, cca.scfg.example: Expose performance options | Runxi Yu | 2024-09-26 | 1 | -1/+1 |
| | |||||
* | *.go: Wrap errors | Runxi Yu | 2024-09-26 | 1 | -3/+4 |
| | |||||
* | *.go: Linting | Runxi Yu | 2024-09-24 | 1 | -11/+11 |
| | |||||
* | courses.go: Comment out coursetype_t enum to make linter happy for now | Runxi Yu | 2024-09-24 | 1 | -5/+7 |
| | |||||
* | *.go: Add more licenses | Runxi Yu | 2024-09-09 | 1 | -0/+30 |
| | |||||
* | *.go: Add comments | Runxi Yu | 2024-09-09 | 1 | -2/+18 |
| | |||||
* | courses.go: Remove unused imports | Runxi Yu | 2024-09-08 | 1 | -1/+0 |
| | |||||
* | *: Display courses | Runxi Yu | 2024-09-08 | 1 | -0/+69 |