Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/course/export/file-use-times.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { StudentsMap, StudentRecord } from "../store";6import {7exec,8query,9write_text_file_to_project,10} from "../../frame-editors/generic/client";11import { splitlines } from "@cocalc/util/misc";1213interface PathUseTimes {14edit_times: number[];15access_times: number[];16}1718interface StudentUseTimes {19student_id: string;20account_id?: string;21project_id?: string;22student_name: string;23assignment_path: string;24paths?: { [path: string]: PathUseTimes };25error?: string; // if it fails for some non-obvious reason26}2728async function one_student_file_use_times(29paths: string[],30project_id: string,31account_id: string,32limit: number = 1000,33): Promise<{ [path: string]: PathUseTimes }> {34project_id = project_id;35account_id = account_id;36const times: { [path: string]: PathUseTimes } = {};37for (const path of paths) {38const q = await query({39query: {40file_use_times: {41project_id,42account_id,43path,44access_times: null,45edit_times: null,46},47},48options: [{ limit }],49});50const { edit_times, access_times } = q.query.file_use_times;51times[path] = { edit_times, access_times };52}53return times;54}5556function student_info(57assignment_path: string,58student: StudentRecord,59get_name: Function,60): StudentUseTimes {61const student_id = student.get("student_id");62const x: StudentUseTimes = {63student_id,64student_name: get_name(student_id),65assignment_path,66};67for (const field of ["account_id", "project_id"]) {68if (student.has(field)) {69x[field] = student.get(field);70}71}72return x;73}7475async function paths_to_scan(76project_id: string,77src_path: string,78target_path: string,79): Promise<string[]> {80const { stdout } = await exec({81command: "find",82args: ["."],83path: src_path,84err_on_exit: true,85project_id,86});87const v: string[] = [];88for (const path of splitlines(stdout)) {89const path2 = path.slice(2);90if (path2) {91v.push(target_path + "/" + path2);92}93}94return v;95}9697export async function all_students_file_use_times(98course_project_id: string,99src_path: string,100target_path: string,101students: StudentsMap,102get_name: Function,103): Promise<{ [student_id: string]: StudentUseTimes }> {104const paths = await paths_to_scan(course_project_id, src_path, target_path);105106// Iterate through the (nondeleted) students determining to what extent107// they used files in the given path in their projects.108const times: { [student_id: string]: StudentUseTimes } = {};109for (const [student_id, student] of students) {110if (student.get("deleted")) continue;111const info = (times[student_id] = student_info(112target_path,113student,114get_name,115));116if (info.project_id == null || info.account_id == null) {117// nothing more to do, since no account or project118continue;119}120try {121info.paths = await one_student_file_use_times(122paths,123info.project_id,124info.account_id,125);126} catch (err) {127info.error = `${err}`;128}129}130return times;131}132133export async function export_student_file_use_times(134course_project_id: string,135src_path: string,136target_path: string,137students: StudentsMap,138target_json: string,139get_name: Function,140): Promise<void> {141const x = await all_students_file_use_times(142course_project_id,143src_path,144target_path,145students,146get_name,147);148await write_text_file_to_project({149project_id: course_project_id,150path: target_json,151content: JSON.stringify(x, null, 2),152});153}154155156