Update arborescence 2

This commit is contained in:
Louis Calas
2019-10-10 18:01:08 +02:00
parent 29dba04efb
commit a0b8e315db
167 changed files with 3 additions and 5 deletions

68
src/Exec.java Normal file
View 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;
}
}

View File

View 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 à lan 2000, 30 ans dhistoire";
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
View 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
View 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;
}
}

View 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;
}
}

View 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
View 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
View 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
View File

286
src/config/Config.java Normal file
View 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
View 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
}

View 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
View 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
View 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());
}
}
}

View 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
View 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;
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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);
}
}