teacher-tools/api/source/sample_data.d

185 lines
5.5 KiB
D

module sample_data;
import ddbc;
import db;
import data_utils;
import slf4d;
import std.random;
import std.algorithm;
import std.array;
import std.datetime;
private const STUDENT_NAMES = [
"Andrew",
"Richard",
"Klaus",
"John",
"Wilson",
"Grace",
"Sarah",
"Rebecca",
"Lily",
"Thomas",
"Michael",
"Jennifer",
"Robert",
"Christopher",
"Margaret",
"Mordecai",
"Rigby",
"Walter",
"Roy",
"Cindy"
];
void insertSampleData() {
Connection conn = getDb();
conn.setAutoCommit(false);
scope(exit) {
conn.commit();
conn.close();
}
deleteAllData(conn);
addUser(conn, "sample-user-A", "test", false, false);
addUser(conn, "sample-user-B", "test", true, false);
addUser(conn, "sample-user-C", "test", false, false);
addUser(conn, "sample-user-D", "test", false, false);
ulong adminUserId = addUser(conn, "test", "test", false, true);
ulong normalUserId = addUser(conn, "test2", "test", false, false);
Random rand = Random(0);
addClassroomComplianceSampleData(rand, adminUserId, conn);
addClassroomComplianceSampleData(rand, normalUserId, conn);
info("Inserted sample data.");
}
void addClassroomComplianceSampleData(ref Random rand, ulong adminUserId, Connection conn) {
const SysTime now = Clock.currTime();
const Date today = Date(now.year, now.month, now.day);
for (ushort i = 1; i <= 6; i++) {
ulong classId = addClass(conn, "2024-2025", i, adminUserId);
bool classHasAssignedDesks = uniform01(rand) < 0.5;
size_t count = uniform(10, STUDENT_NAMES.length, rand);
auto studentsToAdd = randomSample(STUDENT_NAMES, count, rand);
ushort deskNumber = 1;
foreach (name; studentsToAdd) {
bool removed = uniform01(rand) < 0.1;
ushort assignedDeskNumber = 0;
if (classHasAssignedDesks) {
assignedDeskNumber = deskNumber++;
}
ulong studentId = addStudent(conn, name, classId, assignedDeskNumber, removed);
// Add entries for the last N days
for (int n = 0; n < 30; n++) {
Date entryDate = today - days(n);
bool missingEntry = uniform01(rand) < 0.05;
if (missingEntry) continue;
addEntry(conn, classId, studentId, entryDate, rand);
}
}
}
}
ulong addUser(Connection conn, string username, string password, bool locked, bool admin) {
import std.digest.sha;
string passwordHash = cast(string) sha256Of(password).toHexString().idup;
return insertOne(
conn,
"INSERT INTO auth_user (username, password_hash, is_locked, is_admin) VALUES (?, ?, ?, ?) RETURNING id",
username, passwordHash, locked, admin
);
}
ulong addClass(Connection conn, string schoolYear, ushort number, ulong userId) {
return insertOne(
conn,
"INSERT INTO classroom_compliance_class (number, school_year, user_id) VALUES (?, ?, ?) RETURNING id",
number, schoolYear, userId
);
}
ulong addStudent(Connection conn, string name, ulong classId, ushort deskNumber, bool removed) {
return insertOne(
conn,
"INSERT INTO classroom_compliance_student
(name, class_id, desk_number, removed)
VALUES (?, ?, ?, ?) RETURNING id",
name, classId, deskNumber, removed
);
}
void addEntry(
Connection conn,
ulong classId,
ulong studentId,
Date date,
ref Random rand
) {
bool absent = uniform01(rand) < 0.05;
bool hasComment = uniform01(rand) < 0.25;
string comment = hasComment ? "This is a sample comment." : "";
const entryQuery = "
INSERT INTO classroom_compliance_entry
(class_id, student_id, date, absent, comment)
VALUES (?, ?, ?, ?, ?)";
PreparedStatement ps = conn.prepareStatement(entryQuery);
scope(exit) ps.close();
ps.setUlong(1, classId);
ps.setUlong(2, studentId);
ps.setDate(3, date);
ps.setBoolean(4, absent);
ps.setString(5, comment);
ps.executeUpdate();
bool hasChecklistItems = uniform01(rand) < 0.75;
if (!hasChecklistItems) return;
const checklistItemQuery = "
INSERT INTO classroom_compliance_entry_checklist_item
(class_id, student_id, date, item, checked, category)
VALUES (?, ?, ?, ?, ?, ?)";
PreparedStatement ckPs = conn.prepareStatement(checklistItemQuery);
scope(exit) ckPs.close();
const categories = ["Classroom Readiness", "Behavior"];
foreach (category; categories) {
for (int i = 0; i < 6; i++) {
import std.conv : to;
string item = "Checklist item " ~ (i+1).to!string;
bool checked = uniform01(rand) < 0.25;
ckPs.setUlong(1, classId);
ckPs.setUlong(2, studentId);
ckPs.setDate(3, date);
ckPs.setString(4, item);
ckPs.setBoolean(5, checked);
ckPs.setString(6, category);
ckPs.executeUpdate();
}
}
}
void deleteAllData(Connection conn) {
Statement stmt = conn.createStatement();
scope(exit) stmt.close();
const tables = [
"announcement",
"classroom_compliance_class_note",
"classroom_compliance_entry_checklist_item",
"classroom_compliance_entry",
"classroom_compliance_student",
"classroom_compliance_class",
"auth_user"
];
foreach (tableName; tables) {
int rows = stmt.executeUpdate("DELETE FROM " ~ tableName);
infoF!"Deleted %d rows from %s."(rows, tableName);
}
}