import { flatten } from 'lodash'; import { FilterQuery, ObjectID } from 'mongodb'; import { TrainingAlreadyEnrollError, TrainingNotFoundError } from '../error'; import { TrainingDoc, TrainingNode } from '../interface'; import * as document from './document'; export function getStatus(domainId: string, tid: ObjectID, uid: number) { return document.getStatus(domainId, document.TYPE_TRAINING, tid, uid); } export function getMultiStatus(domainId: string, query: FilterQuery) { return document.getMultiStatus(domainId, document.TYPE_TRAINING, query); } export async function getListStatus(domainId: string, uid: number, tids: ObjectID[]) { const tsdocs = await getMultiStatus( domainId, { uid, docId: { $in: Array.from(new Set(tids)) } }, ).toArray(); const r = {}; for (const tsdoc of tsdocs) r[tsdoc.docId] = tsdoc; return r; } export async function enroll(domainId: string, tid: ObjectID, uid: number) { try { await document.setStatus(domainId, document.TYPE_TRAINING, tid, uid, { enroll: 1 }); } catch (e) { throw new TrainingAlreadyEnrollError(tid, uid); } return await document.inc(domainId, document.TYPE_TRAINING, tid, 'attend', 1); } export function setStatus(domainId: string, tid: ObjectID, uid: number, $set: any) { return document.setStatus(domainId, document.TYPE_TRAINING, tid, uid, $set); } export function add( domainId: string, title: string, content: string, owner: number, dag: TrainingNode[] = [], description = '', ) { return document.add(domainId, content, owner, document.TYPE_TRAINING, null, null, null, { dag, title, description, attend: 0, }); } export function edit(domainId: string, tid: ObjectID, $set: Partial) { return document.set(domainId, document.TYPE_TRAINING, tid, $set); } export function del(domainId: string, tid: ObjectID) { return Promise.all([ document.deleteOne(domainId, document.TYPE_TRAINING, tid), document.deleteMultiStatus(domainId, document.TYPE_TRAINING, { docId: tid }), ]); } export function getPids(dag: TrainingNode[]) { return Array.from(new Set(flatten(dag.map((node) => node.pids)))); } export function isDone(node: TrainingNode, doneNids: Set | number[], donePids: Set | number[]) { return (Set.isSuperset(new Set(doneNids), new Set(node.requireNids)) && Set.isSuperset(new Set(donePids), new Set(node.pids))); } export function isProgress(node: TrainingNode, doneNids: Set | number[], donePids: Set | number[], progPids: Set | number[]) { return (Set.isSuperset(new Set(doneNids), new Set(node.requireNids)) && !Set.isSuperset(new Set(donePids), new Set(node.pids)) && Set.intersection( Set.union(new Set(donePids), new Set(progPids)), new Set(node.pids), ).size); } export function isOpen(node: TrainingNode, doneNids: Set | number[], donePids: Set | number[], progPids: Set | number[]) { return (Set.isSuperset(new Set(doneNids), new Set(node.requireNids)) && !Set.isSuperset(new Set(donePids), new Set(node.pids)) && !Set.intersection( Set.union(new Set(donePids), new Set(progPids)), new Set(node.pids), ).size); } export const isInvalid = (node: TrainingNode, doneNids: Set | number[]) => !Set.isSuperset(new Set(doneNids), new Set(node.requireNids)); export async function count(domainId: string, query: FilterQuery) { return await document.count(domainId, document.TYPE_TRAINING, query); } export async function get(domainId: string, tid: ObjectID) { const tdoc = await document.get(domainId, document.TYPE_TRAINING, tid); if (!tdoc) throw new TrainingNotFoundError(domainId, tid); for (const i in tdoc.dag) { for (const j in tdoc.dag[i].pids) { if (Number.isSafeInteger(parseInt(tdoc.dag[i].pids[j], 10))) { tdoc.dag[i].pids[j] = parseInt(tdoc.dag[i].pids[j], 10); } } } return tdoc; } export const getMulti = (domainId: string, query: FilterQuery = {}) => document.getMulti(domainId, document.TYPE_TRAINING, query).sort({ pin: -1, _id: -1 }); export async function getList(domainId: string, tids: ObjectID[]) { const tdocs = await getMulti( domainId, { _id: { $in: Array.from(new Set(tids)) } }, ).toArray(); const r = {}; for (const tdoc of tdocs) r[tdoc.docId.toString()] = tdoc; return r; } global.Hydro.model.training = { getPids, isDone, isProgress, isOpen, isInvalid, add, edit, del, count, get, getList, getMulti, getMultiStatus, getStatus, enroll, setStatus, getListStatus, };