Update arborescence 2
This commit is contained in:
68
src/Exec.java
Normal file
68
src/Exec.java
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import commands.Analyse;
|
||||
import commands.Build;
|
||||
import commands.Evaluate;
|
||||
import commands.Generate;
|
||||
import commands.Produce;
|
||||
import commands.Read;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.*;
|
||||
|
||||
@Command(
|
||||
name = "Exec",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "\n ---- Nicely Generated and Corrected Copies ---- \n\n" +
|
||||
" _______ _________________ ________ \n" +
|
||||
" \\ \\ / _____/\\_ ___ \\\\_ ___ \\ \n" +
|
||||
" / | \\/ \\ ___/ \\ \\// \\ \\/ \n" +
|
||||
" / | \\ \\_ \\ \\ \\___\\ \\___ \n" +
|
||||
" \\____|__ /\\______ /\\______ /\\______ / \n" +
|
||||
" \\/ \\/ \\/ \\/ \n" +
|
||||
" \n" ,
|
||||
footer = "\n\n ---- Provided by IUT Info Nice S3T-G4 ---- \n",
|
||||
description = ""
|
||||
)
|
||||
|
||||
|
||||
public class Exec implements Callable <Void> {
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec; // Permet de tager la commande pour l'appeler dans la surcharge de call()
|
||||
|
||||
// Système d'options et paramètres de commande de l'API
|
||||
|
||||
@Option(names= {"-v","--version"}, versionHelp = true, arity = "0", order = 1, description = "Displays version info")
|
||||
boolean version; // Paramètre associé (versionHelp génere l'aide de version automatiquement)
|
||||
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
// Système de subcommand semblable à celui de git permettant d'appeler les classes relatives
|
||||
String[] t = {"-r","-v9","-d","pdf","config.txt"};
|
||||
CommandLine cmd = new CommandLine (new Exec())
|
||||
.addSubcommand("-r", new Read(System.out)) // nom commande, objet commande
|
||||
.addSubcommand("-b", new Build(System.out))
|
||||
.addSubcommand("-g", new Generate(System.out))
|
||||
.addSubcommand("-p", new Produce(System.out))
|
||||
.addSubcommand("-a", new Analyse(System.out))
|
||||
.addSubcommand("-e", new Evaluate(System.out))
|
||||
.addSubcommand("help", new HelpCommand()); // Aide générée automatiquement par l'API
|
||||
|
||||
cmd.execute(t); //t
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
CommandLine.usage(this.spec, System.out); // Retourne l'aide générée par l'API s'il n'y a pas d'arguments
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
0
src/GenerateurPdf/.gitkeep
Normal file
0
src/GenerateurPdf/.gitkeep
Normal file
343
src/GenerateurPdf/SubjectGenerator.java
Normal file
343
src/GenerateurPdf/SubjectGenerator.java
Normal file
@@ -0,0 +1,343 @@
|
||||
package GenerateurPdf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
|
||||
// infor concernant strok, fill, ... : https://stackoverflow.com/a/27959484
|
||||
|
||||
public class SubjectGenerator {
|
||||
|
||||
private static void drawDotedLine(PDPageContentStream contentStream, int xi, int yi, int xf, int yf)
|
||||
throws IOException {
|
||||
contentStream.moveTo(xi, yi);
|
||||
for (int i = xi; i <= xf; i += 3) {
|
||||
contentStream.lineTo(i, yf);
|
||||
contentStream.moveTo(i + 2, yf);
|
||||
|
||||
}
|
||||
// contentStream.fill();
|
||||
}
|
||||
|
||||
private static void drawCircle(PDPageContentStream contentStream, int cx, int cy, int r) throws IOException {
|
||||
// https://stackoverflow.com/a/42836210
|
||||
final float k = 0.552284749831f;
|
||||
contentStream.moveTo(cx - r, cy);
|
||||
contentStream.curveTo(cx - r, cy + (k * r), cx - (k * r), cy + r, cx, cy + r);
|
||||
contentStream.curveTo(cx + (k * r), cy + r, cx + r, cy + (k * r), cx + r, cy);
|
||||
contentStream.curveTo(cx + r, cy - (k * r), cx + (k * r), cy - r, cx, cy - r);
|
||||
contentStream.curveTo(cx - (k * r), cy - r, cx - r, cy - (k * r), cx - r, cy);
|
||||
contentStream.fill();
|
||||
}
|
||||
|
||||
public static PDDocument generateFooter(PDDocument pdDocument) {
|
||||
int nbTotal = pdDocument.getNumberOfPages();
|
||||
int count = 1;
|
||||
|
||||
try {
|
||||
for (PDPage page : pdDocument.getPages()) {
|
||||
PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page,
|
||||
PDPageContentStream.AppendMode.APPEND, true);
|
||||
PDFont font = PDType1Font.TIMES_ROMAN;
|
||||
int width = (int) page.getMediaBox().getWidth();
|
||||
int fontSize = 10;
|
||||
pdPageContentStream.setFont(font, fontSize);
|
||||
String footer = String.valueOf(count) + " / " + String.valueOf(nbTotal);
|
||||
float titleWidth = (font.getStringWidth(footer) / 1000) * fontSize;
|
||||
float titleHeight = (font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000) * fontSize;
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset((width - titleWidth) / 2, (35 - titleHeight));
|
||||
pdPageContentStream.showText(footer);
|
||||
pdPageContentStream.endText();
|
||||
pdPageContentStream.close();
|
||||
count++;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return pdDocument;
|
||||
|
||||
}
|
||||
|
||||
public static PDDocument generateMarks(PDDocument pdDocument) {
|
||||
for (PDPage page : pdDocument.getPages()) {
|
||||
try {
|
||||
PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page,
|
||||
PDPageContentStream.AppendMode.APPEND, true);
|
||||
PDFont font = PDType1Font.TIMES_ROMAN;
|
||||
|
||||
int height = (int) page.getMediaBox().getHeight();
|
||||
int width = (int) page.getMediaBox().getWidth();
|
||||
|
||||
// Set a Color for the marks
|
||||
pdPageContentStream.setNonStrokingColor(Color.BLACK);
|
||||
pdPageContentStream.setNonStrokingColor(0, 0, 0); // black text
|
||||
pdPageContentStream.setFont(font, 9);
|
||||
|
||||
// generate circle marks in corners
|
||||
SubjectGenerator.drawCircle(pdPageContentStream, 20, height - 30, 5); // top left
|
||||
SubjectGenerator.drawCircle(pdPageContentStream, width - 20, height - 30, 5); // top right
|
||||
SubjectGenerator.drawCircle(pdPageContentStream, 20, 30, 5); // bottom left
|
||||
SubjectGenerator.drawCircle(pdPageContentStream, width - 20, 30, 5); // bottom right
|
||||
|
||||
pdPageContentStream.setLineWidth(0.6f); // largeur du contour des rectangles
|
||||
|
||||
// generate rectangles id (?)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
// draw first range of rectangles
|
||||
pdPageContentStream.addRect(170 + (9 * i), height - 15, 9, 9);
|
||||
// + 9 * i = position du ieme carre
|
||||
// draw second range of rectangles
|
||||
pdPageContentStream.addRect(170 + (9 * i), height - 27, 9, 9);
|
||||
// + 9 * i = position du ieme carre
|
||||
}
|
||||
|
||||
pdPageContentStream.setFont(font, 10);
|
||||
|
||||
// draw the separative line
|
||||
pdPageContentStream.moveTo(28, height - 239);
|
||||
pdPageContentStream.lineTo(width - 28, height - 239);
|
||||
|
||||
// pdPageContentStream.lineTo(width - 28, height - 239);
|
||||
pdPageContentStream.stroke(); // stroke
|
||||
|
||||
pdPageContentStream.setFont(font, 11);
|
||||
|
||||
// number (top of page) +n/n/nn+
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset((width / 2) + 86, height - 30);
|
||||
pdPageContentStream.showText("+1/1/60+");
|
||||
pdPageContentStream.endText();
|
||||
|
||||
// Sujet
|
||||
// center text : https://stackoverflow.com/a/6531362
|
||||
String subject = "Exemple PT S3T : de 1970 à l’an 2000, 30 ans d’histoire";
|
||||
int fontSize = 12;
|
||||
pdPageContentStream.setFont(font, fontSize);
|
||||
float titleWidth = (font.getStringWidth(subject) / 1000) * fontSize;
|
||||
float titleHeight = (font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000) * fontSize;
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset((width - titleWidth) / 2, (height - 57 - titleHeight));
|
||||
pdPageContentStream.showText(subject);
|
||||
pdPageContentStream.endText();
|
||||
|
||||
String subtitle = "Tricherie : Toutes consultations de sources numériques sont interdites !!";
|
||||
titleWidth = (font.getStringWidth(subtitle) / 1000) * fontSize;
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset((width - titleWidth) / 2, (height - 71 - titleHeight));
|
||||
pdPageContentStream.showText(subtitle);
|
||||
pdPageContentStream.endText();
|
||||
|
||||
fontSize = 10;
|
||||
|
||||
// 1st line
|
||||
pdPageContentStream.setFont(font, fontSize);
|
||||
String numConsignePart1 = " Veuillez coder votre numéro";
|
||||
|
||||
titleWidth = (font.getStringWidth(numConsignePart1) / 1000) * fontSize;
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset(width - 224, height - 94 - titleHeight);
|
||||
pdPageContentStream.showText(numConsignePart1);
|
||||
pdPageContentStream.endText();
|
||||
|
||||
// 2nd line
|
||||
String numConsignePart2 = " d’étudiant ci-contre et écrire votre nom";
|
||||
|
||||
titleWidth = (font.getStringWidth(numConsignePart2) / 1000) * fontSize;
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset(width - 244, height - 105 - titleHeight);
|
||||
pdPageContentStream.showText(numConsignePart2);
|
||||
pdPageContentStream.endText();
|
||||
|
||||
// 3rd line
|
||||
String numConsignePart3 = " dans la case ci-dessous.";
|
||||
|
||||
titleWidth = (font.getStringWidth(numConsignePart3) / 1000) * fontSize;
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset(width - 244, height - 118 - titleHeight);
|
||||
pdPageContentStream.showText(numConsignePart3);
|
||||
pdPageContentStream.endText();
|
||||
|
||||
pdPageContentStream.close();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
return pdDocument;
|
||||
}
|
||||
|
||||
/*
|
||||
* public static PDDocument generateIDPageArea(PDDocument pdDocument) {
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
public static PDDocument generateNameArea(PDDocument pdDocument) {
|
||||
try {
|
||||
PDPage page = pdDocument.getPage(0);
|
||||
PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page,
|
||||
PDPageContentStream.AppendMode.APPEND, true);
|
||||
PDFont font = PDType1Font.TIMES_ROMAN;
|
||||
|
||||
// Set a Color for the marks
|
||||
pdPageContentStream.setNonStrokingColor(Color.BLACK);
|
||||
pdPageContentStream.setNonStrokingColor(0, 0, 0); // black text
|
||||
pdPageContentStream.setFont(font, 9);
|
||||
|
||||
int height = (int) page.getMediaBox().getHeight();
|
||||
int width = (int) page.getMediaBox().getWidth();
|
||||
|
||||
// generate rectangle nom
|
||||
|
||||
pdPageContentStream.addRect(width - 238, height - 196, 155, 50); // RECT
|
||||
// text
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset(width - 236, height - 156);
|
||||
pdPageContentStream.showText("Ecrivez votre Nom");
|
||||
pdPageContentStream.endText();
|
||||
|
||||
// dot lines
|
||||
// TODO: Enleve car difficulte d'ocr du fait de la presence des pointilles
|
||||
// SubjectGenerator.drawDotedLine(pdPageContentStream, width - 233, height -
|
||||
// 175, width - 90, height - 175);
|
||||
// SubjectGenerator.drawDotedLine(pdPageContentStream, width - 233, height -
|
||||
// 190, width - 90, height - 190);
|
||||
|
||||
pdPageContentStream.stroke(); // stroke
|
||||
|
||||
// pdPageContentStream.fill();
|
||||
pdPageContentStream.closeAndStroke();
|
||||
|
||||
pdPageContentStream.close();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return pdDocument;
|
||||
}
|
||||
|
||||
public static PDDocument generateNumEtudAreaBis(PDDocument pdDocument) {
|
||||
try {
|
||||
PDPage page = pdDocument.getPage(0);
|
||||
PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page,
|
||||
PDPageContentStream.AppendMode.APPEND, true);
|
||||
PDFont font = PDType1Font.TIMES_ROMAN;
|
||||
|
||||
// Set a Color for the marks
|
||||
pdPageContentStream.setNonStrokingColor(Color.BLACK);
|
||||
pdPageContentStream.setNonStrokingColor(0, 0, 0); // black text
|
||||
pdPageContentStream.setFont(font, 9);
|
||||
|
||||
int height = (int) page.getMediaBox().getHeight();
|
||||
int width = (int) page.getMediaBox().getWidth();
|
||||
|
||||
// num rectangle
|
||||
pdPageContentStream.addRect(width / 4, height - 146, 150, 40);
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset((width / 4) + 2, height - 115);
|
||||
pdPageContentStream.showText("Ecrivez votre Numéro d'étudiant");
|
||||
pdPageContentStream.endText();
|
||||
|
||||
// note rectangle
|
||||
pdPageContentStream.addRect(width / 4, height - 200, 150, 40);
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset((width / 4) + 2, height - 170);
|
||||
pdPageContentStream.showText("Note");
|
||||
pdPageContentStream.endText();
|
||||
|
||||
pdPageContentStream.moveTo((width / 4) + 75, height - 160);
|
||||
pdPageContentStream.lineTo((width / 4) + 75, height - 200);
|
||||
|
||||
// dotedlines
|
||||
|
||||
// SubjectGenerator.drawDotedLine(pdPageContentStream, width - 233, height -
|
||||
// 175, width - 90, height - 175);
|
||||
|
||||
pdPageContentStream.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return pdDocument;
|
||||
}
|
||||
|
||||
public static PDDocument generateNumEtudArea(PDDocument pdDocument) {
|
||||
try {
|
||||
PDPage page = pdDocument.getPage(0);
|
||||
PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page,
|
||||
PDPageContentStream.AppendMode.APPEND, true);
|
||||
PDFont font = PDType1Font.TIMES_ROMAN;
|
||||
|
||||
// Set a Color for the marks
|
||||
pdPageContentStream.setNonStrokingColor(Color.BLACK);
|
||||
pdPageContentStream.setNonStrokingColor(0, 0, 0); // black text
|
||||
pdPageContentStream.setFont(font, 9);
|
||||
|
||||
int height = (int) page.getMediaBox().getHeight();
|
||||
|
||||
// generate rectangles numero etudiant
|
||||
for (int i = 0; i <= 9; i++) {
|
||||
// draw first range of rectangles
|
||||
pdPageContentStream.addRect(80 + (22 * i), height - 107, 11, 11);
|
||||
// write first range of numbers
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset(80 + (22 * i) + 12, height - 105);
|
||||
pdPageContentStream.showText(String.valueOf(i));
|
||||
pdPageContentStream.endText();
|
||||
// draw second range of rectangles
|
||||
pdPageContentStream.addRect(80 + (22 * i), height - 124, 11, 11);
|
||||
// write second range of numbers
|
||||
pdPageContentStream.beginText();
|
||||
pdPageContentStream.newLineAtOffset(80 + (22 * i) + 12, height - 122);
|
||||
pdPageContentStream.showText(String.valueOf(i));
|
||||
pdPageContentStream.endText();
|
||||
}
|
||||
|
||||
pdPageContentStream.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return pdDocument;
|
||||
}
|
||||
|
||||
public void generateHeader(PDDocument pdDocument) {
|
||||
try {
|
||||
PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, pdDocument.getPage(0));
|
||||
PDFont font = PDType1Font.HELVETICA_BOLD;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws IOException {
|
||||
// Create a Document object.
|
||||
PDDocument pdDocument = new PDDocument();
|
||||
// Create a Page object
|
||||
PDPage pdPage1 = new PDPage(PDRectangle.A4);
|
||||
// System.out.println("Height : " + pdPage1.getMediaBox().getHeight());
|
||||
// System.out.println("Width : " + pdPage1.getMediaBox().getWidth());
|
||||
PDPage pdPage2 = new PDPage(PDRectangle.A4);
|
||||
PDPage pdPage3 = new PDPage(PDRectangle.A4);
|
||||
|
||||
// Add the page to the document and save the document to a desired file.
|
||||
pdDocument.addPage(pdPage1);
|
||||
pdDocument.addPage(pdPage2);
|
||||
pdDocument.addPage(pdPage3);
|
||||
|
||||
pdDocument = SubjectGenerator.generateMarks(pdDocument);
|
||||
pdDocument = SubjectGenerator.generateNumEtudAreaBis(pdDocument);
|
||||
pdDocument = SubjectGenerator.generateNameArea(pdDocument);
|
||||
pdDocument = SubjectGenerator.generateFooter(pdDocument);
|
||||
|
||||
// pdDocument.save("C:\\Users\\Nico\\Desktop\\testPDFMarks.pdf");
|
||||
pdDocument.save("E:\\testPDFMarks.pdf");
|
||||
pdDocument.close();
|
||||
System.out.println("PDF saved to the location !!!");
|
||||
}
|
||||
}
|
66
src/commands/Analyse.java
Normal file
66
src/commands/Analyse.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package commands;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import picocli.CommandLine;
|
||||
//import picocli.CommandLine;
|
||||
import picocli.CommandLine.*;
|
||||
|
||||
|
||||
@Command(
|
||||
name = "-a",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "Analyse command - Questions' answers identification",
|
||||
footer = "",
|
||||
description = "\nAnalyzes scanned copies (pdf files) provided to identify student and questions' answers\n"
|
||||
)
|
||||
|
||||
|
||||
public class Analyse implements Callable <Void> {
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec;
|
||||
|
||||
@Option(names= {"-help"}, arity = "0", order = 1, description = "command help")
|
||||
boolean help;
|
||||
|
||||
@Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
|
||||
int step;
|
||||
|
||||
@Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
|
||||
int vb_level;
|
||||
|
||||
@Option(names= {"-d"}, arity = "1", order = 4, defaultValue = "copies", description ="directory")
|
||||
String directory_name;
|
||||
|
||||
@Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
|
||||
String source_path;
|
||||
|
||||
|
||||
|
||||
public Analyse(PrintStream out) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
if(help){
|
||||
CommandLine.usage(this.spec, System.out);
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
System.out.println("\nAnalyse mode activated ...\n");
|
||||
System.out.println("Update : "+step +"\n"+
|
||||
"Verbose : "+vb_level +"\n"+
|
||||
"Directory : "+directory_name +"\n"+
|
||||
"Source : "+source_path +"\n");
|
||||
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
64
src/commands/Build.java
Normal file
64
src/commands/Build.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package commands;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import picocli.CommandLine;
|
||||
//import picocli.CommandLine;
|
||||
import picocli.CommandLine.*;
|
||||
|
||||
|
||||
@Command(
|
||||
name = "-b",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "Build command - Create standard test copy",
|
||||
footer = "",
|
||||
description = "\nCreate a standard test copy accepted by the application.\n"
|
||||
)
|
||||
|
||||
|
||||
public class Build implements Callable <Void> {
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec;
|
||||
|
||||
@Option(names= {"-help"}, arity = "0", order = 1, description = "command help")
|
||||
boolean help;
|
||||
|
||||
@Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
|
||||
int step;
|
||||
|
||||
@Option(names= {"-v"}, arity = "0..1", defaultValue = "1", order = 3, description ="verbose mode")
|
||||
int vb_level;
|
||||
|
||||
@Option(names= {"-a"}, arity = "1", order = 4, defaultValue = "answer-sheet.pdf", description ="answer")
|
||||
String answer_name;
|
||||
|
||||
@Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
|
||||
String source_path;
|
||||
|
||||
|
||||
public Build(PrintStream out) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
if(help){
|
||||
CommandLine.usage(this.spec, System.out);
|
||||
}
|
||||
else {
|
||||
|
||||
System.out.println("\nBuild mode activated ...\n");
|
||||
System.out.println("Update : "+step +"\n"+
|
||||
"Verbose : "+vb_level +"\n"+
|
||||
"Directory : "+answer_name +"\n"+
|
||||
"Source : "+source_path +"\n");
|
||||
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
71
src/commands/Evaluate.java
Normal file
71
src/commands/Evaluate.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package commands;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import picocli.CommandLine;
|
||||
//import picocli.CommandLine;
|
||||
import picocli.CommandLine.*;
|
||||
|
||||
|
||||
@Command(
|
||||
name = "-e",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "Evaluate command - Mark evaluation ",
|
||||
footer = "",
|
||||
description = "\nEvaluate each copies' mark based on the analysis performed previously."
|
||||
+ " Can be executed several times to take changes into account.\n"
|
||||
)
|
||||
|
||||
|
||||
public class Evaluate implements Callable <Void> {
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec;
|
||||
|
||||
@Option(names= {"-help"}, arity = "0", order = 1, description = "command help")
|
||||
boolean help;
|
||||
|
||||
@Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
|
||||
int step;
|
||||
|
||||
@Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
|
||||
int vb_level;
|
||||
|
||||
@Option(names= {"-o"}, arity = "1", order = 4, defaultValue = "result.csv", description ="result")
|
||||
String result_name;
|
||||
|
||||
@Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
|
||||
String source_path;
|
||||
|
||||
|
||||
// public boolean isCsv(String file) {
|
||||
// return file.endsWith(".csv");
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
public Evaluate(PrintStream out) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
if(help){
|
||||
CommandLine.usage(this.spec, System.out);
|
||||
}
|
||||
else {
|
||||
|
||||
System.out.println("\nEvaluate mode activated ...\n");
|
||||
System.out.println("Update : "+step +"\n"+
|
||||
"Verbose : "+vb_level +"\n"+
|
||||
"Result : "+result_name +"\n"+
|
||||
"Source : "+source_path +"\n");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
73
src/commands/Generate.java
Normal file
73
src/commands/Generate.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package commands;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import picocli.CommandLine;
|
||||
//import picocli.CommandLine;
|
||||
import picocli.CommandLine.*;
|
||||
|
||||
|
||||
@Command(
|
||||
name = "-g",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "Generate command - Subject and answer generation",
|
||||
footer = "",
|
||||
description = "\nSubject generation and associated answer with the source document.\n"
|
||||
)
|
||||
|
||||
|
||||
public class Generate implements Callable <Void> {
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec;
|
||||
|
||||
@Option(names= {"-help"}, arity = "0", order = 1, description = "command help")
|
||||
boolean help;
|
||||
|
||||
@Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
|
||||
int step;
|
||||
|
||||
@Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
|
||||
int vb_level;
|
||||
|
||||
@Option(names= {"-t"}, arity = "1", order = 4, defaultValue = "topic-sheet.pdf", description ="topic")
|
||||
String topic_name;
|
||||
|
||||
@Option(names= {"-a"}, arity = "1", order = 5, defaultValue = "answer-sheet.pdf", description ="answer")
|
||||
String answer_name;
|
||||
|
||||
@Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
|
||||
String source_path;
|
||||
|
||||
|
||||
// public boolean isPdf(String file) {
|
||||
// return file.endsWith(".pdf");
|
||||
//
|
||||
// }
|
||||
|
||||
public Generate(PrintStream out) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
if(help){
|
||||
CommandLine.usage(this.spec, System.out);
|
||||
}
|
||||
else {
|
||||
|
||||
System.out.println("\nGenerate mode activated ...\n");
|
||||
System.out.println("Update : "+step +"\n"+
|
||||
"Verbose : "+vb_level +"\n"+
|
||||
"Topic : "+topic_name +"\n"+
|
||||
"Answer : "+answer_name +"\n"+
|
||||
"Source : "+source_path +"\n");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
70
src/commands/Produce.java
Normal file
70
src/commands/Produce.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package commands;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import picocli.CommandLine;
|
||||
//import picocli.CommandLine;
|
||||
import picocli.CommandLine.*;
|
||||
|
||||
|
||||
@Command(
|
||||
name = "-p",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "Produce command - Correction subject generation",
|
||||
footer = "\nProduce correction subject associated to the source file.\n",
|
||||
description = "description"
|
||||
)
|
||||
|
||||
|
||||
public class Produce implements Callable <Void> {
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec;
|
||||
|
||||
@Option(names= {"-help"}, arity = "0", order = 1, description = "command help")
|
||||
boolean help;
|
||||
|
||||
@Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
|
||||
int step;
|
||||
|
||||
@Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
|
||||
int vb_level;
|
||||
|
||||
@Option(names= {"-c"}, arity = "1", order = 4, defaultValue = "corrected-sheet.pdf", description ="sheet")
|
||||
String sheet_name;
|
||||
|
||||
@Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
|
||||
String source_path;
|
||||
|
||||
|
||||
// public boolean isPdf(String file) {
|
||||
// return file.endsWith(".pdf");
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
public Produce(PrintStream out) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
if(help){
|
||||
CommandLine.usage(this.spec, System.out);
|
||||
}
|
||||
else {
|
||||
|
||||
System.out.println("\nProduce mode activated ...\n");
|
||||
System.out.println("Update : "+step +"\n"+
|
||||
"Verbose : "+vb_level +"\n"+
|
||||
"Sheet : "+sheet_name +"\n"+
|
||||
"Source : "+source_path +"\n");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
169
src/commands/Read.java
Normal file
169
src/commands/Read.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package commands;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
|
||||
import picocli.CommandLine.*;
|
||||
import progressbar.ProgressBar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
|
||||
import config.Config;
|
||||
import csv.GenerateCSV;
|
||||
import ocr.GestionnaireCopies;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@Command(
|
||||
name = "-r",
|
||||
version = "Version 1.0",
|
||||
sortOptions = false,
|
||||
usageHelpWidth = 60,
|
||||
header = "Read command - Automatic entry",
|
||||
footer = "",
|
||||
description = "\nAnalyzes all scanned copies (pdf files) provided to recognize student's name and mark.\n"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
public class Read implements Callable <Void> {
|
||||
|
||||
public Logger logger = LogManager.getLogger(Read.class);
|
||||
|
||||
@Spec
|
||||
Model.CommandSpec spec;
|
||||
|
||||
@Option(names= {"-help"}, arity = "0", order = 1, description = "command help")
|
||||
boolean help;
|
||||
|
||||
@Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
|
||||
int step;
|
||||
|
||||
@Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
|
||||
public int vb_level;
|
||||
|
||||
@Option(names= {"-d"}, arity = "1", order = 4, defaultValue = "copies", description ="directory")
|
||||
String directory_name;
|
||||
|
||||
@Option(names= {"-o"}, arity = "1", order = 5, defaultValue = "result.csv", description ="result")
|
||||
String result_name;
|
||||
|
||||
@Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
|
||||
String source_path;
|
||||
|
||||
|
||||
// Flux de sortie si nécéssaire
|
||||
public Read(PrintStream out) {
|
||||
}
|
||||
|
||||
// Check de l'extension csv (à améliorer)
|
||||
public boolean isCsv(String file) {
|
||||
return file.endsWith(".csv");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
|
||||
// Niveau de debug selon verbosite
|
||||
|
||||
if (vb_level >= 0 && vb_level <=2) {
|
||||
Configurator.setLevel("commands", Level.FATAL);
|
||||
Configurator.setLevel("csv", Level.FATAL);
|
||||
}
|
||||
else if (vb_level >= 3 && vb_level <=4) {
|
||||
Configurator.setLevel("commands", Level.ERROR);
|
||||
Configurator.setLevel("csv", Level.ERROR);
|
||||
}
|
||||
else if (vb_level >= 5 && vb_level <=6) {
|
||||
Configurator.setLevel("commands", Level.WARN);
|
||||
Configurator.setLevel("csv", Level.WARN);
|
||||
}
|
||||
else if (vb_level >= 7 && vb_level <=8) {
|
||||
Configurator.setLevel("commands", Level.INFO);
|
||||
Configurator.setLevel("csv", Level.INFO);
|
||||
}
|
||||
else {
|
||||
Configurator.setLevel("commands", Level.DEBUG);
|
||||
Configurator.setLevel("csv", Level.DEBUG);
|
||||
}
|
||||
|
||||
// Help genere de la commande
|
||||
|
||||
if(help) {
|
||||
logger.info("Help for 'read' command executed");
|
||||
CommandLine.usage(this.spec, System.out);
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
//************* Progress Bar Prototype **************
|
||||
|
||||
// ProgressBar bar = new ProgressBar();
|
||||
//
|
||||
// System.out.println("\nReading pdf ...\n");
|
||||
//
|
||||
// bar.update(0, 1000);
|
||||
// for(int i=0;i<1000;i++) {
|
||||
// // do something!
|
||||
// //imgList.lenght * temps estimé par img
|
||||
// for(int j=0;j<10000000;j++)
|
||||
// for(int p=0;p<10000000;p++);
|
||||
// // update the progress bar
|
||||
// bar.update(i, 1000); // On ajoute 100/imgList.length à chaque temps estimé par image
|
||||
// }
|
||||
//
|
||||
// System.out.println("\nCopies correction succeed !\n");
|
||||
|
||||
//***************************************************
|
||||
|
||||
|
||||
// Log des parametres
|
||||
|
||||
logger.info("Read mode activated");
|
||||
logger.debug("Update : "+step);
|
||||
logger.debug("Verbose : "+vb_level);
|
||||
logger.debug("Directory : "+directory_name);
|
||||
logger.debug("Result : "+result_name);
|
||||
logger.debug("Source : "+source_path);
|
||||
|
||||
|
||||
if (!isCsv(result_name)) {
|
||||
result_name = result_name+".csv";
|
||||
logger.info("Result file name changed to '"+result_name+"'");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Config config = new Config(source_path); //Initialise le fichier de configuration selon le chemin donné
|
||||
config.readConfig();
|
||||
|
||||
String filePath = new File("").getAbsolutePath();
|
||||
|
||||
// Instantie l'OCR
|
||||
GestionnaireCopies ocr = new GestionnaireCopies(directory_name);
|
||||
|
||||
|
||||
logger.debug("CSV initialized with : "+ocr.createHashMapforCSV()+" , "+config.getParam().get("Code")+" , "+result_name);
|
||||
|
||||
GenerateCSV csv = new GenerateCSV(ocr.createHashMapforCSV(),config.getParam().get("Code"), result_name);
|
||||
|
||||
csv.createFile(); //Génère le fichier csv à partir de la HMap retournée par l'OCR
|
||||
|
||||
//Done !
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
0
src/config/.gitkeep
Normal file
0
src/config/.gitkeep
Normal file
286
src/config/Config.java
Normal file
286
src/config/Config.java
Normal file
@@ -0,0 +1,286 @@
|
||||
package config;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Config {
|
||||
private HashMap<String, String> param = new HashMap<String, String>(); // Hashmap des parametres de config, Key =
|
||||
// nom paramn,
|
||||
private ArrayList<Question> questions = new ArrayList<Question>();
|
||||
|
||||
private String source; // Chemin vers le fichier source
|
||||
|
||||
// Getters et setters
|
||||
public HashMap<String, String> getParam() {
|
||||
return param;
|
||||
}
|
||||
|
||||
public void setParam(HashMap<String, String> param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public ArrayList<Question> getQuestions() {
|
||||
return questions;
|
||||
}
|
||||
|
||||
public void setQuestions(ArrayList<Question> questions) {
|
||||
this.questions = questions;
|
||||
}
|
||||
|
||||
public boolean isParsable(String s) {
|
||||
try {
|
||||
Integer.valueOf(s);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Config(String s) {
|
||||
// Constructeur, prend en parametre le chemin vers le fichier source
|
||||
source = s;
|
||||
// Initialisation des parametres avec les valeurs par défaut.
|
||||
// Les élements avec des placeholders en valeur sont des élements qui ne servent
|
||||
// pas pour le moment
|
||||
param.put("PaperSize", "A4"); // A3 A4 A5 letter
|
||||
param.put("Title", "Placeholder"); // titre de l exam
|
||||
param.put("Presentation", "Placeholder"); // texte de consignes
|
||||
param.put("DocumentModel", "PlaceHolder"); // nom du fichier du modéle
|
||||
param.put("ShuffleQuestions", "1"); // 1 = qt mélangées, 0 = non mél
|
||||
param.put("ShuffleAnswers", "1"); // 1= proposition rép mélangées, 0= non
|
||||
param.put("Code", "8"); // code étudiant = 8 chiffres (entre 1 et 16)
|
||||
param.put("MarkFormat", "20/4"); // expl "20/4" pour des notes entre 0 et 20 notées é 0.25 points
|
||||
param.put("NameField", "Nom et Prénom"); // remplace le texte
|
||||
param.put("StudentField",
|
||||
"Veuillez coder votre numéro\r\n d'étudiant ci-contre et écrire votre nom \r\n dans la case ci-dessous");
|
||||
// sert à remplacer le petit texte qui demande de coder son numéro déétudiant et
|
||||
// inscrire son nom
|
||||
param.put("MarkField", "Veuillez coder le numéro de l'étudiant");
|
||||
param.put("SeparateAnswerSheet", "1"); // si 1 = feuille de réponse séparée.
|
||||
param.put("AnswerSheetTitle", "Title"); // titre é inscrire en tete de la feuille de rép
|
||||
param.put("AnswerSheetPresentation", "Presentation"); // Donne le texte de présentation de la feuille de réponse
|
||||
param.put("SingleSided", "Placeholder");// si valeur = 1, aucune page blanche entre feuille de sujet et de
|
||||
// réponse
|
||||
param.put("DefaultScoringS", "Placeholder");// Donne le baréme par défaut pour les questions simples
|
||||
param.put("DefaultScoringM", "Placeholder");// Donne le baréme par défaut pour les questions é choix multiple
|
||||
param.put("QuestionBlocks", "Placeholder");// prend 0 pour valeur pour permettre é la boite d'une question boite
|
||||
// d'etre coupé sur plusieurs pages, prend 1 sinon
|
||||
|
||||
}
|
||||
|
||||
public void readConfig() {
|
||||
// Methode pour lire le fichier config en chemin dans la variable source
|
||||
// Si une ligne du fichier correspond é un parametre, changer la valeur du
|
||||
// parametre avec celle dans le fichier (si valeur valide)
|
||||
// Gere aussi les questions dans le fichier source et les mets dans une liste de
|
||||
// questions.
|
||||
// Gestion de questions mais actuellement inutile pour le programme
|
||||
try {
|
||||
Scanner scan = new Scanner(new File(source), "UTF-8");
|
||||
String ligne;
|
||||
Question q;
|
||||
ligne = scan.nextLine();
|
||||
// ligne pour gerer le code FEFF en UTF-8 BOM qui peut apparaitre si le fichier
|
||||
// txt est edité avec windows notepad
|
||||
// ce caractere apparait uniquement en debut de fichier
|
||||
if (ligne.startsWith("\uFEFF"))
|
||||
ligne = ligne.substring(1);
|
||||
while (scan.hasNext() || !ligne.isEmpty() || ligne.equals(System.lineSeparator())) {
|
||||
if (!ligne.equals("")) {
|
||||
if (!(ligne.substring(0, 1).equals("#"))) // si ligne commence par un # c'est un commentaire, donc
|
||||
// on
|
||||
// l'ignore
|
||||
{
|
||||
if (ligne.substring(0, 1).equals("*")) // si ligne commence par une *, c'est une question
|
||||
{
|
||||
q = makeQuestion(ligne);
|
||||
ligne = scan.nextLine(); // on scan la prochaine ligne
|
||||
while (!ligne.equals("")) // tant que la ligne n'est pas vide, on lit la suite qui est
|
||||
// supposé
|
||||
// etre les reponses
|
||||
{
|
||||
q.addReponse(ligne);
|
||||
ligne = scan.nextLine();
|
||||
}
|
||||
questions.add(q);
|
||||
} else // si c'est pas une *, alors c'est un parametre (on ignore les lignes vides)
|
||||
{
|
||||
lireParam(ligne);
|
||||
}
|
||||
}
|
||||
}
|
||||
ligne = scan.nextLine();
|
||||
while (ligne.equals("")) // on saute les lignes vides avant de recommencer la boucle while
|
||||
ligne = scan.nextLine();
|
||||
}
|
||||
scan.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
// methode pour creer une question
|
||||
// methode utilisée é partir d'un string supposé lu sur un fichier config
|
||||
// TODO : gestion des options telles que coeff et frozenanswer
|
||||
public Question makeQuestion(String ligne) {
|
||||
Question q;
|
||||
String s = ligne.substring(1, 2); // on lit le caractere qui differencie chaque type de question
|
||||
switch (s) {
|
||||
|
||||
case "*":
|
||||
// si c'est une * alors c'est une question é choix multiple
|
||||
q = new Question(ligne.substring(3, ligne.length()), true);
|
||||
|
||||
break;
|
||||
|
||||
case "<":
|
||||
// si c'est une < alors c'est une question de type boite
|
||||
int debut = ligne.indexOf("="); // on cherche la position du =, le caractere apres le = sera le nb de lignes
|
||||
// de la boite
|
||||
int fin = ligne.indexOf(">"); // on cherce la position du >, la suite de ce caractere sera l'intitulé de la
|
||||
// question
|
||||
int nblignes = Integer.parseInt(ligne.substring(debut + 1, fin));
|
||||
q = new QuestionBoite(ligne.substring(fin + 2, ligne.length()), false, nblignes);
|
||||
break;
|
||||
|
||||
default:
|
||||
// si pas une des conditions citées en haut, alors c'est une question é choix
|
||||
// unique
|
||||
q = new Question(ligne.substring(2, ligne.length()), false);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
// modification des valeurs du hashmap param
|
||||
// lecture d'un string supposé lu sur un fichier config
|
||||
public void lireParam(String s) {
|
||||
int n = s.indexOf(":"); // recherche de position du premier ":" pour pouvoir separer le nom du param de
|
||||
// sa valeur
|
||||
if (n != -1) // si -1 alors il n'y a pas de : et donc ce n'est pas un paramètre
|
||||
{
|
||||
String spl[] = { s.substring(0, n), s.substring(n + 1, s.length()) };
|
||||
while (spl[1].substring(0, 1).equals(" "))
|
||||
spl[1] = spl[1].substring(1, spl[1].length());
|
||||
spl[0] = spl[0].toUpperCase().trim(); // pour eviter la casse, on met tout en upper case
|
||||
switch (spl[0]) // chaque case correspond é un parametre, pour le moment on ignore tout
|
||||
// parametre qui n'est pas utile au programme.
|
||||
{
|
||||
case "PAPERSIZE":
|
||||
setPaperSize(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "CODE":
|
||||
setCode(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "MARKFORMAT":
|
||||
setMarkFormat(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "NAMEFIELD":
|
||||
setNameField(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "STUDENTIDFIELD":
|
||||
setStudentIdField(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "MARKFIELD":
|
||||
setMarkField(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "SEPARATEANSWERSHEET":
|
||||
setSeparateAnswerSheet(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "ANSWERSHEETTITLE":
|
||||
setAnswerSheetTitle(spl[1]);
|
||||
|
||||
break;
|
||||
|
||||
case "ANSWERSHEETPRESENTATION":
|
||||
setAnswerSheetPresentation(spl[1]);
|
||||
|
||||
break;
|
||||
default: // parametre mal tapé ou non utile (pour le moment) au programme, on l'ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// liste des set de chaque valeur de parametre
|
||||
// actuellement, uniquement les parametres de l'étape 1 sont traités
|
||||
|
||||
// TODO
|
||||
// possibilité d'afficher sur la console messages de valeur invalide et valeur
|
||||
// par défaut utilisée en cas d'erreur si verbose
|
||||
public void setPaperSize(String s) {
|
||||
s = s.toUpperCase();
|
||||
s = s.trim();
|
||||
if (s.equals("A3") || s.equals("A4") || s.equals("A5") || s.equals("LETTER")) {
|
||||
param.replace("PaperSize", s);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCode(String s) {
|
||||
s = s.trim();
|
||||
if (isParsable(s)) {
|
||||
int n = Integer.parseInt(s);
|
||||
if (n >= 1 && n <= 16) {
|
||||
param.replace("Code", s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setMarkFormat(String s) {
|
||||
s = s.trim();
|
||||
if (s.equals("20/4") || s.equals("100")) {
|
||||
param.replace("MarkFormat", s);
|
||||
}
|
||||
}
|
||||
|
||||
public void setNameField(String s) {
|
||||
if (!s.equals("")) {
|
||||
param.replace("NameField", s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setStudentIdField(String s) {
|
||||
if (!s.equals("")) {
|
||||
param.replace("StudentIdField", s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setMarkField(String s) {
|
||||
if (!s.equals("")) {
|
||||
param.replace("MarkField", s);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSeparateAnswerSheet(String s) {
|
||||
s = s.trim();
|
||||
int n = Integer.parseInt(s);
|
||||
if (n == 0 || n == 1) {
|
||||
param.replace("SeparateAnswerSheet", s);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnswerSheetTitle(String s) {
|
||||
if (!s.equals("")) {
|
||||
param.replace("AnswerSheetTitle", s);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnswerSheetPresentation(String s) {
|
||||
if (!s.equals("")) {
|
||||
param.replace("AnswerSheetPresentation", s);
|
||||
}
|
||||
}
|
||||
}
|
80
src/config/Question.java
Normal file
80
src/config/Question.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Question {
|
||||
private String titre; // intitulé de la question
|
||||
private int coeff; // coefficient de la question, vide par défaut mais c'est une option possible
|
||||
private boolean multiple = false; // boolean pour savoir si c'est une question choix multiple
|
||||
private ArrayList<Reponse> reponses = new ArrayList<Reponse>(); // liste des reponses
|
||||
|
||||
//constructeur d'une question sans coeff
|
||||
public Question(String t, boolean b) {
|
||||
titre = t;
|
||||
multiple = b;
|
||||
}
|
||||
|
||||
//constructeur d'une question avec coeff
|
||||
public Question(String t, boolean b, int n) {
|
||||
titre = t;
|
||||
multiple = b;
|
||||
coeff = n;
|
||||
}
|
||||
|
||||
public ArrayList<Reponse> getReponses() {
|
||||
return reponses;
|
||||
}
|
||||
|
||||
public void setReponses(ArrayList<Reponse> reponses) {
|
||||
this.reponses = reponses;
|
||||
}
|
||||
|
||||
public int getCoeff() {
|
||||
return coeff;
|
||||
}
|
||||
|
||||
public void setCoeff(int n) {
|
||||
this.coeff = n;
|
||||
}
|
||||
|
||||
public String getTitre() {
|
||||
return titre;
|
||||
}
|
||||
|
||||
public void setTitre(String titre) {
|
||||
this.titre = titre;
|
||||
}
|
||||
|
||||
public boolean isMultiple() {
|
||||
return multiple;
|
||||
}
|
||||
|
||||
public void setMultiple(boolean multiple) {
|
||||
this.multiple = multiple;
|
||||
}
|
||||
|
||||
//rajout des reponses a la question
|
||||
//prend en parametre un string qui commence par + ou -
|
||||
//si le string commence pas par + ou - alors c'est la suite du titre
|
||||
public void addReponse(String ligne) {
|
||||
switch (ligne.substring(0, 1)) {
|
||||
case "+":
|
||||
// reponse correcte
|
||||
reponses.add(new Reponse(ligne.substring(2, ligne.length()), true));
|
||||
|
||||
break;
|
||||
|
||||
case "-":
|
||||
// reponse fausse
|
||||
reponses.add(new Reponse(ligne.substring(2, ligne.length()), false));
|
||||
break;
|
||||
|
||||
default:
|
||||
// si pas + ou - alors c'est la suite a la ligne du titre
|
||||
titre = (titre + "\n" + ligne);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO : methode pour verifier si la question a au moins une bonne reponse ET une mauvaise reponse
|
||||
|
||||
}
|
19
src/config/QuestionBoite.java
Normal file
19
src/config/QuestionBoite.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package config;
|
||||
|
||||
public class QuestionBoite extends Question {
|
||||
// Type de question differente du normal, c'est une question avec une boite de texte où l'étudiant saisira du texte
|
||||
private int nbligne; // nb de lignes dans la boite
|
||||
|
||||
public QuestionBoite(String t, boolean b, int nb) {
|
||||
super(t, b);
|
||||
nbligne = nb;
|
||||
}
|
||||
|
||||
public int getNbligne() {
|
||||
return nbligne;
|
||||
}
|
||||
|
||||
public void setNbligne(int nbligne) {
|
||||
this.nbligne = nbligne;
|
||||
}
|
||||
}
|
27
src/config/Reponse.java
Normal file
27
src/config/Reponse.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package config;
|
||||
|
||||
public class Reponse {
|
||||
private String intitule;
|
||||
private boolean juste = false;
|
||||
|
||||
public String getIntitule() {
|
||||
return intitule;
|
||||
}
|
||||
|
||||
public Reponse(String t, boolean b) {
|
||||
intitule = t;
|
||||
juste = b;
|
||||
}
|
||||
|
||||
public void setIntitule(String intitule) {
|
||||
this.intitule = intitule;
|
||||
}
|
||||
|
||||
public boolean isJuste() {
|
||||
return juste;
|
||||
}
|
||||
|
||||
public void setJuste(boolean juste) {
|
||||
this.juste = juste;
|
||||
}
|
||||
}
|
100
src/csv/GenerateCSV.java
Normal file
100
src/csv/GenerateCSV.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package csv;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class GenerateCSV {
|
||||
|
||||
Map<String, String> etudiants;
|
||||
int numLength;
|
||||
String path = "export";
|
||||
Logger logger = LogManager.getLogger(GenerateCSV.class);
|
||||
|
||||
public GenerateCSV(Map<String, String> map, String length, String pth) {
|
||||
this.etudiants = map;
|
||||
this.numLength = Integer.parseInt(length);
|
||||
this.path = path + "/" + pth;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Teste validité du numero etudiant (selon param de la config passé :
|
||||
// numLength)
|
||||
|
||||
public boolean isValid(String s) {
|
||||
int i = 0;
|
||||
logger.debug("Checking string validity");
|
||||
if (s.length() == this.numLength) {
|
||||
while (i < s.length()) {
|
||||
|
||||
int nb = Character.getNumericValue(s.charAt(i));
|
||||
|
||||
|
||||
if (nb < 0 || nb > 9) {
|
||||
|
||||
logger.fatal("Student id's characters are not recognized");
|
||||
return false;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
logger.debug("String validity ok");
|
||||
return true;
|
||||
} else {
|
||||
logger.fatal("Student id's length is not correct");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void createFile() {
|
||||
try (PrintWriter writer = new PrintWriter(new File(this.path))) {
|
||||
|
||||
logger.info("Creating csv file");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Student number");
|
||||
sb.append(';');
|
||||
sb.append("Grade");
|
||||
sb.append(System.getProperty("line.separator"));
|
||||
|
||||
writer.write(sb.toString());
|
||||
|
||||
if (!etudiants.isEmpty()) {
|
||||
|
||||
for (String etud : this.etudiants.keySet()) {
|
||||
|
||||
// Si etudiant HashMap est null, pas ecrit
|
||||
if (etud != null) {
|
||||
|
||||
if (this.isValid(etud)) {
|
||||
writer.write(etud + ";" + etudiants.get(etud) + System.getProperty("line.separator"));
|
||||
}
|
||||
else {
|
||||
logger.debug("Invalid id not added to csv");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
logger.debug("Null id not added to csv");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.info("File creation succeed");
|
||||
} else {
|
||||
logger.fatal("Students list for csv generation is empty");
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.fatal(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
316
src/lecturePdf/Recadrage.java
Normal file
316
src/lecturePdf/Recadrage.java
Normal file
@@ -0,0 +1,316 @@
|
||||
package lecturePdf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
||||
|
||||
public class Recadrage {
|
||||
String dir="";
|
||||
String filename="";
|
||||
BufferedImage img;
|
||||
|
||||
|
||||
public Recadrage(String directory,String file) {
|
||||
dir=directory;
|
||||
filename=file;
|
||||
File f =new File(dir+filename);
|
||||
try {
|
||||
img=ImageIO.read(f);
|
||||
} catch (IOException e) {
|
||||
//System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Recadrage(BufferedImage image) {
|
||||
img=image;
|
||||
}
|
||||
public Recadrage(){
|
||||
}
|
||||
|
||||
public boolean estDroite() { //determine si l'image png/jpg du pdf est droite (doit etre en noir et blanc)
|
||||
int count=0;
|
||||
boolean stop=false;
|
||||
for (int ty=0; ty<100 && !stop;ty++) {
|
||||
for (int tx=0;tx<img.getWidth();tx++) {
|
||||
|
||||
Color tmp=new Color(img.getRGB(tx, ty));
|
||||
if (tmp.getGreen()<20) {
|
||||
count++;
|
||||
stop=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count>img.getWidth()/5.4 && count <img.getWidth()/5)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setImage(BufferedImage entree){
|
||||
this.img=entree;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public BufferedImage automation() throws IOException {
|
||||
if (!this.estDroite()) {
|
||||
int[][] points=RdB();
|
||||
double angle=getAngle(points);
|
||||
System.out.println("l'angle est de = "+angle);
|
||||
img=rotate(img,angle);
|
||||
String nomImage="sortie";
|
||||
File nomfichier = new File("C:\\Users\\Xxsafirex\\Desktop\\Image\\" + nomImage + ".jpg");// ou jpg
|
||||
ImageIO.write(img, "JPG", nomfichier);//ou JPG
|
||||
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ArrayList<BufferedImage> listAutomation(ArrayList<BufferedImage>list){
|
||||
ArrayList<BufferedImage> retour =new ArrayList<BufferedImage>();
|
||||
|
||||
for (BufferedImage imag:list) {
|
||||
this.img=imag;
|
||||
try {
|
||||
this.automation();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
retour.add(this.img);
|
||||
}
|
||||
return retour;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public int[][] RdB() { // cherche les 4 points noirs
|
||||
int[][] roar = new int[img.getWidth()*img.getHeight()][2];
|
||||
|
||||
int[][] regroupY = new int[img.getWidth()*img.getHeight()][2];
|
||||
int boucleY=0;int groupYi=0;
|
||||
int i=0;
|
||||
int diamMax=0;
|
||||
int radius=8; // 19= limite de detection de checkCircle
|
||||
for (int ty=0; ty<img.getHeight();ty++) {
|
||||
for (int tx=0;tx<img.getWidth();tx++) {
|
||||
|
||||
Color tmp=new Color(img.getRGB(tx, ty));
|
||||
if (tmp.getGreen()<20) { //si le pixel est noir
|
||||
if (checkCircle(tx,ty,radius) ) { //verifie si un cercle de radius entoure le pixel
|
||||
roar[i][0]=tx;
|
||||
roar[i][1]=ty;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("fin");
|
||||
int tempora=0;
|
||||
int tmp=1;
|
||||
int roar2[][]=new int [img.getWidth()*img.getHeight()][2];
|
||||
roar2[0]=roar[0];
|
||||
for (int l=0;l<img.getHeight()*img.getWidth() && (roar[l][1]!=0 || roar[l][0]!=0);l++) {
|
||||
if((roar[l][0]-roar2[tmp-1][0])<5 || roar[l][1]-roar2[tmp-1][1]<5 ){ //x-(x-1)>5 ou y-(y-1)>5
|
||||
roar2[tmp][0]=roar[l][0]; //efface le precedent roar2 si il était a 1 pixel de diff
|
||||
roar2[tmp][1]=roar[l][1];
|
||||
}
|
||||
else {
|
||||
tmp++;
|
||||
roar2[tmp]=roar[l];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//boucle de determination des points noirs
|
||||
//System.out.println("roar2debut");
|
||||
int points[][]=new int [4][2];
|
||||
int lastRoar[][]=new int [roar2.length][2]; int boucl=0; int lasti=0;
|
||||
int t=0;
|
||||
for (int l=1;l<=img.getHeight()*img.getWidth() && (roar2[l-1][1]!=0 || roar2[l-1][0]!=0);l++) {
|
||||
|
||||
|
||||
|
||||
int diffx=roar2[l][0]-roar2[l-1][0];
|
||||
int diffy=roar2[l][1]-roar2[l-1][1];
|
||||
int diff=Math.abs(diffx)+Math.abs(diffy);
|
||||
if (diff>img.getWidth()*0.85)
|
||||
{
|
||||
points[t]=roar2[l];
|
||||
t++;
|
||||
}
|
||||
|
||||
if (diffx<10 && diffy<10) {
|
||||
boucl++;
|
||||
}
|
||||
else {
|
||||
lastRoar[lasti][0]=roar2[l-boucl/2][0];
|
||||
lastRoar[lasti][1]=roar2[l-boucl/2][1];
|
||||
lasti++;boucl=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//System.out.println("lasrorar");
|
||||
for (int l=0;l<=lastRoar.length && (lastRoar[l][1]!=0 || lastRoar[l][0]!=0);l++) {
|
||||
//System.out.println("x: "+lastRoar[l][0]+" y: "+lastRoar[l][1]); //reste a grouper les coord pour avoir le centre des ronds
|
||||
}
|
||||
|
||||
|
||||
for (int l=0;l<=lastRoar.length && (lastRoar[l][1]!=0 || lastRoar[l][0]!=0);l++) {
|
||||
boolean test=true;
|
||||
int maxPoint=0;
|
||||
for (int li=0;li<=points.length && (points[li][1]!=0 || points[li][0]!=0);li++) {
|
||||
int diffx= Math.abs(lastRoar[l][0]-points[li][0]);
|
||||
int diffy= Math.abs(lastRoar[l][1]-points[li][1]);
|
||||
boolean testx= diffx>img.getWidth()*0.85 || diffx<img.getWidth()*0.2; //diff <0.1 ou >0.8 x la largeur de feuille
|
||||
boolean testy= diffy>img.getHeight()*0.8 || diffy<img.getWidth()*0.2;
|
||||
boolean Repeat= diffx+diffy>img.getWidth()*0.2; //si point deja présent
|
||||
|
||||
if (!Repeat || (!testx || !testy) ) // si 0.2>diffx>0.8 ou "diffy" et
|
||||
{
|
||||
test=false;
|
||||
}
|
||||
maxPoint=li;
|
||||
}
|
||||
|
||||
if(test && maxPoint<2) {
|
||||
//System.out.println(lastRoar[l][0]+" "+lastRoar[l][1]);
|
||||
points[maxPoint+1][0]=lastRoar[l][0];
|
||||
points[maxPoint+1][1]=lastRoar[l][1];
|
||||
}
|
||||
}
|
||||
//System.out.println("point");
|
||||
for (int l=1;l<=points.length;l++) {
|
||||
System.out.println("x: "+points[l-1][0]+" y: "+points[l-1][1]);
|
||||
}
|
||||
|
||||
return points;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean checkCircle(int x,int y,int radius) {
|
||||
double pi=Math.PI; //3.14
|
||||
Color tmp;
|
||||
for (double k=-1;k<=1;k+=0.05) { // de 0 à 2 pi
|
||||
int px=x+(int)Math.round(radius*Math.cos(k*pi)); //px = pos x du contour du supposé cercle
|
||||
int py=y+(int)Math.round(radius*Math.sin(k*pi)); //diam calculé +/- 42 pixels
|
||||
if(py<0)py=0;
|
||||
if(py>img.getHeight())py=img.getHeight()-1;
|
||||
if(px<0)px=0;
|
||||
if (px>img.getWidth())px=img.getWidth()-1;
|
||||
tmp=new Color(img.getRGB(px, py));
|
||||
if (tmp.getGreen()>20) { //si pixel == blanc
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public double getAngle(int[][] tab) {
|
||||
double[] res= new double[4];int resi=0;
|
||||
int cmpt=0;
|
||||
int angle=0;
|
||||
for (int i=0;i<tab.length;i++) {
|
||||
if (!(tab[i][0]==0) || !(tab[i][1]==0))
|
||||
cmpt++;
|
||||
}
|
||||
//System.out.println("cmpt = "+cmpt);
|
||||
|
||||
if (cmpt<=1) {
|
||||
return 0; //RIP CODE
|
||||
}
|
||||
|
||||
for (int i=1;i<tab.length && (!(tab[i][0]==0) || !(tab[i][1]==0));i++) {
|
||||
for(int c=1;i<tab.length && (tab[c][0]!=0 || tab[c][1]!=0);i++)
|
||||
{
|
||||
int diffx=tab[i-1][0]-tab[i][0];
|
||||
int diffy=tab[i-1][1]-tab[i][1];
|
||||
|
||||
double yb=tab[i][1];
|
||||
double xb=tab[i][0];
|
||||
double ya=tab[i-1][1];
|
||||
double xa=tab[i-1][0];
|
||||
|
||||
double pointy,pointx;
|
||||
pointy=yb; //pointy/x = coord du 3e point de triangle rectangle
|
||||
pointx=xa;
|
||||
//System.out.println("xb"+ xb + " xa "+xa);
|
||||
|
||||
double dhypo=Math.sqrt(Math.pow(xb-xa,2)+Math.pow(yb-ya,2));//(yb-ya)/(xb-xa);
|
||||
|
||||
|
||||
double dadj=Math.sqrt(Math.pow(xb-pointx, 2)+Math.pow(yb-pointy, 2)); //adjacent / rapport a xb,yb
|
||||
|
||||
System.out.println("dadj "+dadj + " dhypo "+dhypo);
|
||||
|
||||
|
||||
if (dhypo<img.getWidth() && dhypo!=0) { //deux points selectionnés sont des diagonales
|
||||
double retour=Math.acos(dadj/dhypo)*(180/Math.PI);
|
||||
if (retour>90/2)
|
||||
retour=180-90-retour;
|
||||
|
||||
if((xa<xb && ya<yb )||( xb<xa && yb<ya)) //point de droite plus haut que celui de gauche
|
||||
return -retour;
|
||||
else
|
||||
return retour;
|
||||
}
|
||||
/*else { //deux points sont en diagonnale
|
||||
double retour=Math.acos(dadj/dhypo)*(180/Math.PI); // ne marche pas
|
||||
return (Math.abs(45-retour)/2);
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//rotation de https://stackoverflow.com/questions/37758061/rotate-a-buffered-image-in-java
|
||||
public static BufferedImage rotate(BufferedImage bimg, double angle) {
|
||||
int w = bimg.getWidth();
|
||||
int h = bimg.getHeight();
|
||||
|
||||
BufferedImage rotated = new BufferedImage(w, h, bimg.getType());
|
||||
Graphics2D graphic = rotated.createGraphics();
|
||||
graphic.rotate(Math.toRadians(angle), w/2, h/2);
|
||||
graphic.drawImage(bimg, null, 0, 0);
|
||||
graphic.dispose();
|
||||
return rotated;
|
||||
}
|
||||
|
||||
|
||||
}
|
22
src/ocr/Copie.java
Normal file
22
src/ocr/Copie.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package ocr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class Copie {
|
||||
|
||||
ImagesCopie base;
|
||||
|
||||
public Copie(BufferedImage img) {
|
||||
this.base = new ImagesCopie(img);
|
||||
}
|
||||
|
||||
public ImagesCopie getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public void setBase(ImagesCopie base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
|
||||
}
|
126
src/ocr/GestionnaireCopies.java
Normal file
126
src/ocr/GestionnaireCopies.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package ocr;
|
||||
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
|
||||
|
||||
public class GestionnaireCopies {
|
||||
|
||||
private List<Copie> listeCopie;
|
||||
|
||||
private List<BufferedImage> copies;
|
||||
|
||||
public GestionnaireCopies(String chemin) {
|
||||
|
||||
copies = createImagesCopies(chemin);
|
||||
listeCopie = new ArrayList<>();
|
||||
|
||||
for(BufferedImage i : copies)
|
||||
{
|
||||
listeCopie.add(new Copie(i));
|
||||
|
||||
}
|
||||
applyOcr();
|
||||
|
||||
}
|
||||
|
||||
public List<BufferedImage> createImagesCopies(String path){
|
||||
|
||||
PdfToImage pdfAnalyzer = new PdfToImage();
|
||||
File pdfFile;
|
||||
PDDocument document = null;
|
||||
//LISTE DES IMAGES
|
||||
List<BufferedImage> images = new ArrayList<>(); // stockera les images (resultat)
|
||||
// CONVERT PAGES TO IMAGES
|
||||
|
||||
|
||||
try {
|
||||
|
||||
|
||||
// nom du fichier pdf à ouvrir (TODO: changer le chemin)
|
||||
List<String> files = pdfAnalyzer.listAllFiles(path, ".pdf");
|
||||
|
||||
for (String fname : files) {
|
||||
pdfFile = new File(fname);
|
||||
document = PDDocument.load(pdfFile); // charge le fichier pdf cree pour le traiter
|
||||
|
||||
images.addAll(pdfAnalyzer.convertPagesToBWJPG(document,1));
|
||||
// appelle la methode qui convertit les pages en images (jpg) noir et blanches
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
/*
|
||||
File img = new File("E:\\S3T\\Projet\\pt-s3t-g4\\pdf\\img_0.jpg");
|
||||
|
||||
BufferedImage in;
|
||||
try {
|
||||
in = ImageIO.read(img);
|
||||
|
||||
Image tmp = in.getScaledInstance(500, 331, Image.SCALE_SMOOTH);
|
||||
BufferedImage dimg = new BufferedImage(500, 331, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D g2d = dimg.createGraphics();
|
||||
g2d.drawImage(tmp, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
|
||||
|
||||
System.out.println(in.getHeight() + " " + in.getWidth());
|
||||
JFrame frame = new JFrame();
|
||||
frame.getContentPane().add(new JLabel(new ImageIcon(dimg)));
|
||||
//frame.getContentPane().add(new JLabel(new ImageIcon(images.get(0))));
|
||||
frame.setVisible(true);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
pdfAnalyzer.saveOnDisk(images, "E:\\S3T\\Projet\\pt-s3t-g4\\pdf\\");
|
||||
|
||||
|
||||
*/
|
||||
//LISTE DES IMAGES COMPRENANT L'IMAGE DE LA NOTE ET DU NUM ETUDIANT
|
||||
|
||||
return images;
|
||||
|
||||
}
|
||||
|
||||
public Map<String,String> createHashMapforCSV(){
|
||||
|
||||
HashMap<String,String> temp = new HashMap<>();
|
||||
|
||||
|
||||
for(Copie c : listeCopie)
|
||||
{
|
||||
|
||||
String numEtu = c.getBase().gethMapImgs().get("NumEtu").getDescription();
|
||||
String noteEtu = c.getBase().gethMapImgs().get("Note").getDescription();
|
||||
|
||||
temp.put(numEtu, noteEtu);
|
||||
}
|
||||
|
||||
return temp;
|
||||
|
||||
}
|
||||
|
||||
public void applyOcr()
|
||||
{
|
||||
for(Copie c : listeCopie)
|
||||
{
|
||||
c.getBase().applyOcrForEach();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
36
src/ocr/ImagesCopie.java
Normal file
36
src/ocr/ImagesCopie.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package ocr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Map;
|
||||
|
||||
public class ImagesCopie {
|
||||
|
||||
private Map<String,Img> hMapImgs;
|
||||
|
||||
|
||||
public ImagesCopie(BufferedImage imgOriginale) {
|
||||
|
||||
|
||||
hMapImgs = Rogneur.createHMapImgs(imgOriginale);
|
||||
}
|
||||
|
||||
public void applyOcrForEach() {
|
||||
|
||||
for(Img s : hMapImgs.values())
|
||||
{
|
||||
s.applyOcrImg();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Map<String, Img> gethMapImgs() {
|
||||
return hMapImgs;
|
||||
}
|
||||
|
||||
public void sethMapImgs(Map<String, Img> hMapImgs) {
|
||||
this.hMapImgs = hMapImgs;
|
||||
}
|
||||
|
||||
|
||||
}
|
41
src/ocr/Img.java
Normal file
41
src/ocr/Img.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package ocr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public abstract class Img {
|
||||
|
||||
BufferedImage img;
|
||||
String description;
|
||||
|
||||
public Img(BufferedImage img) {
|
||||
|
||||
this.img = img;
|
||||
|
||||
}
|
||||
|
||||
public abstract void applyOcrImg();
|
||||
|
||||
public BufferedImage getImg() {
|
||||
return img;
|
||||
}
|
||||
|
||||
public void setImg(BufferedImage img) {
|
||||
this.img = img;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void sanitizeDesc()
|
||||
{
|
||||
this.description = this.description.replace(" ", "");
|
||||
this.description = this.description.replace("\n", "");
|
||||
}
|
||||
|
||||
|
||||
}
|
23
src/ocr/ImgNote.java
Normal file
23
src/ocr/ImgNote.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package ocr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
|
||||
|
||||
|
||||
public class ImgNote extends Img{
|
||||
|
||||
public ImgNote(BufferedImage img) {
|
||||
super(img);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyOcrImg() {
|
||||
|
||||
setDescription(OCR.applyOcrNumber(getImg()));
|
||||
this.sanitizeDesc();
|
||||
|
||||
}
|
||||
|
||||
}
|
20
src/ocr/ImgNumEtu.java
Normal file
20
src/ocr/ImgNumEtu.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package ocr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
|
||||
|
||||
public class ImgNumEtu extends Img{
|
||||
|
||||
public ImgNumEtu(BufferedImage img) {
|
||||
super(img);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyOcrImg() {
|
||||
setDescription(OCR.applyOcrNumber(getImg()));
|
||||
this.sanitizeDesc();
|
||||
|
||||
}
|
||||
|
||||
}
|
28
src/ocr/OCR.java
Normal file
28
src/ocr/OCR.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package ocr;
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.sourceforge.tess4j.Tesseract;
|
||||
import net.sourceforge.tess4j.TesseractException;
|
||||
|
||||
public abstract class OCR {
|
||||
|
||||
|
||||
|
||||
public static String applyOcrNumber(BufferedImage img) {
|
||||
//FAIRE L'OCR
|
||||
Tesseract tesseract = new Tesseract();
|
||||
String str="";
|
||||
try {
|
||||
tesseract.setDatapath("Tess4J");
|
||||
tesseract.setLanguage("eng");
|
||||
//tesseract.setOcrEngineMode(2);
|
||||
tesseract.setTessVariable("tessedit_char_whitelist","0123456789");
|
||||
str=tesseract.doOCR(img);
|
||||
} catch (TesseractException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
111
src/ocr/PdfToImage.java
Normal file
111
src/ocr/PdfToImage.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package ocr;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
|
||||
import lecturePdf.Recadrage;
|
||||
|
||||
public class PdfToImage {
|
||||
|
||||
public List<String> listAllFiles(String directory, String extension) {
|
||||
// https://www.mkyong.com/java/java-how-to-list-all-files-in-a-directory/
|
||||
List<String> files = new ArrayList<String>();
|
||||
try (Stream<Path> walk = Files.walk(Paths.get(directory))) {
|
||||
// voir simplification si necessaire
|
||||
files = walk.map(x -> x.toString()).filter(f -> f.endsWith(extension)).collect(Collectors.toList());
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
public BufferedImage blackWhiteConvert(BufferedImage image) {
|
||||
// Convertit une image en image en noir et blanc
|
||||
// TODO : voir recursivite
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (image.getRGB(x, y) < 128) {
|
||||
image.setRGB(x, y, 0);
|
||||
} else {
|
||||
image.setRGB(x, y, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
public boolean isBlackWhite(BufferedImage image) {
|
||||
// verifie si une image est en noir et blanc
|
||||
// TODO : voir recursivite
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if ((image.getRGB(x, y) != 0) || (image.getRGB(x, y) != 255)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ArrayList<BufferedImage> convertPagesToBWJPG(PDDocument document, int n) {
|
||||
// convertit chaque page d'un document pdf en image noir et blanc
|
||||
// retourne une array liste d'images
|
||||
ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
try {
|
||||
int pageCounter = 0;
|
||||
for (PDPage page : document.getPages()) {
|
||||
if (pageCounter == n) {
|
||||
return images;
|
||||
}
|
||||
System.out.println("page.getRotation() : " + page.getRotation());
|
||||
System.out.println("pageCounter : " + pageCounter);
|
||||
BufferedImage bim = pdfRenderer.renderImageWithDPI(pageCounter++, 300, ImageType.BINARY); // BINARY =
|
||||
// noir et
|
||||
// blanc
|
||||
images.add(bim);
|
||||
System.out.println("Ajout n°" + pageCounter);
|
||||
}
|
||||
document.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
Recadrage recadrage=new Recadrage();
|
||||
return recadrage.listAutomation(images);
|
||||
//return images;
|
||||
|
||||
}
|
||||
|
||||
public void saveOnDisk(List<BufferedImage> images, String originalFileDir) {
|
||||
// sauvegarde sur le disque les images
|
||||
|
||||
int pageCounter = 0;
|
||||
try {
|
||||
for (BufferedImage img : images) {
|
||||
ImageIO.write(img, "JPEG", new File(originalFileDir + "img_" + pageCounter++ + ".jpg"));
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
79
src/ocr/Rogneur.java
Normal file
79
src/ocr/Rogneur.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package ocr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public abstract class Rogneur {
|
||||
|
||||
|
||||
|
||||
// Retourne une hashmap contenant une image et la description de son contenu
|
||||
public static Map<String, Img> createHMapImgs(BufferedImage imgOriginale) {
|
||||
|
||||
|
||||
Map<String,Img> temp = new HashMap<>();
|
||||
temp.put("NumEtu", rogneurNumEtu(imgOriginale));
|
||||
temp.put("Note", rogneurNote(imgOriginale));
|
||||
//temp.put("FormatNote", rogneurFormatNote(imgOriginale));
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
// rogne la partie du numEtu
|
||||
public static Img rogneurNumEtu(BufferedImage imgOriginale)
|
||||
{
|
||||
int ratioX = (imgOriginale.getWidth()/595);
|
||||
int ratioY = (imgOriginale.getWidth()/841);
|
||||
|
||||
int numEtuX1 = ratioX*((595/4)+ 4)+10;
|
||||
int numEtuY1 = ratioY*115 + 275;
|
||||
|
||||
int numEtuX2 = ratioX*((595/4)+150);
|
||||
int numEtuY2 = ratioY*146 + 310;
|
||||
|
||||
BufferedImage temp = imgOriginale.getSubimage(numEtuX1, numEtuY1, numEtuX2-numEtuX1, numEtuY2-numEtuY1);
|
||||
/*
|
||||
JFrame frame = new JFrame();
|
||||
frame.getContentPane().add(new JLabel(new ImageIcon(temp)));
|
||||
//frame.getContentPane().add(new JLabel(new ImageIcon(images.get(0))));
|
||||
frame.setVisible(true);
|
||||
*/
|
||||
return new ImgNumEtu(temp);
|
||||
|
||||
}
|
||||
|
||||
// rogne la partie de la note
|
||||
public static Img rogneurNote(BufferedImage imgOriginale)
|
||||
{
|
||||
int ratioX = (imgOriginale.getWidth()/595);
|
||||
int ratioY = (imgOriginale.getWidth()/841);
|
||||
|
||||
int numNoteX1 = ratioX*((595/4) + 4)+60;
|
||||
int numNoteY1 = ratioY*160+400;
|
||||
|
||||
int numNoteX2 = ratioX*((595/4) +80);
|
||||
int numNoteY2 = ratioY*200+400;
|
||||
|
||||
|
||||
BufferedImage temp = imgOriginale.getSubimage(numNoteX1, numNoteY1, numNoteX2-numNoteX1, numNoteY2-numNoteY1);
|
||||
|
||||
/*
|
||||
JFrame frame = new JFrame();
|
||||
frame.getContentPane().add(new JLabel(new ImageIcon(temp)));
|
||||
//frame.getContentPane().add(new JLabel(new ImageIcon(images.get(0))));
|
||||
frame.setVisible(true);
|
||||
*/
|
||||
return new ImgNote(temp);
|
||||
}
|
||||
|
||||
// rogne la partie du format de la note
|
||||
/*public static Img rogneurFormatNote(BufferedImage imgOriginale)
|
||||
{
|
||||
return imgOriginale.getSubimage(x, y, w, h);
|
||||
}*/
|
||||
}
|
15166
src/picocli/CommandLine.java
Normal file
15166
src/picocli/CommandLine.java
Normal file
File diff suppressed because it is too large
Load Diff
46
src/progressbar/ProgressBar.java
Normal file
46
src/progressbar/ProgressBar.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package progressbar;
|
||||
|
||||
// Source : https://masterex.github.io/archive/2011/10/23/java-cli-progress-bar.html
|
||||
|
||||
public class ProgressBar {
|
||||
private StringBuilder progress;
|
||||
|
||||
/**
|
||||
* initialize progress bar properties.
|
||||
*/
|
||||
public ProgressBar() {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* called whenever the progress bar needs to be updated.
|
||||
* that is whenever progress was made.
|
||||
*
|
||||
* @param done an int representing the work done so far
|
||||
* @param total an int representing the total work
|
||||
*/
|
||||
public void update(int done, int total) {
|
||||
char[] workchars = {'|', '/', '-', '\\'};
|
||||
String format = "\r%3d%% %s %c";
|
||||
|
||||
int percent = (++done * 100) / total;
|
||||
int extrachars = (percent / 2) - this.progress.length();
|
||||
|
||||
while (extrachars-- > 0) {
|
||||
progress.append('=');
|
||||
}
|
||||
|
||||
System.out.printf(format, percent, progress,
|
||||
workchars[done % workchars.length]);
|
||||
|
||||
if (done == total) {
|
||||
System.out.flush();
|
||||
System.out.println();
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.progress = new StringBuilder(60);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user