136 lines
4 KiB
TypeScript
136 lines
4 KiB
TypeScript
import Colle from '#models/colle'
|
|
import Examiner from '#models/examiner'
|
|
import Room from '#models/room'
|
|
import Subject from '#models/subject'
|
|
import User from '#models/user'
|
|
|
|
export class ColleService {
|
|
async getStudent(studentName: string, className: string) {
|
|
// Find or create a student by name
|
|
const { firstName, lastName } = this.splitNames(studentName)
|
|
const student = await User.query()
|
|
.where('first_name', firstName)
|
|
.where('last_name', lastName)
|
|
.where('class_name', className)
|
|
.first()
|
|
if (!student) {
|
|
return User.create({ firstName, lastName, className })
|
|
}
|
|
return student
|
|
}
|
|
|
|
splitNames(fullName: string): { firstName: string; lastName: string } {
|
|
const words = fullName.trim().split(/\s+/)
|
|
|
|
let lastNameParts: string[] = []
|
|
let i = 0
|
|
|
|
// Collect all uppercase words at the start
|
|
while (i < words.length && words[i] === words[i].toUpperCase()) {
|
|
lastNameParts.push(words[i])
|
|
i++
|
|
}
|
|
|
|
const lastName = lastNameParts.join(' ')
|
|
const firstName = words.slice(i).join(' ')
|
|
|
|
return { firstName, lastName }
|
|
}
|
|
|
|
async getExaminer(examinerName: string) {
|
|
// Find or create an examiner by name
|
|
const examiner = await Examiner.query().where('name', examinerName).first()
|
|
if (!examiner) return Examiner.create({ name: examinerName })
|
|
return examiner
|
|
}
|
|
|
|
async getSubject(subjectName: string) {
|
|
// Find or create a subject by name
|
|
const subject = await Subject.query().where('name', subjectName).first()
|
|
if (!subject) return Subject.create({ name: subjectName })
|
|
return subject
|
|
}
|
|
|
|
async getRoom(roomName: string) {
|
|
// Find or create a room by name
|
|
const room = await Room.query().where('name', roomName).first()
|
|
if (!room) return Room.create({ name: roomName })
|
|
return room
|
|
}
|
|
|
|
async getColles(student: User, startDate: string, endDate: string) {
|
|
const classColles = await Colle.query()
|
|
.preload('student')
|
|
.preload('examiner')
|
|
.preload('subject')
|
|
.preload('room')
|
|
.where('date', '>=', startDate)
|
|
.where('date', '<=', endDate)
|
|
.whereHas('student', (query) => {
|
|
query.where('className', student.className)
|
|
})
|
|
// Filter only colles that have been graded
|
|
.whereNotNull('grade')
|
|
.orderBy('date', 'asc')
|
|
|
|
const studentColles = await Colle.query()
|
|
.preload('examiner')
|
|
.preload('subject')
|
|
.preload('room')
|
|
.preload('student')
|
|
.where('date', '>=', startDate)
|
|
.where('date', '<=', endDate)
|
|
.where('studentId', student.id)
|
|
.orderBy('date', 'asc')
|
|
|
|
// TODO: Favorite colles
|
|
const favoriteColles = [] as Colle[]
|
|
|
|
return {
|
|
classColles,
|
|
studentColles,
|
|
favoriteColles,
|
|
}
|
|
}
|
|
|
|
// Pre-process HTML content to render LaTeX
|
|
private removeTrailingLines(htmlString: string) {
|
|
return htmlString.replace(/(<br\s*\/?>\s*)+$/gi, '').trim()
|
|
}
|
|
|
|
private extractLatexImages(html: string) {
|
|
const imgRegex = /<img[^>]+src="(https:\/\/latex\.codecogs\.com\/gif\.latex\?(=?.*?))"[^>]*>/g
|
|
let parts = []
|
|
let latexMatches: string[] = []
|
|
let lastIndex = 0
|
|
|
|
html.replace(imgRegex, (match, _, latex, index) => {
|
|
parts.push(html.slice(lastIndex, index)) // Add HTML before image
|
|
latexMatches.push(decodeURIComponent(latex)) // Extract and decode LaTeX
|
|
lastIndex = index + match.length
|
|
return ''
|
|
})
|
|
|
|
parts.push(html.slice(lastIndex)) // Add remaining HTML after last image
|
|
|
|
return { parts, latexMatches }
|
|
}
|
|
|
|
prepareHtmlForRendering(html: string) {
|
|
const strippedHtml = this.removeTrailingLines(html)
|
|
const { parts, latexMatches } = this.extractLatexImages(strippedHtml)
|
|
|
|
const outputHtml = parts
|
|
.map((part, i) => {
|
|
if (!latexMatches[i]) {
|
|
return part
|
|
}
|
|
return `${part}$$${latexMatches[i]}$$`
|
|
})
|
|
.join('')
|
|
|
|
// Remove all "\," from string
|
|
const regex = /\\,/g
|
|
return outputHtml.replace(regex, ' ')
|
|
}
|
|
}
|