Law Student Tracker - Val.town Project

Automates attendance tracking and cold-call selection for both T&E and L&C classes.

Vals

FileTypePurpose
T&E (Trusts & Estates)
oncall-selection.http.tsxHTTPAlgorithmically selects 6 students for cold-calling
oncall-notify.cron.tsxCronEmails on-call list before class (3 PM)
te-report-prompt.cron.tsxCronReminds Sarah to submit T&E report (6 PM)
L&C (Law & Capitalism)
lc-oncall-selection.http.tsxHTTPLooks up preset on-call from syllabus
lc-oncall-notify.cron.tsxCronEmails on-call list before class (8 AM)
lc-report-prompt.cron.tsxCronReminds Sarah to submit L&C report (12 PM)
Shared
post-class-report.http.tsxHTTPReceives reports, updates tracking, triggers alerts
process-form-reports-api.http.tsxHTTPParses Google Form responses, calls post-class-report
process-form-reports-schedule.cron.tsxCronTriggers form processing (every 10 min)
main.http.tsxHTTPSheets connection test
utils.tsxScriptShared utilities

Environment Variables

Set these in Val.town UI (Settings → Environment Variables):

VariablePurpose
GOOGLE_APPLICATION_CREDENTIALSService account JSON (full string)
REPORT_API_KEYSecret key for report submissions
POST_CLASS_REPORT_URLURL for post-class-report.http.tsx
PROCESS_FORM_REPORTS_URLURL for process-form-reports-api.http.tsx

Cron Schedules

Set in Val.town UI for each cron val. Times are UTC:

ValEST TimeUTC Cron
T&E
oncall-notify3 PM Mon/Wed0 20 * * 1,3
te-report-prompt6 PM Mon/Wed0 23 * * 1,3
L&C
lc-oncall-notify8 AM Mon/Wed0 13 * * 1,3
lc-report-prompt12 PM Mon/Wed0 17 * * 1,3

Note: Adjust for DST. These are EST (UTC-5). EDT (summer) is UTC-4.

Report Submission

POST to post-class-report.http.tsx endpoint with:

curl -X POST "https://sahar--{hash}.web.val.run" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_REPORT_API_KEY" \ -d '{ "date": "2026-01-12", "class_type": "te", "cold_calls": [ {"student_name": "Alice Adams", "result": "completed", "performance": "great"}, {"student_name": "Bob Baker", "result": "absent"}, {"student_name": "Carol Chen", "result": "refused"} ], "absences": ["David Davis"] }'

Fields:

  • date: Class date (YYYY-MM-DD)
  • class_type: "te" or "lc"
  • cold_calls: Array of students called on
    • result: "completed" | "absent" | "refused"
    • performance: "great" | "normal" | "bad" (only for completed)
  • absences: Other absent students (not on on-call list)

Response:

{ "success": true, "date": "2026-01-12", "cold_calls_logged": 3, "absences_logged": 1, "unprepared_processed": 0, "alerts_sent": [] }

Alerts

Automatic email alerts at thresholds:

  • 3 absences → Contact dean + student
  • 5 concerning events → Contact student

Concerning events = absent + unprepared + refused + bad performance.

Sheet Structure

Uses Google Sheet with tabs:

Shared:

  • Form Responses 1 - Student self-reports (form-owned, read-only)
  • Cold Call Log - Audit trail of actual cold calls

T&E:

  • T&E Roster - Student list + cumulative tracking (columns: student_name, last_name, pool, cold_call_count, last_called, absences, concerning_events)
  • T&E On-Call - Daily on-call selections (for idempotency)

L&C:

  • L&C Roster - Student list + cumulative tracking (same columns, minus pool)
  • L&C Assignments - Preset syllabus schedule (columns: date, student_name)
  • L&C On-Call - Daily on-call cache (for idempotency)

L&C Setup

  1. Create L&C Roster tab with columns: student_name, last_name, cold_call_count, last_called, absences, concerning_events
  2. Create L&C Assignments tab with columns: date, student_name
  3. Populate L&C Assignments with syllabus data (one row per student per date)

Example L&C Assignments:

datestudent_name
2026-01-13Alice Adams
2026-01-13Bob Baker
2026-01-15Carol Chen