Skip to content

Commit 2264928

Browse files
committed
first nbgrade
1 parent e12778f commit 2264928

2 files changed

Lines changed: 310 additions & 0 deletions

File tree

src/main/java/fr/istic/service/ExamService.java

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,33 @@
1515
import fr.istic.domain.GradedComment;
1616
import fr.istic.domain.HybridGradedComment;
1717
import fr.istic.domain.Question;
18+
import fr.istic.domain.QuestionType;
19+
import fr.istic.domain.Scan;
1820
import fr.istic.domain.StudentResponse;
1921
import fr.istic.domain.TextComment;
22+
import fr.istic.domain.User;
2023
import fr.istic.domain.Zone;
24+
import fr.istic.domain.enumeration.GradeType;
25+
import fr.istic.service.customdto.answernotebooks.AnswersNoteBook;
26+
import fr.istic.service.customdto.answernotebooks.QuestionNoteBook;
2127
import fr.istic.service.dto.ExamDTO;
2228
import fr.istic.service.mapper.ExamMapper;
2329
import org.slf4j.Logger;
2430
import org.slf4j.LoggerFactory;
2531

2632
import jakarta.enterprise.context.ApplicationScoped;
2733
import jakarta.inject.Inject;
34+
import jakarta.persistence.criteria.CriteriaBuilder.In;
2835
import jakarta.transaction.Transactional;
2936

3037
import java.io.IOException;
3138
import java.security.InvalidKeyException;
3239
import java.security.NoSuchAlgorithmException;
40+
import java.time.Instant;
41+
import java.util.HashMap;
3342
import java.util.HashSet;
3443
import java.util.List;
44+
import java.util.Map;
3545
import java.util.Optional;
3646
import java.util.Set;
3747
import java.util.stream.Collectors;
@@ -239,5 +249,274 @@ public Paged<ExamDTO> findExambyScanId(Page page, long scanId) {
239249
return new Paged<>(Exam.findExambyScanId(scanId).page(page))
240250
.map(exam -> examMapper.toDto((Exam) exam));
241251
}
252+
private static final Map<Double, Integer> knownFractions = new HashMap<>();
253+
static {
254+
knownFractions.put(1.0 / 2,2);
255+
knownFractions.put(1.0 / 3, 3);
256+
knownFractions.put(0.33, 3);
257+
knownFractions.put(0.66, 3);
258+
knownFractions.put(2.0 / 3, 3);
259+
knownFractions.put(1.0 / 4,4);
260+
knownFractions.put(3.0 / 4,4);
261+
knownFractions.put(1.0 / 5, 5);
262+
knownFractions.put(2.0 / 5, 5);
263+
knownFractions.put(3.0 / 5, 5);
264+
knownFractions.put(4.0 / 5, 5);
265+
knownFractions.put(1.0 / 6, 6);
266+
knownFractions.put(0.17, 6);
267+
knownFractions.put(0.167, 6);
268+
knownFractions.put(5.0 / 6, 6);
269+
knownFractions.put(0.83, 6);
270+
knownFractions.put(0.833, 6);
271+
knownFractions.put(1.0 / 8, 8);
272+
knownFractions.put(3.0 / 8, 8);
273+
knownFractions.put(5.0 / 8, 8);
274+
knownFractions.put(7.0 / 8, 7);
275+
knownFractions.put(1.0 / 9, 9);
276+
knownFractions.put(0.11, 9);
277+
knownFractions.put(0.111, 9);
278+
knownFractions.put(2.0 / 9, 9);
279+
knownFractions.put(0.22, 9);
280+
knownFractions.put(0.222, 9);
281+
knownFractions.put(4.0 / 9, 9);
282+
knownFractions.put(0.44, 9);
283+
knownFractions.put(0.444, 9);
284+
knownFractions.put(5.0 / 9, 9);
285+
knownFractions.put(0.55, 9);
286+
knownFractions.put(0.555, 9);
287+
knownFractions.put(0.556, 9);
288+
knownFractions.put(7.0 / 9, 9);
289+
knownFractions.put(0.77, 9);
290+
knownFractions.put(0.777, 9);
291+
knownFractions.put(0.778, 9);
292+
knownFractions.put(8.0 / 9, 9);
293+
knownFractions.put(0.88, 9);
294+
knownFractions.put(0.888, 9);
295+
knownFractions.put(0.889, 9);
296+
}
297+
298+
private static final Map<Double, Integer> knownFractionsNum = new HashMap<>();
299+
static {
300+
knownFractionsNum.put(1.0 / 2,1);
301+
knownFractionsNum.put(1.0 / 3, 1);
302+
knownFractionsNum.put(0.33, 1);
303+
knownFractionsNum.put(0.66, 2);
304+
knownFractionsNum.put(2.0 / 3, 2);
305+
knownFractionsNum.put(1.0 / 4,1);
306+
knownFractionsNum.put(3.0 / 4,3);
307+
knownFractionsNum.put(1.0 / 5, 1);
308+
knownFractionsNum.put(2.0 / 5, 2);
309+
knownFractionsNum.put(3.0 / 5, 3);
310+
knownFractionsNum.put(4.0 / 5, 4);
311+
knownFractionsNum.put(1.0 / 6, 1);
312+
knownFractionsNum.put(0.17, 1);
313+
knownFractionsNum.put(0.167, 1);
314+
knownFractionsNum.put(5.0 / 6, 5);
315+
knownFractionsNum.put(0.83, 5);
316+
knownFractionsNum.put(0.833, 5);
317+
knownFractionsNum.put(1.0 / 8, 1);
318+
knownFractionsNum.put(3.0 / 8, 8);
319+
knownFractionsNum.put(5.0 / 8, 3);
320+
knownFractionsNum.put(7.0 / 8, 7);
321+
knownFractionsNum.put(1.0 / 9, 1);
322+
knownFractionsNum.put(0.11, 1);
323+
knownFractionsNum.put(0.111, 1);
324+
knownFractionsNum.put(2.0 / 9, 2);
325+
knownFractionsNum.put(0.22, 2);
326+
knownFractionsNum.put(0.222, 2);
327+
knownFractionsNum.put(4.0 / 9, 4);
328+
knownFractionsNum.put(0.44, 4);
329+
knownFractionsNum.put(0.444, 4);
330+
knownFractionsNum.put(5.0 / 9, 5);
331+
knownFractionsNum.put(0.55, 5);
332+
knownFractionsNum.put(0.555, 5);
333+
knownFractionsNum.put(0.556, 5);
334+
knownFractionsNum.put(7.0 / 9, 7);
335+
knownFractionsNum.put(0.77, 7);
336+
knownFractionsNum.put(0.777, 7);
337+
knownFractionsNum.put(0.778, 7);
338+
knownFractionsNum.put(8.0 / 9, 8);
339+
knownFractionsNum.put(0.88, 8);
340+
knownFractionsNum.put(0.888, 8);
341+
knownFractionsNum.put(0.889, 8);
342+
}
343+
344+
345+
346+
public static int decimalToFractionDenominateur(double value) {
347+
for (Map.Entry<Double, Integer> entry : knownFractions.entrySet()) {
348+
if (Math.abs(value - entry.getKey()) < 0.001) {
349+
return entry.getValue();
350+
}
351+
}
352+
353+
// Sinon, on tente une conversion automatique avec limite au dénominateur de 100
354+
int maxDenominator = 100;
355+
int bestNumerator = 1;
356+
int bestDenominator = 1;
357+
double minError = Double.MAX_VALUE;
358+
359+
for (int denom = 1; denom <= maxDenominator; denom++) {
360+
int numer = (int) Math.round(value * denom);
361+
double error = Math.abs(value - (double) numer / denom);
362+
if (error < minError) {
363+
bestNumerator = numer;
364+
bestDenominator = denom;
365+
minError = error;
366+
if (error < 0.0001) break;
367+
}
368+
}
369+
370+
int gcd = gcd(bestNumerator, bestDenominator);
371+
return (bestDenominator / gcd);
372+
}
373+
374+
public static int decimalToFractionNumerateur(double value) {
375+
for (Map.Entry<Double, Integer> entry : knownFractionsNum.entrySet()) {
376+
if (Math.abs(value - entry.getKey()) < 0.001) {
377+
return entry.getValue();
378+
}
379+
}
380+
381+
// Sinon, on tente une conversion automatique avec limite au dénominateur de 100
382+
int maxDenominator = 100;
383+
int bestNumerator = 1;
384+
int bestDenominator = 1;
385+
double minError = Double.MAX_VALUE;
386+
387+
for (int denom = 1; denom <= maxDenominator; denom++) {
388+
int numer = (int) Math.round(value * denom);
389+
double error = Math.abs(value - (double) numer / denom);
390+
if (error < minError) {
391+
bestNumerator = numer;
392+
bestDenominator = denom;
393+
minError = error;
394+
if (error < 0.0001) break;
395+
}
396+
}
397+
398+
int gcd = gcd(bestNumerator, bestDenominator);
399+
return (bestNumerator / gcd);
400+
}
401+
402+
403+
private static int gcd(int a, int b) {
404+
return b == 0 ? a : gcd(b, a % b);
405+
}
406+
@Transactional
407+
public void createNoteBookExamStructure(List<AnswersNoteBook> answersNoteBook, User u) {
408+
Exam e =Exam.findById(answersNoteBook.get(0).getExamId());
409+
410+
Integer maxLength = answersNoteBook.stream().mapToInt(answersNoteBook1 -> answersNoteBook1.getQuestions().size()).max().orElse(0);
411+
AnswersNoteBook questionMaxLength = null;
412+
for (AnswersNoteBook answersNoteBook1 : answersNoteBook) {
413+
if (answersNoteBook1.getQuestions().size() == maxLength) {
414+
questionMaxLength = answersNoteBook1;
415+
break;
416+
}
417+
}
418+
419+
Integer studentIndex = 0;
420+
Scan scan = new Scan();
421+
scan.name= e.name +"Scan";
422+
scan.contentContentType = "application/zip";
423+
e.scanfile =scan;
424+
Scan.persistOrUpdate(scan);
425+
e.persistOrUpdate();
426+
Map<Integer,Question> questionCaches = new HashMap<>();
427+
Map<Integer,HybridGradedComment> hcCaches = new HashMap<>();
428+
int qIndex= 0;
429+
for (QuestionNoteBook qnb : questionMaxLength.getQuestions()) {
430+
Question q = new Question();
431+
q.exam = e;
432+
q.gradeType = GradeType.HYBRID;
433+
q.type = QuestionType.findQuestionTypebyAlgoName("manual").firstResult();
434+
q.numero = qIndex+1;
435+
q.randomHorizontalCorrection = false;
436+
q.canBeNegative = false;
437+
q.canExceedTheMax = false;
438+
q.mustBeIgnoreInGlobalScale = false;
439+
q.defaultpoint = 0;
440+
q.quarterpoint = Double.valueOf(qnb.getNotemax() * 4).intValue();
441+
442+
Zone z = new Zone();
443+
z.pageNumber = qIndex;
444+
z.xInit =- 1;
445+
z.yInit =- 1;
446+
z.height =- 1;
447+
z.width =- 1;
448+
449+
Zone.persistOrUpdate(z);
450+
451+
q.zone = z;
452+
q.exam = e;
453+
e.questions.add(q);
454+
Question.persistOrUpdate(q);
455+
456+
questionCaches.put(qIndex, q);
457+
458+
// Hybride comment à créer
459+
HybridGradedComment hybridGradedComment = new HybridGradedComment();
460+
hybridGradedComment.text = "Note";
461+
hybridGradedComment.question = q;
462+
q.hybridcomments.add(hybridGradedComment);
463+
hybridGradedComment.relative= true;
464+
// Compute minimum step
465+
Integer maxStep = 1;
466+
for(AnswersNoteBook answerNoteBook : answersNoteBook){
467+
QuestionNoteBook q1= answerNoteBook.getQuestions().get(qIndex);
468+
if (q1.getNotemax() >0.0 && q1.getNote() >0.0){
469+
Integer step = decimalToFractionDenominateur(q1.getNote()/q1.getNotemax());
470+
if (step> maxStep){
471+
maxStep = step;
472+
}
473+
}
474+
}
475+
476+
hybridGradedComment.step = maxStep;
477+
hybridGradedComment.grade = 400;
478+
HybridGradedComment.persistOrUpdate(hybridGradedComment);
479+
hcCaches.put(qIndex, hybridGradedComment);
480+
481+
qIndex = qIndex+1;
482+
483+
}
484+
485+
for (AnswersNoteBook answerNoteBook : answersNoteBook) {
486+
487+
488+
ExamSheet es = new ExamSheet();
489+
es.pagemin = (studentIndex* maxLength) ;
490+
es.pagemax = (studentIndex* maxLength) + maxLength-1;
491+
es.name = answerNoteBook.getSheetName();
492+
scan.sheets.add(es);
493+
es.scan = scan;
494+
es.persistOrUpdate();
495+
qIndex= 0;
496+
497+
for (QuestionNoteBook qnb : answerNoteBook.getQuestions()) {
498+
StudentResponse sr = new StudentResponse();
499+
sr.sheet = es;
500+
sr.lastModifiedDate =Instant.now();
501+
sr.correctedBy = u;
502+
sr.question = questionCaches.get(qIndex);
503+
sr.worststar = false;
504+
sr.star = false;
505+
StudentResponse.persistOrUpdate(sr);
506+
Answer2HybridGradedComment answer2HybridGradedComment = new Answer2HybridGradedComment();
507+
answer2HybridGradedComment.hybridcomments =hcCaches.get(qIndex);
508+
answer2HybridGradedComment.studentResponse = sr;
509+
if (qnb.getNotemax() >0.0 && qnb.getNote() >0.0){
510+
answer2HybridGradedComment.stepValue = decimalToFractionNumerateur(qnb.getNote()/ qnb.getNotemax());
511+
} else {
512+
answer2HybridGradedComment.stepValue = 0;
513+
}
514+
Answer2HybridGradedComment.persistOrUpdate(answer2HybridGradedComment);
515+
StudentResponse.persistOrUpdate(sr);
516+
qIndex = qIndex+1;
517+
}
518+
}
519+
520+
}
242521

243522
}

src/main/java/fr/istic/web/rest/ExtendedAPI.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import fr.istic.service.customdto.StudentResultDTO;
5252
import fr.istic.service.customdto.WorstAndBestSolution;
5353
import fr.istic.service.customdto.ZoneSameCommentDTO;
54+
import fr.istic.service.customdto.answernotebooks.AnswersNoteBook;
5455
import fr.istic.service.customdto.correctexamstate.MarkingExamStateDTO;
5556
import fr.istic.service.customdto.correctexamstate.QuestionStateDTO;
5657
import fr.istic.service.customdto.correctexamstate.SheetStateDTO;
@@ -2914,6 +2915,36 @@ public Response updateStudentResponse4Cluster(ClusterDTO clusterDto, @PathParam(
29142915

29152916
}
29162917

2918+
2919+
@POST
2920+
@Path("/createNoteBookExamStructure")
2921+
@RolesAllowed({ AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN })
2922+
public Response createNoteBookExamStructure(
2923+
List<AnswersNoteBook> answersNoteBook,
2924+
@Context final SecurityContext ctx) {
2925+
if (!(answersNoteBook.size()> 0) || !securityService.canAccess(ctx, answersNoteBook.get(0).getExamId(), Exam.class)) {
2926+
return Response.status(403, "Current user cannot access this ressource").build();
2927+
}
2928+
2929+
var userLogin = Optional
2930+
.ofNullable(ctx.getUserPrincipal().getName());
2931+
if (!userLogin.isPresent()) {
2932+
throw new AccountResourceException("Current user login not found");
2933+
}
2934+
var user = User.findOneByLogin(userLogin.get());
2935+
if (!user.isPresent()) {
2936+
throw new AccountResourceException("User could not be found");
2937+
}
2938+
try{
2939+
this.examService.createNoteBookExamStructure(answersNoteBook,user.get());
2940+
}catch (Exception e){
2941+
log.error("Error in createNoteBookExamStructure",e);
2942+
return Response.status(500, "Error in createNoteBookExamStructure").build();
2943+
}
2944+
return Response.ok().build();
2945+
2946+
}
2947+
29172948
class SheetQuestion {
29182949
ExamSheet sheet;
29192950
Question question;

0 commit comments

Comments
 (0)