Restructuration du projet, tout bien séparés dans des paquets MVC.

Ajout du document de présentation du projet.
This commit is contained in:
Mysaa 2021-05-24 16:18:45 +02:00
parent 2c0b74a366
commit e8ee1eb2a2
26 changed files with 2491 additions and 233 deletions

View File

@ -3,7 +3,7 @@
*
* This generated file contains a sample Java Library project to get you started.
* For more details take a look at the Java Libraries chapter in the Gradle
* user guide available at https://docs.gradle.org/4.10.2/userguide/java_library_plugin.html
* user guide available at https://docs.gradle.org/4.8.1/userguide/java_library_plugin.html
*/
plugins {
@ -21,13 +21,11 @@ dependencies {
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.13'
// https://mvnrepository.com/artifact/org.jopendocument/jOpenDocument
compile group: 'org.jopendocument', name: 'jOpenDocument', version: '1.3'
compile "org.libreoffice:juh:6.2.3"
compile "org.libreoffice:ridl:6.2.3"
compile "org.libreoffice:unoil:6.2.3"
compile "org.libreoffice:jurt:6.2.3"
compile "org.libreoffice:officebean:6.2.3"
}
// In this section you declare where to find the dependencies of your project

BIN
kholloscopinator.pdf Normal file

Binary file not shown.

235
kholloscopinator.tex Normal file
View File

@ -0,0 +1,235 @@
\documentclass[a4paper]{article}
\usepackage[margin=2.5cm]{geometry}
\usepackage[francais]{babel}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{enumitem}
\usepackage{censor}
\usepackage{cleveref}
\usepackage{tabularx}
\usetikzlibrary{shapes,snakes}
\title{Khôlloscopinator}
\author{Mysaa}
\date{2019}
\begin{document}
\maketitle
\tableofcontents
\newpage
Ce document traitera de comment sera codé Khôlloscopinator et de comment l'utiliser (en \LaTeX !).
Il sera utilisé pendant la phase de conception informatique.
\section{Entrées sorties du programme}
Cette section présentera les documents que pourra créer le programme et les données requises pour que la tâche soit accomplie.
\subsection{Cycle d'utilisation}
Présentons tout d'abord le cycle que parcourront les fichiers avant de créer le khôlloscope.
Pour des raisons de 'normalisation' des fichiers d'entrée, le programme générera d'abord des fichiers \emph{à compléter}
\begin{figure}[h]
\centering
\begin{tikzpicture}[shift={(current page.center)}]
\tikzstyle{file} = [rectangle,draw,text width=150,align=center]
\tikzstyle{debut} = [regular polygon,regular polygon sides=5,inner sep=0,outer sep=0,draw,scale=0.9]
\tikzstyle{actionA} = [->, >=latex]
\tikzstyle{action} = [midway,right,text width=150,anchor=west,align=right]
\node[debut] (start) at (0,7) {Démarrage};
\node[file] (template) at (0,4) {Les fichiers 'Template' générés};
\node[file] (rempli) at (0,2) {Les fichiers d'entrée remplis};
\node[file] (donnees) at (0,0) {Les fichiers contenant les données du khôlloscope};
\node[draw=none] (xl) at (6,7) {};
\node[draw=none] (xr) at (-6,7) {};
\draw[actionA] (start)--(template) node[action] {L'utilisateur demande au programme un template};
\draw[actionA] (template)--(rempli) node[action] {L'utilisateur remplis les données};
\draw[actionA] (rempli)--(donnees) node[action] {L'utilisateur lance le programme};
\end{tikzpicture}
\caption{Le cycle de création du khôlloscope}
\end{figure}
Au départ, l'utilisateur lance le programme avec les paramètres de son futur khôlloscope: calendrier, inclusion de la génération des groupes ou non, etc ... (Voir les Entrées en \ref{inputs})
Une fois que le programme a généré ces fichiers vides, l'utilisateur va pouvoir les remplir (voire les faire remplir) convenablement : Horaires de disponibilités pour les khôlleurs, pour les élèves, les spécificités des élèves (LV2,PSI ...), les groupes si ils ne sont pas à générer, etc...
Ensuite, l'utilisateur pourra relancer le programme dans le même dossier, ce dernier s'occupera d'acquérir ces données et de générer un khôlloscope convenant aux besoins de l'utilisateur, qui sautera de joie et embrassera l'ordinateur de joie (pensez à vérifier l'étanchéité des machines)
\subsection{Entrées}\label{inputs}
Cette partie va donc lister les entrées nécessaires ou facultatives, pour qu'un khôlloscope puisse être généré et quelles restrictions ces dernieres doivent avoir.
\setlist[description]{style=nextline}
\begin{description}
\item[Calendrier de l'année/semestre] Rentrer les jours féries, les horaires bloqués (repas de noël), les vacances, les semaines 1 ou 2 ...
\item[Liste des Khôlleurs] Le nom, la matière, des informations complémentaires
\item[Liste des Élèves] Nom, prénom, les différents groupes auxquels l'élève appartient (desquels découlerons ses contraintes dans l'emploi du temps) par exemple (A,INFO2,PSI)
\item[Disponibilités Khôlleurs] Deux types de fichiers différent :
\begin{itemize}[label=\textbullet]
\item Un fichier général où l'utilisateur fourni les disponibilités de tous les khôlleurs. À utiliser lorsque l'utilisateur a une seule disponibilité à rajouter ou à enlever
\item Un dossier de fichiers, avec un fichier par khôlleur . L'utilisateur pourrai envoyer ces fichiers à remplir aux différents khôlleurs, pour les faire remplir.
\end{itemize}
Le programme va ensuite synthétiser les deux types de fichiers pour référencer les disponibilités des khôlleurs.
\item[EDT élèves] Séparer les semaines 1 des semaines 2, possibilité d'organiser des semaines spéciales (à l'emploi du temps unique dans l'année). Ces dernières seront gérées comme des semaines d'un autre type (par exemple S3,S4 ou plus) et seront à préciser dans le calendrier.
Dans cet emploi du temps, préciser les groupes concernés par les horaire (un raccourci, le groupe X représentera tous les élèves). Échantillonnage élémentaire temporel : l'heure ou bien plus petit
\end{description}
\subsection{Sorties}
Cette partie va (je vous le donne en mille) lister les différents formes que pourra prendre le khôlloscope généré. Bien sur, tous ces différents types pourrons être générés en même temps, il s'agit là d'un changement de style d'affichage du khôlloscope, pas de génération (qui elle, sera discutée en partie \ref{khgen})
\begin{description}
\item[Khôlloscope condensé] Un khôlloscope basé sur celui donné l'année 2018-2019: un gros condensé des khôlles de tous les élèves, visible sur une seule page (typiquement le khôlloscope a imprimer en A3 pour afficher au fond de la salle)
\item[Khôlloscope par élève] Un dossiers de khôlloscopes présentés sous la forme d'une liste d'instants (date+heure) durant lesquels l'élève à une khôlle, en indiquant la matière, la salle et le professeur. De tels khôlloscopes serons similaires au sein d'un même groupe de khôlle, c'est pourquoi le programme proposera de générer les fichiers assignés aux élèves (plus simple à distribuer mais des doublons), ou alors de générer un fichier par groupe (à mettre en ligne, par exemple).
\item[Les fichiers \og fat\fg] Ces fichiers ne serons que des versions concaténées des fichiers précédents (un fichier contenant touts les khôlloscope par élève). Cela permettra d'imprimer la grande masse de papier plus facilement (au lieu d'imprimer chaque document une fois, imprimer une seule fois un gros document)
\item[Khôlloscope condensé par professeur] Il s'agit d'un khôlloscope avec le même affichage que le khôlloscope condensé, mais contenant seulement les lignes concernant le professeur en question.
\item[Khôlloscope liste par professeur] Une liste des khôlles à effectuer, présentées dans l'ordre chronologique. Seront précisés les jours/heures, les groupes à khôller et éventuellement les salles de khôlle (ou du moins un emplacement vide \og à compéter \fg)
\item[Khôlloscope calendrier par professeur] Il s'agit là d'une vue d'ensemble, des khôlles organisées sous la forme d'un calendrier où ne serons affichées que les heures auxquelles le khôlleur khôlle. Cela peux être imprimé en petit et collé à l'arrière de son casier.
\item[Khôlloscope pour élèves, mode liste] Un l'instar du khôlloscope liste pour les professeurs, ce khôlloscope présente les khôlles du semestre sous la forme d'une liste d'horaires (normalement deux par semaine). Ce document est facile à imprimer et contient toutes les informations nécessaires : date, heure, khôlleur, matière, salle (ou une case à compléter)
\item[Khôlloscope pour élèves, mode calendrier] Il s'agit d'un calendrier du semestre (sous la forme habituelle, mois-colonnes et lignes-jours). Dedans seront indiqué les noms des khôlleurs et les horaires. Là aussi, il ne contient pas beaucoup d'informations, et est plus destiné à satisfaire les rapides coups dœil \og Tiens, ai-je khôlle aujourd'hui ? \fg ou encore \og \censor{Merde} ! À quelle heure ai-je khôlle aujourd'hui ? \fg
\item[Le récapitulatif des groupes] Un simple tableau référençant les groupes, affichant par ligne les nom des trois membres, leur numéro de groupe et leurs \og contraintes \fg (voir \ref{contraintes_def})
\end{description}
\section{Conventions}
Je vais définir ici les éléments logiques de la création du khôlloscope.
\begin{description}
\item[Contraintes] \label{contraintes_def}Appliquées à un élève ou a un groupe de khôlle, il s'agit de l'ensemble des groupes auxquels appartient l'élève ou le groupe. Dans le cas du groupe, il s'agit de l'union des contraintes des élèves (exemple: un groupe formé d'un élève dans les groupes (A,I1,ALL) et d'un élève dans les groupes (A,I2) aura les contraintes (A,I1,I2,ALL)
\item[Horaire] Il s'agit d'une heure dans la semaine, contenant l'information (Jour de la semaine, heure de début). Par exemple, l'horaire (Mer,15h) correspond à l'heure s'écoulant de 15h à 16h les mercredis
\end{description}
\section{Algorithmie / Informatique}
Le programme suivra le pattern MVC (Model View Controller) qui sépare le code en trois parties distinctes :
\begin{itemize}
\item\textbf{Le Modèle (Model)} encodant les données utilisées et transférées (par exemple, les classes représentant les Khôlles, les Horaires, etc ... décrites en partie \ref{model})
\item\textbf{La Vue (View)} Régissant les flux d'entrées sortie avec l'utilisateur et les fichiers. Il va s'agir principalement de la fenêtre graphique, dans laquelle l'utilisateur rentrera ses options de génération et aura un retour du travail fait par l'algorithme
\item\textbf{Le Contrôlleur (Controller)} La partie qui va effectuer les travaux demandés par la partie Vue à travers des objets du Modèle. C'est dans cette partie que se fera tout le travail de génération, d'écriture des fichiers (tout la partie \textit{active}, en fait)
\end{itemize}
\subsection{Modèle}\label{model}
\subsubsection{Informatisations des données}
\og \textit{Donnez moi des bits, je vous encoderai le monde} \fg
Pour pouvoir rendre le programme le plus adaptable possible et sans descendre dans une complexité de classe trop hautes, certaines données basiques seront enregistrées sous la forme d'un type de base (int,string,etc...). Voici donc la liste de ces \og désobjetifications\fg des variables.
\begin{description}
\item[Appartenances] Les groupes auxquels appartiennent un élève seront représentés par une chaîne de caractères. Ces groupes sont les "Groupes d'informatique", les "groupes A \& B", etc\ldots. Les chaînes de caractères représenterons chaque groupe. Par exemple "I1" ou "A", mais on pourrait tout aussi bien mettre n'importe quelle autre chaîne, comme "\verb|le_meilleur_des_groupes|" voire "\verb|#@~&§!%£|" (l'utilité de la chose reste néanmoins à prouver).
\item[Matières] Les matières scolaires seront décrites comme des chaînes de caractères, en majuscules, possiblement abrégées. La convention de nommage doit bien entendu rester la même tout le long de la génération du khôlloscope. On aura ainsi les matières "\verb|MATHS|","\verb|PHYSIQUE|" ou encore "\verb|ANG|"
\end{description}
\subsubsection{Les Classes}
Afin d'obtenir un code lisible et \og beau \fg, de nombreuses classes aux rôles bien spécifiques devront être crées, leurs sens et leurs attributs vont être présentés ici.
À noter que un vocabulaire lié au POO (Programmation orientée objet) va être utilisée dans cette partie. Si vous ne connaissez pas les termes objet, classe, instance ou attribut, sauter cette partie peut être une bonne idée.
\begin{description}
\item[Élève] Une instance de cette classe représente un élève, et ce de manière unique. Il contient le nom, prénom et toutes les autres informations personnelles, ainsi que les contraintes de l'élève (voir partie \ref{contraintes_def} pour les définitions)
\item[Groupe] Une instance de cette classe représente un groupe d'élèves dans un khôlloscope. C'est à dire, que si plusieurs khôlloscopes existent en même temps, même si ils possèdent des groupes constitués identiquement, ils contiendrons leur propre de \textit{Groupe}), sauf si les groupes sont donnés par l'utilisateur, auquel cas, tous les khôlloscopes partagerons les mêmes instances de groupe. Les groupes n'auront comme attribut que la liste des élèves membres, ainsi que la liste des contraintes associées au groupe.
\item[Khôlleur] À l'instar de celle des élèves, les instances de cette classe représenteront un khôlleur de manière unique. Elles contiendrons les informations tel que le Nom, la matière enseignée, ainsi que d'autres informations personnelles
\end{description}
\subsection{Génération du khôlloscope}
\label{khgen}
Voici la partie la plus délicate (et bien évidemment le cœur du programme).
La génération se fera en plusieurs étapes, présentées ci-dessous.
\subsubsection{Étape 1 : Analyse des possibles et impossibles}
Cette première étape est plutôt simple et rapide. Son rôle est de supprimer tout horaire ou date impossible à satisfaire (par exemple, un khôlleur ayant un horaire libre pendant que tous les élèves auront cours : cet horaire ne pourra jamais être utilisé et sera donc supprimé) réduisant ainsi la taille et la quantité des données d'entrée à traiter, et donc le temps dexécution
\subsubsection{Étape 2 : Taggage}
L'étape de taggage (en anglais, to tag = coller une étiquette) permettra au programme d'être plus simple à coder. En effet, les horaires, élèves, khôlleurs, etc... se verront accolés de nombreux tags, par exemple pour indiquer que les élèves d'un certain groupe ne pourrons jamais rencontrer un khôlleur, ou que certaines khôlles bien qu'à des horaires déconseillés (voir \ref{crit_kh}) devront être effectuées pour respecter la contrainte de diversité des khôlleurs. Ces \og tags \fg seront utilisés durant les générations des khôlloscopes pour éviter d'en générer de trop pourris (c'est à dire ne respectant que peu les contraintes) qui seraient tout de suite invalidés. (À noter que le caractère aléatoire de la génération rendra toujours possible la génération fortuite d'un khôlloscope pourri, mais qui sera sous-classé face à d'autres khôlloscopes, meilleurs).
\subsubsection{Étape 3 : Créations des khôlloscopes}
Viens la section la plus complexe : des khôlloscopes seront générés semaine par semaine jusqu'à ce qu'une impossibilité arrive (c'est probable). Les conditions initiales seront tirées au hasard, mais avec un hasard pondéré, de manière à vérifier avec une plus forte probabilité les critères de Khôlloscope. Le programme va ainsi lancer plusieurs générations de Khôlloscope. Pour des raisons pratiques, chaque génération sera lancée dans des \textit{threads} (processus) parallèles. Les semaines se remplirons de Khôlles jusqu'à ce que tout soit rempli ou jusqu'à ce qu'une impossibilité survienne (par exemple, nécessite mais impossibilité de placer une khôlle d'anglais)
\subsubsection{Étape 4 : Qui est le meilleur}
Pour cette étape, il suffit d'affecter un score à chaque khôlloscope complètement généré, afin de n'afficher que les meilleurs. Les critères et leur importance pour le calcul du score seront vues en \ref{score_kh}. Un algorithme génétique serait une idée, mais le jeu de nombre aléatoires n'évoluant pas de manière continue, nous ne pourrons faire converger les khôlloscopes vers un objet stable.
\subsection{Qu'es-ce qu'un khôlloscope ?}
Mais comment doit faire le programme pour déterminer si un khôlloscope est bon ou non ?
\subsubsection{Critères de génération}
\label{crit_kh}
Je vais ici lister les critères que devrons respecter les khôlloscopes. Cela se présentera sous la forme d'un tableau listant:
\begin{description}
\item[Importance] Cette valeur permet de classer les critères, les plus basses valeurs étant les plus \og dispensables\fg
\item[Decription] Une description du critère
\item[Fallback] Que faire si le critère ne peut être satisfait (exemple : avoir tous les khôlleurs alors que c'est impossible à cause de l'emploi du temps)
\end{description}
\begin{tabularx}{\textwidth}{|c|X|X|}
\hline
Importance & Description & Fallback \\\hline
$\infty$ & Tous les élèves doivent avoir les khôlles demandées par semaine & Les repousser dans les deux semaines avant ou après, les annuler sinon \\\hline
$\infty$ & Les élèves doivent voir tous les khôlleurs, et les khôlleurs doivent être le mieux répartis (Éviter qu'un groupe n'ai principalement qu'un khôlleur) & Ne pas considérer les khôlleurs \og impossibles \fg mais essayer tout de même de respecter la diversité \\\hline
$\infty$ & Les élèves doivent pouvoir manger & Non négociable, invalidation du khôlloscope si non satisfait \\\hline
$\infty$ & Les groupes de khôlle doivent être de la bonne taille (par exemple, pas de groupe de un mais plutôt deux groupes de deux) & Invalidation du khôlloscope \\\hline
$\infty$ & Les professeurs ayant demandant un créneau repas doivent y avoir accès & Invalidation du khôlloscope, les professeurs sont aussi des humains \\\hline
$15$ & Éviter deux khôlles par jour & \\\hline
$11$ & Éviter les khôlles lors des grosses journées (par exemple, préférer les journées avec cours de sport, avec TD ...) & \\\hline
$10$ & Séparer les khôlleurs temporellement (éviter d'avoir un certain professeur trois fois de suite ...) & \\\hline
$9$ & Droit à la justice pour les élèves : tous les groupes de khôlle sont égaux :un même groupe ne doit pas se prendre, par exemple, un horaire de khôlle dérangeant cinq fois d'affilée & \\\hline
\end{tabularx}
Ce critères ont une valeur indicative, chacun correspondra à un module algorithmique indépendant, ce qui permettra de rajouter ou d'enlever des critères simplement. Ceci ne sont pas fixés et peuvent être modifiés, supprimés ou ajoutés.
\subsubsection{Score des Khôlloscopes}
\label{score_kh}
Le score des khôlloscope se basera principalement sur les critères dispensables. Si ils sont respectés, le khôlloscope sera bien noté. Leur importance dans le calcul (coefficients) sera jugée par rapport à leur \og Importance\fg donnée dans le tableau ci-dessus. Bien sur, d'autres mesures du score pourront être ajoutées au tableau suivant :
\begin{tabularx}{\textwidth}{|c|X|X|}
\hline
Importance & Description \\\hline
$10$ & Critère du dodo : les khôlles les moins tard seront à privilégier \\\hline
\end{tabularx}
\end{document}

View File

@ -4,7 +4,7 @@
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user guide at https://docs.gradle.org/4.10.2/userguide/multi_project_builds.html
* in the user guide at https://docs.gradle.org/4.8.1/userguide/multi_project_builds.html
*/
rootProject.name = 'Kholloscopinator'

View File

@ -1,15 +0,0 @@
package com.bernard.kholle;
import java.io.File;
import com.bernard.kholle.process.KholloscopeProcessor;
public class KholloMain {
public static void main(String[] args) {
System.out.println("Wiouw");
System.out.println(new File(".").getAbsolutePath());
KholloscopeProcessor.khollize(new File("./kholloscope2018_1.ods"));
}
}

View File

@ -1,7 +0,0 @@
package com.bernard.kholle.model;
public class Eleve {
String nom;
String prenom;
int[] groups;// 1(ALL) , 7(INFO2) ,...
}

View File

@ -1,12 +0,0 @@
package com.bernard.kholle.model;
public class Horaire {
String day;//Lun, Mar, Mer ...
String hour;//12-13,13-14,15-16, ...
byte[] place;// 1(S1), 2(S2)
byte[] tags;// 1(M , midi), 2(S, soir)
String[] profs;// LEVAUX, PRINCIAUX, LAMARTINE, ...
int[] groups;// 1(ALL) , 7(INFO2) ,...
}

View File

@ -1,8 +0,0 @@
package com.bernard.kholle.model;
public class KGroup {
Eleve[] élèves;
int[] constrains;// 1(ALL) , 7(INFO2) ,...
}

View File

@ -1,61 +0,0 @@
package com.bernard.kholle.model;
public class Kholle {
String tag,hour;
String semaine;
String prof;
int kGroup;
String salle;
public Kholle(String tag, String hour, String semaine, String prof, int kGroup, String salle) {
super();
this.tag = tag;
this.hour = hour;
this.semaine = semaine;
this.prof = prof;
this.kGroup = kGroup;
this.salle = salle;
}
@Override
public String toString() {
return "Kholle [tag=" + tag + ", hour=" + hour + ", semaine=" + semaine + ", prof=" + prof + ", kGroup="
+ kGroup + ", salle=" + salle + "]";
}
public String getTag() {
return tag;
}
public String getHour() {
return hour;
}
public String getSemaine() {
return semaine;
}
public String getProf() {
return prof;
}
public int getkGroup() {
return kGroup;
}
public String getSalle() {
return salle;
}
}

View File

@ -1,19 +0,0 @@
package com.bernard.kholle.process;
import java.util.Map;
import com.bernard.kholle.model.Eleve;
import com.bernard.kholle.model.Horaire;
import com.bernard.kholle.model.Kholle;
public class KholloMaker {
public static final Kholle[] findBestKholloscope(Eleve[] eleves, Horaire[] horaires, Map<String,String> profs /* {PRINCIAUX,Math},{BOUSSAGEON,Physique}*/) {
return null;
}
}

View File

@ -1,102 +0,0 @@
package com.bernard.kholle.process;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.jopendocument.dom.spreadsheet.Sheet;
import org.jopendocument.dom.spreadsheet.SpreadSheet;
import com.bernard.kholle.model.Kholle;
public class KholloscopeProcessor {
public static List<Kholle> khollize(File f){
List<Kholle> kholles = new ArrayList<>();
try {
SpreadSheet sheet = SpreadSheet.createFromFile(f);
Sheet khollesSheet = sheet.getFirstSheet();
parseCell(4, 19, 7, 21, khollesSheet, kholles);
parseCell(4, 19, 23, 35, khollesSheet, kholles);
parseCell(4, 19, 37, 46, khollesSheet, kholles);
System.out.println(kholles);
System.out.println(kholles.size());
} catch (IOException e) {
e.printStackTrace();
}
return kholles;
}
public static void parseCell(int x0,int x1,int y0,int y1,Sheet khollesSheet,List<Kholle> kholles) {
for(int i = y0;i<y1;i++) {
String prof = khollesSheet.getImmutableCellAt(0, i).getTextValue();//A voir pour les cell jointes
String time = khollesSheet.getImmutableCellAt(2, i).getTextValue();//A voir pour les cell jointes
String salle = khollesSheet.getImmutableCellAt(3, i).getTextValue();//A voir pour les cell jointes
for(int j = x0;j<x1;j++) {
String groupe = khollesSheet.getImmutableCellAt(j, i).getTextValue();
try {
int kGroup = Integer.parseInt(groupe);
kholles.add(new Kholle(time.split(" ")[0], time.split(" ")[1], khollesSheet.getImmutableCellAt(j, 2).getTextValue(), prof, kGroup, salle));
}catch(NumberFormatException e) {
}
}
}
}
public static List<String> sqlize(List<Kholle> kholles,Connection c){
List<String> statements = new ArrayList<>();
final String STATEMENT = "INSERT INTO kholles (ID,tag,hour,semaine,prof,kGroup,salle) VALUES (NULL,?,?,?,?,?,?)";
for(Kholle k : kholles) {
try {
PreparedStatement st = c.prepareStatement(STATEMENT);
st.setString(1, k.getTag());
st.setString(2, k.getHour());
st.setString(3, k.getSemaine());
st.setString(4, k.getProf());
st.setInt(5, k.getkGroup());
st.setString(6, k.getSalle());
try {
Class<?> stmt1 = st.getClass();
java.lang.reflect.Field mem = stmt1.getField("sql");
String value = (String)mem.get(st);
System.out.println(value);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
st.execute();
} catch (SQLException e) {
e.printStackTrace();
}
}
return statements;
}
}

View File

@ -0,0 +1,35 @@
package com.bernard.kholloscopinator;
import java.awt.Color;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Util {
public static List<Color> colors(int count) {
return colors(count,new Random());
}
public static List<Color> colors(int count,Random r) {
float startAngle = r.nextFloat();
return IntStream.range(0, count)
.mapToDouble(i->startAngle+i/((float)count))
.mapToObj(h->Color.getHSBColor((float)h, 1.f, 1.f))
.collect(Collectors.toList());
}
public static Color complementaire(Color c) {
return new Color(0xFFFFFF - c.getRGB()&0xFFFFFF);
}
public static Integer toInt(Color c) {
int value = 0xFF0000 & c.getBlue()*0x010000
+ 0xFF00 & c.getGreen()*0x0100
+ 0xFF & c.getRed()*0x01;
System.out.println(Integer.toHexString(value));
return Integer.valueOf(value^0xFFFFFF);
}
}

View File

@ -0,0 +1,5 @@
package com.bernard.kholloscopinator.controlleur;
public class FileParser {
}

View File

@ -0,0 +1,606 @@
package com.bernard.kholloscopinator.controlleur;
import static com.sun.star.uno.UnoRuntime.queryInterface;
import java.awt.Color;
import java.io.File;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.bernard.kholloscopinator.Util;
import com.bernard.kholloscopinator.model.KConfig;
import com.bernard.kholloscopinator.model.Kholleur;
import com.bernard.kholloscopinator.model.Kholloscope;
import com.bernard.kholloscopinator.model.Semaine;
import com.sun.star.awt.Rectangle;
import com.sun.star.beans.PropertyState;
import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.PropertyVetoException;
import com.sun.star.beans.UnknownPropertyException;
import com.sun.star.beans.XPropertySet;
import com.sun.star.chart.XChartDocument;
import com.sun.star.chart.XDiagram;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.container.XIndexAccess;
import com.sun.star.container.XNameAccess;
import com.sun.star.container.XNameContainer;
import com.sun.star.document.XEmbeddedObjectSupplier;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.io.IOException;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.IndexOutOfBoundsException;
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.sheet.ConditionEntryType;
import com.sun.star.sheet.ConditionFormatOperator;
import com.sun.star.sheet.XCellRangeAddressable;
import com.sun.star.sheet.XCellRangesQuery;
import com.sun.star.sheet.XConditionEntry;
import com.sun.star.sheet.XConditionalFormat;
import com.sun.star.sheet.XConditionalFormats;
import com.sun.star.sheet.XSheetCellRanges;
import com.sun.star.sheet.XSpreadsheet;
import com.sun.star.sheet.XSpreadsheetDocument;
import com.sun.star.sheet.XSpreadsheets;
import com.sun.star.style.XStyle;
import com.sun.star.style.XStyleFamiliesSupplier;
import com.sun.star.table.CellHoriJustify;
import com.sun.star.table.CellRangeAddress;
import com.sun.star.table.XCell;
import com.sun.star.table.XCellRange;
import com.sun.star.table.XTableChart;
import com.sun.star.table.XTableCharts;
import com.sun.star.table.XTableChartsSupplier;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.uno.XInterface;
import com.sun.star.util.XMergeable;
public class FileWriter {
public static final String[] MONTHES = { "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août",
"Septembre", "Octobre", "Novembre", "Décembre" };
public static final String[] DAYS = { "Dim", "Lun", "'Mar", "Mer", "Jeu", "Ven", "Sam" };
public static final boolean writeKholloscope(Kholloscope kholloscope, Set<Kholleur> kholleurs,
List<Semaine> calendrier, KConfig config) {
// TODO
// oooooooooooooooooooooooooooStep 2oooooooooooooooooooooooooooooooooooooooooo
// open an empty document. In this case it's a calc document.
// For this purpose an instance of com.sun.star.frame.Desktop
// is created. The desktop provides the XComponentLoader interface,
// which is used to open the document via loadComponentFromURL
System.out.println("Opening an empty Calc document");
XSpreadsheetDocument myDoc = openCalc(OfficeController.xContext, null);
// oooooooooooooooooooooooooooStep 3oooooooooooooooooooooooooooooooooooooooooo
// create cell styles.
// For this purpose get the StyleFamiliesSupplier and the family
// CellStyle. Create an instance of com.sun.star.style.CellStyle and
// add it to the family. Now change some properties
try {
XStyleFamiliesSupplier xSFS = UnoRuntime.queryInterface(XStyleFamiliesSupplier.class, myDoc);
XNameAccess xSF = xSFS.getStyleFamilies();
XNameAccess xCS = UnoRuntime.queryInterface(XNameAccess.class, xSF.getByName("CellStyles"));
XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, myDoc);
XNameContainer oStyleFamilyNameContainer = UnoRuntime.queryInterface(XNameContainer.class, xCS);
XInterface oInt1 = (XInterface) oDocMSF.createInstance("com.sun.star.style.CellStyle");
oStyleFamilyNameContainer.insertByName("StyleS1", oInt1);
XPropertySet oCPS1 = UnoRuntime.queryInterface(XPropertySet.class, oInt1);
oCPS1.setPropertyValue("IsCellBackgroundTransparent", Boolean.FALSE);
oCPS1.setPropertyValue("CellBackColor", Integer.valueOf(6710932));
oCPS1.setPropertyValue("CharColor", Integer.valueOf(16777215));
XInterface oInt2 = (XInterface) oDocMSF.createInstance("com.sun.star.style.CellStyle");
oStyleFamilyNameContainer.insertByName("My Style2", oInt2);
XPropertySet oCPS2 = UnoRuntime.queryInterface(XPropertySet.class, oInt2);
oCPS2.setPropertyValue("IsCellBackgroundTransparent", Boolean.FALSE);
oCPS2.setPropertyValue("CellBackColor", Integer.valueOf(13421823));
} catch (Exception e) {
e.printStackTrace(System.err);
}
// oooooooooooooooooooooooooooStep 4oooooooooooooooooooooooooooooooooooooooooo
// get the sheet an insert some data.
// Get the sheets from the document and then the first from this container.
// Now some data can be inserted. For this purpose get a Cell via
// getCellByPosition and insert into this cell via setValue() (for floats)
// or setFormula() for formulas and Strings
XSpreadsheet xSheet = null;
try {
System.out.println("Getting spreadsheet");
XSpreadsheets xSheets = myDoc.getSheets();
XIndexAccess oIndexSheets = UnoRuntime.queryInterface(XIndexAccess.class, xSheets);
xSheet = UnoRuntime.queryInterface(XSpreadsheet.class, oIndexSheets.getByIndex(0));
} catch (Exception e) {
System.out.println("Couldn't get Sheet " + e);
e.printStackTrace(System.err);
}
System.out.println("Creating the Header");
insertIntoCell(1, 0, "JAN", xSheet, "");
insertIntoCell(2, 0, "FEB", xSheet, "");
insertIntoCell(3, 0, "MAR", xSheet, "");
insertIntoCell(4, 0, "APR", xSheet, "");
insertIntoCell(5, 0, "MAI", xSheet, "");
insertIntoCell(6, 0, "JUN", xSheet, "");
insertIntoCell(7, 0, "JUL", xSheet, "");
insertIntoCell(8, 0, "AUG", xSheet, "");
insertIntoCell(9, 0, "SEP", xSheet, "");
insertIntoCell(10, 0, "OCT", xSheet, "");
insertIntoCell(11, 0, "NOV", xSheet, "");
insertIntoCell(12, 0, "DEC", xSheet, "");
insertIntoCell(13, 0, "SUM", xSheet, "");
System.out.println("Fill the lines");
insertIntoCell(0, 1, "Smith", xSheet, "");
insertIntoCell(1, 1, "42", xSheet, "V");
insertIntoCell(2, 1, "58.9", xSheet, "V");
insertIntoCell(3, 1, "-66.5", xSheet, "V");
insertIntoCell(4, 1, "43.4", xSheet, "V");
insertIntoCell(5, 1, "44.5", xSheet, "V");
insertIntoCell(6, 1, "45.3", xSheet, "V");
insertIntoCell(7, 1, "-67.3", xSheet, "V");
insertIntoCell(8, 1, "30.5", xSheet, "V");
insertIntoCell(9, 1, "23.2", xSheet, "V");
insertIntoCell(10, 1, "-97.3", xSheet, "V");
insertIntoCell(11, 1, "22.4", xSheet, "V");
insertIntoCell(12, 1, "23.5", xSheet, "V");
insertIntoCell(13, 1, "=SUM(B2:M2)", xSheet, "");
insertIntoCell(0, 2, "Jones", xSheet, "");
insertIntoCell(1, 2, "21", xSheet, "V");
insertIntoCell(2, 2, "40.9", xSheet, "V");
insertIntoCell(3, 2, "-57.5", xSheet, "V");
insertIntoCell(4, 2, "-23.4", xSheet, "V");
insertIntoCell(5, 2, "34.5", xSheet, "V");
insertIntoCell(6, 2, "59.3", xSheet, "V");
insertIntoCell(7, 2, "27.3", xSheet, "V");
insertIntoCell(8, 2, "-38.5", xSheet, "V");
insertIntoCell(9, 2, "43.2", xSheet, "V");
insertIntoCell(10, 2, "57.3", xSheet, "V");
insertIntoCell(11, 2, "25.4", xSheet, "V");
insertIntoCell(12, 2, "28.5", xSheet, "V");
insertIntoCell(13, 2, "=SUM(B3:M3)", xSheet, "");
insertIntoCell(0, 3, "Brown", xSheet, "");
insertIntoCell(1, 3, "31.45", xSheet, "V");
insertIntoCell(2, 3, "-20.9", xSheet, "V");
insertIntoCell(3, 3, "-117.5", xSheet, "V");
insertIntoCell(4, 3, "23.4", xSheet, "V");
insertIntoCell(5, 3, "-114.5", xSheet, "V");
insertIntoCell(6, 3, "115.3", xSheet, "V");
insertIntoCell(7, 3, "-171.3", xSheet, "V");
insertIntoCell(8, 3, "89.5", xSheet, "V");
insertIntoCell(9, 3, "41.2", xSheet, "V");
insertIntoCell(10, 3, "71.3", xSheet, "V");
insertIntoCell(11, 3, "25.4", xSheet, "V");
insertIntoCell(12, 3, "38.5", xSheet, "V");
insertIntoCell(13, 3, "=SUM(A4:L4)", xSheet, "");
// oooooooooooooooooooooooooooStep 5oooooooooooooooooooooooooooooooooooooooooo
// apply the created cell style.
// For this purpose get the PropertySet of the Cell and change the
// property CellStyle to the appropriate value.
// change backcolor
chgbColor(1, 0, 13, 0, "My Style", xSheet);
chgbColor(0, 1, 0, 3, "My Style", xSheet);
chgbColor(1, 1, 13, 3, "My Style2", xSheet);
// oooooooooooooooooooooooooooStep 6oooooooooooooooooooooooooooooooooooooooooo
// insert a 3D chart.
// get the CellRange which holds the data for the chart and its RangeAddress
// get the TableChartSupplier from the sheet and then the TableCharts from it.
// add a new chart based on the data to the TableCharts.
// get the ChartDocument, which provide the Diagramm. Change the properties
// Dim3D (3 dimension) and String (the title) of the diagramm.
// insert a chart
Rectangle oRect = new Rectangle();
oRect.X = 500;
oRect.Y = 3000;
oRect.Width = 25000;
oRect.Height = 11000;
XCellRange oRange = UnoRuntime.queryInterface(XCellRange.class, xSheet);
XCellRange myRange = oRange.getCellRangeByName("A1:N4");
XCellRangeAddressable oRangeAddr = UnoRuntime.queryInterface(XCellRangeAddressable.class, myRange);
CellRangeAddress myAddr = oRangeAddr.getRangeAddress();
CellRangeAddress[] oAddr = new CellRangeAddress[1];
oAddr[0] = myAddr;
XTableChartsSupplier oSupp = UnoRuntime.queryInterface(XTableChartsSupplier.class, xSheet);
XTableChart oChart = null;
System.out.println("Insert Chart");
XTableCharts oCharts = oSupp.getCharts();
oCharts.addNewByName("Example", oRect, oAddr, true, true);
// get the diagramm and Change some of the properties
try {
oChart = (UnoRuntime.queryInterface(XTableChart.class,
UnoRuntime.queryInterface(XNameAccess.class, oCharts).getByName("Example")));
XEmbeddedObjectSupplier oEOS = UnoRuntime.queryInterface(XEmbeddedObjectSupplier.class, oChart);
XInterface oInt = oEOS.getEmbeddedObject();
XChartDocument xChart = UnoRuntime.queryInterface(XChartDocument.class, oInt);
XDiagram oDiag = xChart.getDiagram();
System.out.println("Change Diagramm to 3D");
XPropertySet oCPS = UnoRuntime.queryInterface(XPropertySet.class, oDiag);
oCPS.setPropertyValue("Dim3D", Boolean.TRUE);
System.out.println("Change the title");
Thread.sleep(200);
XPropertySet oTPS = UnoRuntime.queryInterface(XPropertySet.class, xChart.getTitle());
oTPS.setPropertyValue("String", "The new title");
} catch (Exception e) {
System.err.println("Changing Properties failed " + e);
e.printStackTrace(System.err);
}
try {
File dest = new File("./test.ods");
PropertyValue v = new PropertyValue("FilterName", -1, "", PropertyState.DEFAULT_VALUE);
XStorable store = UnoRuntime.queryInterface(XStorable.class, myDoc);
store.storeToURL(dest.toURI().toString(), new PropertyValue[] { v });
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("done");
// System.exit(0);
return false;
}
public static XSpreadsheetDocument openCalc(XComponentContext xContext, File in) {
// define variables
XMultiComponentFactory xMCF = null;
XComponentLoader xCLoader;
XSpreadsheetDocument xSpreadSheetDoc = null;
XComponent xComp = null;
try {
// get the servie manager rom the office
xMCF = xContext.getServiceManager();
// create a new instance of the desktop
Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
// query the desktop object for the XComponentLoader
xCLoader = UnoRuntime.queryInterface(XComponentLoader.class, oDesktop);
PropertyValue[] szArgs = new PropertyValue[] { new PropertyValue() };
szArgs[0].Name = "Hidden";
szArgs[0].Value = true;
String strDoc = (in == null) ? "private:factory/scalc" : in.toURI().toString();
xComp = xCLoader.loadComponentFromURL(strDoc, "_blank", 0, szArgs);
xSpreadSheetDoc = UnoRuntime.queryInterface(XSpreadsheetDocument.class, xComp);
} catch (Exception e) {
System.err.println("Impossible de créer le document");
e.printStackTrace();
}
return xSpreadSheetDoc;
}
public static void insertIntoCell(int CellX, int CellY, String theValue, XSpreadsheet TT1, String flag) {
XCell xCell = null;
try {
xCell = TT1.getCellByPosition(CellX, CellY);
} catch (com.sun.star.lang.IndexOutOfBoundsException ex) {
System.err.println("Could not get Cell");
ex.printStackTrace(System.err);
}
if (flag.equals("V")) {
xCell.setValue((Float.valueOf(theValue)).floatValue());
} else {
xCell.setFormula(theValue);
}
}
public static void chgbColor(int x1, int y1, int x2, int y2, String template, XSpreadsheet TT) {
XCellRange xCR = null;
try {
xCR = TT.getCellRangeByPosition(x1, y1, x2, y2);
} catch (com.sun.star.lang.IndexOutOfBoundsException ex) {
System.err.println("Could not get CellRange");
ex.printStackTrace(System.err);
}
XPropertySet xCPS = UnoRuntime.queryInterface(XPropertySet.class, xCR);
try {
xCPS.setPropertyValue("CellStyle", template);
} catch (Exception e) {
System.err.println("Can't change colors chgbColor" + e);
e.printStackTrace(System.err);
}
}
public static List<Semaine> readCalendar(File entree) {
/// Ouverture d'un nouveau document ///
XSpreadsheetDocument myDoc = openCalc(OfficeController.xContext, entree);
try {
/// Création des styles pour la coloration automatique ///
XStyleFamiliesSupplier styleFamiliesSupplier = UnoRuntime.queryInterface(XStyleFamiliesSupplier.class,
myDoc);
XNameAccess styleFamilies = styleFamiliesSupplier.getStyleFamilies();
XNameAccess cellStyles = UnoRuntime.queryInterface(XNameAccess.class,
styleFamilies.getByName("CellStyles"));
XNameContainer cellStylesContainer = UnoRuntime.queryInterface(XNameContainer.class, cellStyles);
XStyle styleAnnee;
styleAnnee = queryInterface(XStyle.class, cellStylesContainer.getByName("StyleAnnee"));
XPropertySet styleAnneeProprietes = UnoRuntime.queryInterface(XPropertySet.class, styleAnnee);
System.out.println(Arrays.stream(styleAnneeProprietes.getPropertySetInfo().getProperties()).map(p -> {
try {
return p.Name + "->" + styleAnneeProprietes.getPropertyValue(p.Name);
} catch (UnknownPropertyException | WrappedTargetException e) {
e.printStackTrace();
}
return "";
}).sorted().collect(Collectors.joining("\n")));
} catch (NoSuchElementException | WrappedTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return null;
}
public static boolean genCalendar(Date startMonth, Date endMonth, int semTypes, File destination) {
if (!startMonth.before(endMonth)) {
System.err.println("La date de fin est avant la date de début");
return false;
}
Calendar startC = Calendar.getInstance(Locale.FRANCE);
startC.setTime(startMonth);
startC.set(Calendar.DAY_OF_MONTH, 1);
Calendar endC = Calendar.getInstance(Locale.FRANCE);
endC.setTime(endMonth);
endC.set(Calendar.DAY_OF_MONTH, -1);
int startYear = startC.get(Calendar.YEAR);
int yearDiff = endC.get(Calendar.YEAR) - startYear;
Map<Integer, List<Integer>> monthes = new HashMap<>();
if (yearDiff == 0) {
monthes.put(startC.get(Calendar.YEAR),
IntStream.range(startC.get(Calendar.MONTH), endC.get(Calendar.MONTH) + 1).mapToObj(x -> x)
.collect(Collectors.toList()));
} else {
monthes.put(startC.get(Calendar.YEAR),
IntStream.range(startC.get(Calendar.MONTH), 12 + 1).mapToObj(x -> x).collect(Collectors.toList()));
monthes.put(endC.get(Calendar.YEAR),
IntStream.range(1, endC.get(Calendar.MONTH) + 1).mapToObj(x -> x).collect(Collectors.toList()));
}
for (yearDiff--; yearDiff > 0; yearDiff--)
monthes.put(startC.get(Calendar.YEAR) + yearDiff,
IntStream.range(1, 12 + 1).mapToObj(x -> x).collect(Collectors.toList()));
yearDiff = endC.get(Calendar.YEAR) - startYear;
try {
/// Ouverture d'un nouveau document ///
XSpreadsheetDocument myDoc = openCalc(OfficeController.xContext, null);
/// Création des styles pour la coloration automatique ///
XMultiServiceFactory multiServiceFactory = UnoRuntime.queryInterface(XMultiServiceFactory.class, myDoc);
XStyleFamiliesSupplier styleFamiliesSupplier = UnoRuntime.queryInterface(XStyleFamiliesSupplier.class,
myDoc);
XNameAccess styleFamilies = styleFamiliesSupplier.getStyleFamilies();
XNameAccess cellStyles = UnoRuntime.queryInterface(XNameAccess.class,
styleFamilies.getByName("CellStyles"));
XNameContainer cellStylesContainer = UnoRuntime.queryInterface(XNameContainer.class, cellStyles);
List<Color> couleurs = Util.colors(semTypes + 10);
Collections.shuffle(couleurs);
for (int i = 0; i < semTypes + 10; i++) {
XStyle styleSemaine = queryInterface(XStyle.class,
multiServiceFactory.createInstance("com.sun.star.style.CellStyle"));
cellStylesContainer.insertByName("StyleS" + i, styleSemaine);
XPropertySet oCPS1 = UnoRuntime.queryInterface(XPropertySet.class, styleSemaine);
colorCell(oCPS1, couleurs.get(i));
}
XStyle styleAnnee = queryInterface(XStyle.class,
multiServiceFactory.createInstance("com.sun.star.style.CellStyle"));
cellStylesContainer.insertByName("StyleAnnee", styleAnnee);
XPropertySet styleAnneeProprietes = UnoRuntime.queryInterface(XPropertySet.class, styleAnnee);
styleAnneeProprietes.setPropertyValue("HoriJustify", CellHoriJustify.CENTER);
colorCell(styleAnneeProprietes, Color.ORANGE);
XStyle styleSVacances = queryInterface(XStyle.class,
multiServiceFactory.createInstance("com.sun.star.style.CellStyle"));
cellStylesContainer.insertByName("StyleSVacances", styleSVacances);
XPropertySet styleSVacancesProprietes = UnoRuntime.queryInterface(XPropertySet.class, styleSVacances);
styleSVacancesProprietes.setPropertyValue("HoriJustify", CellHoriJustify.CENTER);
colorCell(styleSVacancesProprietes, Color.DARK_GRAY);
XInterface styleMois = (XInterface) multiServiceFactory.createInstance("com.sun.star.style.CellStyle");
cellStylesContainer.insertByName("StyleMois", styleMois);
XPropertySet styleMoisProprietes = UnoRuntime.queryInterface(XPropertySet.class, styleMois);
styleMoisProprietes.setPropertyValue("HoriJustify", CellHoriJustify.CENTER);
colorCell(styleMoisProprietes, Color.YELLOW);
XInterface styleJour1 = (XInterface) multiServiceFactory.createInstance("com.sun.star.style.CellStyle");
cellStylesContainer.insertByName("StyleJour1", styleJour1);
XPropertySet styleJour1Propriétés = UnoRuntime.queryInterface(XPropertySet.class, styleJour1);
colorCell(styleJour1Propriétés, Color.WHITE);
XInterface styleJour2 = (XInterface) multiServiceFactory.createInstance("com.sun.star.style.CellStyle");
cellStylesContainer.insertByName("StyleJour2", styleJour2);
XPropertySet styleJour2Propriétés = UnoRuntime.queryInterface(XPropertySet.class, styleJour2);
colorCell(styleJour2Propriétés, Color.decode("0xdddddd"));
/// Récupération de la feuille ///
System.out.println("Getting spreadsheet");
XSpreadsheets xSheets = myDoc.getSheets();
XIndexAccess oIndexSheets = UnoRuntime.queryInterface(XIndexAccess.class, xSheets);
XSpreadsheet xSheet = UnoRuntime.queryInterface(XSpreadsheet.class, oIndexSheets.getByIndex(0));
/// Dessin du calendrier ///
int lastPosition = 0;
int weekTypeIndex = 0;
for (int i = 0; i < monthes.size(); i++) {
int year = startYear + i;
int newPosition = lastPosition + 2 * monthes.get(startYear + i).size();
mergeAndSet(xSheet.getCellRangeByPosition(lastPosition, 0, newPosition - 1, 0), Integer.toString(year),
"StyleAnnee");
for (int j = 0; j < monthes.get(year).size(); j++) {
int month = monthes.get(year).get(j) - 1;
int monthPos = lastPosition + 2 * j;
mergeAndSet(xSheet.getCellRangeByPosition(monthPos, 1, monthPos + 1, 1), MONTHES[month],
"StyleMois");
Calendar c = Calendar.getInstance(Locale.FRANCE);
c.setFirstDayOfWeek(Calendar.MONDAY);
c.setMinimalDaysInFirstWeek(1);
c.set(year, month, 1);
int monthLength = c.getActualMaximum(Calendar.DAY_OF_MONTH);
boolean toggleStyle = true;
for (int day = 1; day < monthLength + 1; day++) {
XCell cell = xSheet.getCellByPosition(monthPos, 1 + day);
c.set(year, month, day);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
setValue(cell,
DAYS[dayOfWeek - 1] + " " + Integer.toString(day) + " " + c.get(Calendar.WEEK_OF_MONTH),
"StyleJour" + (toggleStyle ? "1" : "2"));
toggleStyle = !toggleStyle;
}
c.set(year, month, 1);
int firstDay = 1;
while (firstDay <= monthLength) {
c.set(Calendar.DAY_OF_MONTH, firstDay);
int weekLength = 8 - realDayOfWeek(c.get(Calendar.DAY_OF_WEEK));
XCellRange range;
if (firstDay + weekLength <= monthLength) {
range = xSheet.getCellRangeByPosition(monthPos + 1, 1 + firstDay, monthPos + 1,
1 + firstDay + weekLength - 1);
weekTypeIndex = (weekTypeIndex + 1) % semTypes;
range.getCellByPosition(0, 0).setFormula("S" + (weekTypeIndex + 1));
} else {
range = xSheet.getCellRangeByPosition(monthPos + 1, 1 + firstDay, monthPos + 1,
1 + monthLength);
range.getCellByPosition(0, 0).setFormula("S" + (weekTypeIndex));
}
merge(range);
firstDay += weekLength;
}
}
lastPosition = newPosition;
}
XPropertySet sheetProperties = queryInterface(XPropertySet.class, xSheet);
XConditionalFormats conditionalFormats = queryInterface(XConditionalFormats.class,
sheetProperties.getPropertyValue("ConditionalFormats"));
// XIndexAccess conditionalFormatsAccess = queryInterface(XIndexAccess.class,
// conditionalFormats);
XCellRangesQuery querier = queryInterface(XCellRangesQuery.class, xSheet);
XSheetCellRanges ranges = querier.queryEmptyCells();
int id = conditionalFormats.createByRange(ranges);
System.out.println("Coucou" + conditionalFormats.getConditionalFormats().length);
XConditionalFormat format = conditionalFormats.getConditionalFormats()[0];// queryInterface(XConditionalFormat.class,
// conditionalFormatsAccess.getByIndex(id));
for (int s = 0; s < semTypes + 10; s++) {
format.createEntry(ConditionEntryType.CONDITION, s);
XConditionEntry entry = queryInterface(XConditionEntry.class, format.getByIndex(s));
XPropertySet entryProps = queryInterface(XPropertySet.class, entry);
entryProps.setPropertyValue("Operator", ConditionFormatOperator.EQUAL);
entryProps.setPropertyValue("Formula1", "\"cc\"");
//entryProps.setPropertyValue("Formula1", "'S" + Integer.toString(s + 1));
entryProps.setPropertyValue("StyleName", "StyleS" + (s + 1));
}
// XSheetCondition conditionS = ;
// XSheetConditionalEntries entries = ;
// entries.addNew(arg0);
// XSheetConditionalEntry entry = ;
// entry.setStyleName("StyleS");
PropertyValue vType = new PropertyValue("FilterName", -1, "", PropertyState.DEFAULT_VALUE);
PropertyValue vOw = new PropertyValue("Overwrite", -1, true, PropertyState.DEFAULT_VALUE);
XStorable store = UnoRuntime.queryInterface(XStorable.class, myDoc);
store.storeToURL(destination.toURI().toString(), new PropertyValue[] { vType, vOw });
} catch (Exception e) {
e.printStackTrace(System.err);
return false;
}
return true;
}
public static int realDayOfWeek(int day) {
if (day == Calendar.SUNDAY)
return 7;
return day - 1;
}
public static void colorCell(XPropertySet cell, Color backColor)
throws IllegalArgumentException, UnknownPropertyException, PropertyVetoException, WrappedTargetException {
cell.setPropertyValue("CellBackColor", Integer.valueOf(backColor.getRGB() & 0xFFFFFF));
cell.setPropertyValue("CharColor", Integer.valueOf(Util.complementaire(backColor).getRGB() & 0xFFFFFF));
cell.setPropertyValue("IsCellBackgroundTransparent", Boolean.FALSE);
}
public static void merge(XCellRange range) {
XMergeable merger = queryInterface(XMergeable.class, range);
merger.merge(true);
}
public static void mergeAndSet(XCellRange range, String formula, String style) throws IndexOutOfBoundsException,
IllegalArgumentException, UnknownPropertyException, PropertyVetoException, WrappedTargetException {
merge(range);
setValue(range.getCellByPosition(0, 0), formula, style);
}
public static void setValue(XCell cell, String formula, String style) throws IndexOutOfBoundsException,
IllegalArgumentException, UnknownPropertyException, PropertyVetoException, WrappedTargetException {
cell.setFormula(formula);
XPropertySet props = queryInterface(XPropertySet.class, cell);
props.setPropertyValue("CellStyle", style);
}
}

View File

@ -0,0 +1,211 @@
package com.bernard.kholloscopinator.controlleur;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.bernard.kholloscopinator.model.*;
import static java.lang.Math.*;
public class KholloscopeMaker {
public static int selectionSize = 10;
public static int maxSelectionTries = 100;
public static final Kholloscope genRandKholloscope(Random r,KConfig config, Set<Eleve> eleves, Set<Kholleur> kholleurs,Set<Groupe> preGroupes, List<Semaine> calendrier, Map<String,Map<String,Set<Horaire>>> disponibilites, Map<String,Map<Kholleur,Set<Horaire>>> disponibilitesKholleurs,Map<Semaine,Map<Groupe,List<String>>> khPrevues) {
khMake: while(true) {
if(config.isShouldGenGrps()) {
// Crée les groupes
preGroupes = new HashSet<>();
Queue<Integer> sizes = new LinkedBlockingQueue<>();
sizes.addAll(Collections.nCopies(eleves.size()/3-2, 3));
switch(eleves.size()%3) {
case 0:
sizes.add(3);
sizes.add(3);
break;
case 1:
sizes.add(2);
sizes.add(2);
break;
case 2:
sizes.add(3);
sizes.add(2);
break;
}
Queue<String> contraintes = eleves.stream().map(e->e.getContraintes()).flatMap(Set::stream).distinct().collect(Collectors.toCollection(LinkedBlockingQueue::new));
Map<Set<String>,List<Eleve>> tries = eleves.stream().collect(Collectors.groupingBy(Eleve::getContraintes));
while(sizes.isEmpty()) {
tries.values().stream().forEach(l->{
while(l.size()>=sizes.peek()) {
Set<Eleve> elevesDuGroupe = new HashSet<>();
for (int i = 0; i < sizes.peek(); i++) {
elevesDuGroupe.add(l.get(0));
l.remove(0);
}
sizes.poll();
}
});
String contrainte = contraintes.poll();
tries = tries.entrySet().stream()
.collect(Collectors.groupingBy(e->e.getKey()
.stream()
.filter(ct->!ct.equals(contrainte))
.collect(Collectors.toSet())))
.entrySet().stream()
.collect(Collectors.toMap(e->e.getKey(), e->e.getValue().stream()
.map(Entry::getValue)
.flatMap(List::stream)
.collect(Collectors.toList())));
}
}
Set<Groupe> groupes = preGroupes;
Map<Semaine,Set<Kholle>> kholles = new HashMap<>();
// Taggage
//Track
Map<Kholleur,Map<Groupe,Set<Integer>>> kiDejaEu = new HashMap<Kholleur, Map<Groupe,Set<Integer>>>();
for(Semaine semaine : calendrier) {
int semIndex = calendrier.indexOf(semaine);
Map<Kholleur,Set<Horaire>> disposKH = disponibilitesKholleurs.get(semaine.getType());
Map<String,Set<Horaire>> dispoEL = disponibilites.get(semaine.getType());
Map<Groupe,Map<Kholle,Double>> khollesPossibles = new HashMap<>();
for(Groupe gr : groupes) {
// Calcul du score
Function<Kholle, Double> getKScore = new Function<Kholle, Double>() {
@Override
public Double apply(Kholle kh) {
double score = 0;
score += exp(-0.0005*pow(kiDejaEu.get(kh.getKholleur())
.get(kh.getGroupe()).stream()
.mapToDouble(x-> exp(-0.0005*pow(semIndex-x,4)))
.sum(),4));
score *= ((double)kiDejaEu.get(kh.getKholleur())
.get(kh.getGroupe()).size())/(semIndex+1);
return score;
}
};
// Les kholles possibles et leur score
List<String> khAFaire = khPrevues.get(semaine).get(gr);
Set<Horaire> dispoGrp = gr.getContraintes().stream().map(dispoEL::get).map(HashSet::new).reduce(new HashSet<Horaire>(), (h1,h2)->{h1.retainAll(h2);return h1;});
Map<Kholle,Double> scores = dispoGrp.stream() // Pour chaque horaire du groupe
.map(h -> disposKH.keySet().stream() // Associer la liste des dispos du kholleur
.filter(kholleur -> disposKH.get(kholleur).contains(h)) // Inter celles du groupe
.filter(k -> khAFaire.contains(k.getMatière()))// Enlever les kholleurs de mauvaise matière
.map(k -> new Kholle(k, gr, h)) // Puis créer les objets kholles correspondant
.collect(Collectors.toSet()))
.reduce(new HashSet<Kholle>(), (h1,h2)->{h1.addAll(h2);return h1;}).stream()
.collect(Collectors.toMap(Function.identity(),getKScore));
khollesPossibles.put(gr, scores);
}
//Sélection des kholles
Map<Map<Groupe,List<Kholle>>,Double> selection = new HashMap<>();
dstr:for(int iter=0;selection.size()<selectionSize || iter<maxSelectionTries;iter++) {
List<Groupe> shuffledList = groupes.stream().collect(Collectors.toList());
Collections.shuffle(shuffledList, r);
Map<Groupe,List<Kholle>> distribution = new HashMap<>();
double score = 0;
for(Groupe gr : shuffledList) {
//Sélectionner la kholle
Map<Kholle,Double> kPossibles = khollesPossibles
.get(gr)
.entrySet()
.stream()
.filter(e->!distribution.values().stream().anyMatch(l->l.stream().anyMatch(k->k.getHoraire().equals(e.getKey().getHoraire()) && k.getKholleur().equals(e.getKey().getKholleur()))))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
List<Kholle> sel = new ArrayList<>();
for (String matiere : khPrevues.get(semaine).get(gr)) {
Kholle ptSel = weightedSelection(kPossibles.entrySet().stream().filter(e->e.getKey().getKholleur().getMatière().equals(matiere)).collect(Collectors.toMap(Entry::getKey, Entry::getValue)), r);
if(ptSel==null)continue dstr;
sel.add(ptSel);
kPossibles.remove(ptSel);
}
distribution.put(gr, sel);
score += sel.stream().map(kPossibles::get).mapToDouble(x->x).sum();
}
selection.put(distribution, score);
}
if(selection.size()==0) {
continue khMake; // Refaire un nouveau kholloscope
}
//Sélection de la meilleure distribution
double maxScore = selection.values().stream().mapToDouble(x->x).max().getAsDouble();
Map<Groupe,List<Kholle>> selectionne = selection.entrySet().stream().filter(e->e.getValue()==maxScore).map(Entry::getKey).findAny().get();
kholles.put(semaine,selectionne.values().stream().flatMap(List::stream).collect(Collectors.toSet()));
//update tracking maps
kholleurs.stream().forEach(k-> groupes.stream().filter(g->selectionne.get(g).stream().anyMatch(kh->kh.getKholleur().equals(k))).forEach(g->kiDejaEu.get(k).get(g).add(semIndex)) );
}
return new Kholloscope(groupes.stream().collect(Collectors.toList()), kholles);
}
}
public static <E> E weightedSelection(Map<E,Double> values,Random r){
double sum = values.values().stream().mapToDouble(x->x).sum();
double rand = r.nextDouble() * sum;
double temp = 0;
E selected = null;
for(E e : values.keySet()) {
if(temp > rand)break;
temp += values.get(e);
selected = e;
}
return selected;
}
public static long hashSetOfStrings(Set<String> toHash) {
return toHash.stream().sorted().collect(Collectors.joining(";")).hashCode();
}
public static final class KholleDisponible{
Kholleur kholleur;
Horaire horaire;
}
}

View File

@ -0,0 +1,147 @@
package com.bernard.kholloscopinator.controlleur;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Random;
import com.sun.star.bridge.UnoUrlResolver;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lib.util.NativeLibraryLoader;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
public class OfficeController {
public static Process soffice = null;
public static XComponentContext xContext;
static {
try {
bootstrap(Bootstrap.getDefaultOptions());
System.out.println("Connécté à office");
} catch (BootstrapException e) {
e.printStackTrace();
System.exit(42);
}
}
public static final void bootstrap( String[] argArray )
throws BootstrapException {
XComponentContext xContext = null;
try {
// create default local component context
XComponentContext xLocalContext =
Bootstrap.createInitialComponentContext( (Map<String, Object>) null );
if ( xLocalContext == null )
throw new BootstrapException( "no local component context!" );
// find office executable relative to this class's class loader
String sOffice =
System.getProperty( "os.name" ).startsWith( "Windows" ) ?
"soffice.exe" : "soffice";
File fOffice = NativeLibraryLoader.getResource(
Bootstrap.class.getClassLoader(), sOffice );
if ( fOffice == null )
throw new BootstrapException( "no office executable found!" );
// create random pipe name
String sPipeName = "uno" +
Long.toString(new Random().nextLong() & 0x7fffffffffffffffL);
// create call with arguments
String[] cmdArray = new String[ argArray.length + 2 ];
cmdArray[0] = fOffice.getPath();
cmdArray[1] = ( "--accept=pipe,name=" + sPipeName + ";urp;" );
System.arraycopy( argArray, 0, cmdArray, 2, argArray.length );
// start office process
Process p = Runtime.getRuntime().exec( cmdArray );
pipe( p.getInputStream(), System.out, "CO> " );
pipe( p.getErrorStream(), System.err, "CE> " );
// initial service manager
XMultiComponentFactory xLocalServiceManager =
xLocalContext.getServiceManager();
if ( xLocalServiceManager == null )
throw new BootstrapException( "no initial service manager!" );
// create a URL resolver
XUnoUrlResolver xUrlResolver =
UnoUrlResolver.create( xLocalContext );
// connection string
String sConnect = "uno:pipe,name=" + sPipeName +
";urp;StarOffice.ComponentContext";
// wait until office is started
for (int i = 0;; ++i) {
try {
// try to connect to office
Object context = xUrlResolver.resolve( sConnect );
xContext = UnoRuntime.queryInterface(
XComponentContext.class, context);
if ( xContext == null )
throw new BootstrapException( "no component context!" );
break;
} catch ( com.sun.star.connection.NoConnectException ex ) {
// Wait 500 ms, then try to connect again, but do not wait
// longer than 5 min (= 600 * 500 ms) total:
if (i == 600) {
throw new BootstrapException(ex);
}
Thread.sleep( 500 );
}
}
OfficeController.soffice=p;
OfficeController.xContext=xContext;
} catch ( BootstrapException e ) {
throw e;
} catch ( java.lang.RuntimeException e ) {
throw e;
} catch ( java.lang.Exception e ) {
throw new BootstrapException( e );
}
}
private static void pipe(
final InputStream in, final PrintStream out, final String prefix ) {
new Thread( "Pipe: " + prefix) {
@Override
public void run() {
try {
BufferedReader r = new BufferedReader(
new InputStreamReader(in, "UTF-8") );
for ( ; ; ) {
String s = r.readLine();
if ( s == null ) {
break;
}
out.println( prefix + s );
}
} catch ( UnsupportedEncodingException e ) {
e.printStackTrace( System.err );
} catch ( java.io.IOException e ) {
e.printStackTrace( System.err );
}
}
}.start();
}
public static void closeOffice() {
OfficeController.soffice.destroy();
}
}

View File

@ -0,0 +1,70 @@
package com.bernard.kholloscopinator.model;
import java.util.Set;
public class Eleve {
private String nom;
private String prenom;
private String regime;
private Set<String> contraintes;
public Eleve(String nom, String prenom, String regime, Set<String> contraintes) {
super();
this.nom = nom;
this.prenom = prenom;
this.regime = regime;
this.contraintes = contraintes;
}
public String getNom() {
return nom;
}
public String getPrenom() {
return prenom;
}
public String getRegime() {
return regime;
}
public Set<String> getContraintes() {
return contraintes;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((nom == null) ? 0 : nom.hashCode());
result = prime * result + ((prenom == null) ? 0 : prenom.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Eleve other = (Eleve) obj;
if (nom == null) {
if (other.nom != null)
return false;
} else if (!nom.equals(other.nom))
return false;
if (prenom == null) {
if (other.prenom != null)
return false;
} else if (!prenom.equals(other.prenom))
return false;
return true;
}
}

View File

@ -0,0 +1,64 @@
package com.bernard.kholloscopinator.model;
import java.util.HashSet;
import java.util.Set;
public class Groupe {
private Set<Eleve> eleves;
private volatile Set<String> contraintes;
public Groupe(Set<Eleve> eleves) {
this.eleves = eleves;
updateContraintes();
}
private void updateContraintes() {
Set<String> contraintes = new HashSet<String>();
for(Eleve e : eleves) {
contraintes.addAll(e.getContraintes());
}
}
public Set<Eleve> getEleves() {
return eleves;
}
public Set<String> getContraintes() {
return contraintes;
}
/**
* Ne tiens compte que des élèves du groupe, les contraintes n'étant pas supposées être discriminantes
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((eleves == null) ? 0 : eleves.hashCode());
return result;
}
/**
* Ne tiens compte que des élèves du groupe, les contraintes n'étant pas supposées être discriminantes
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Groupe other = (Groupe) obj;
if (eleves == null) {
if (other.eleves != null)
return false;
} else if (!eleves.equals(other.eleves))
return false;
return true;
}
}

View File

@ -0,0 +1,63 @@
package com.bernard.kholloscopinator.model;
import java.util.Set;
public class Horaire {
String jour; // Ex: "Mon"
String heure; // Ex: "9h" ou "12h30-14h45"
Set<String> tags; // Ex : {"S","M"}
public Horaire(String jour, String heure, Set<String> tags) {
super();
this.jour = jour;
this.heure = heure;
this.tags = tags;
}
public String getJour() {
return jour;
}
public String getHeure() {
return heure;
}
public Set<String> getTags() {
return tags;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((heure == null) ? 0 : heure.hashCode());
result = prime * result + ((jour == null) ? 0 : jour.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Horaire other = (Horaire) obj;
if (heure == null) {
if (other.heure != null)
return false;
} else if (!heure.equals(other.heure))
return false;
if (jour == null) {
if (other.jour != null)
return false;
} else if (!jour.equals(other.jour))
return false;
return true;
}
}

View File

@ -0,0 +1,299 @@
package com.bernard.kholloscopinator.model;
public class KConfig {
private boolean shouldGenGrps;
private char genMethod; // 'n' par nombre, 't' pour temps
private Long genTimeTime;
private Integer genNumberNumber;
private String outputFileName, inputFileName;
private boolean genKCondense,genKParEleve,genKParEleveFat,genKParGroupe,genKParGroupeFat,genKCondenseParProf,genKCondenseParProfFat,genKListeParProf,genKListeParProfFat,genKCalendrierParProf,genKCalendrierParProfFat,genKPourEleveCalendrier,genKPourEleveCalendrierFat,genKPourGroupeCalendrier,genKPourGroupeCalendrierFat,genListeGroupes;
/**
* @param shouldGenGrps
* @param genMethod
* @param genTimeTime
* @param genNumberNumber
* @param outputFileName
* @param inputFileName
* @param genKCondense
* @param genKParEleve
* @param genKParEleveFat
* @param genKParGroupe
* @param genKParGroupeFat
* @param genKCondenseParProf
* @param genKCondenseParProfFat
* @param genKListeParProf
* @param genKListeParProfFat
* @param genKCalendrierParProf
* @param genKCalendrierParProfFat
* @param genKPourEleveCalendrier
* @param genKPourEleveCalendrierFat
* @param genKPourGroupeCalendrier
* @param genKPourGroupeCalendrierFat
* @param genListeGroupes
*/
public KConfig(boolean shouldGenGrps, char genMethod, Long genTimeTime, Integer genNumberNumber,
String outputFileName, String inputFileName, boolean genKCondense, boolean genKParEleve,
boolean genKParEleveFat, boolean genKParGroupe, boolean genKParGroupeFat, boolean genKCondenseParProf,
boolean genKCondenseParProfFat, boolean genKListeParProf, boolean genKListeParProfFat,
boolean genKCalendrierParProf, boolean genKCalendrierParProfFat, boolean genKPourEleveCalendrier,
boolean genKPourEleveCalendrierFat, boolean genKPourGroupeCalendrier, boolean genKPourGroupeCalendrierFat,
boolean genListeGroupes) {
this.shouldGenGrps = shouldGenGrps;
this.genMethod = genMethod;
this.genTimeTime = genTimeTime;
this.genNumberNumber = genNumberNumber;
this.outputFileName = outputFileName;
this.inputFileName = inputFileName;
this.genKCondense = genKCondense;
this.genKParEleve = genKParEleve;
this.genKParEleveFat = genKParEleveFat;
this.genKParGroupe = genKParGroupe;
this.genKParGroupeFat = genKParGroupeFat;
this.genKCondenseParProf = genKCondenseParProf;
this.genKCondenseParProfFat = genKCondenseParProfFat;
this.genKListeParProf = genKListeParProf;
this.genKListeParProfFat = genKListeParProfFat;
this.genKCalendrierParProf = genKCalendrierParProf;
this.genKCalendrierParProfFat = genKCalendrierParProfFat;
this.genKPourEleveCalendrier = genKPourEleveCalendrier;
this.genKPourEleveCalendrierFat = genKPourEleveCalendrierFat;
this.genKPourGroupeCalendrier = genKPourGroupeCalendrier;
this.genKPourGroupeCalendrierFat = genKPourGroupeCalendrierFat;
this.genListeGroupes = genListeGroupes;
}
public static KConfig getDefaultConfig() {
return new KConfig(true, 't', 600L, 42, "/kholloscope.kou", "/kholloscope.kin", true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true);
}
public boolean isShouldGenGrps() {
return shouldGenGrps;
}
public char getGenMethod() {
return genMethod;
}
public Long getGenTimeTime() {
return genTimeTime;
}
public Integer getGenNumberNumber() {
return genNumberNumber;
}
public String getOutputFileName() {
return outputFileName;
}
public String getInputFileName() {
return inputFileName;
}
public boolean isGenKCondense() {
return genKCondense;
}
public boolean isGenKParEleve() {
return genKParEleve;
}
public boolean isGenKParEleveFat() {
return genKParEleveFat;
}
public boolean isGenKParGroupe() {
return genKParGroupe;
}
public boolean isGenKParGroupeFat() {
return genKParGroupeFat;
}
public boolean isGenKCondenseParProf() {
return genKCondenseParProf;
}
public boolean isGenKCondenseParProfFat() {
return genKCondenseParProfFat;
}
public boolean isGenKListeParProf() {
return genKListeParProf;
}
public boolean isGenKListeParProfFat() {
return genKListeParProfFat;
}
public boolean isGenKCalendrierParProf() {
return genKCalendrierParProf;
}
public boolean isGenKCalendrierParProfFat() {
return genKCalendrierParProfFat;
}
public boolean isGenKPourEleveCalendrier() {
return genKPourEleveCalendrier;
}
public boolean isGenKPourEleveCalendrierFat() {
return genKPourEleveCalendrierFat;
}
public boolean isGenKPourGroupeCalendrier() {
return genKPourGroupeCalendrier;
}
public boolean isGenKPourGroupeCalendrierFat() {
return genKPourGroupeCalendrierFat;
}
public boolean isGenListeGroupes() {
return genListeGroupes;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (genKCalendrierParProf ? 1231 : 1237);
result = prime * result + (genKCalendrierParProfFat ? 1231 : 1237);
result = prime * result + (genKCondense ? 1231 : 1237);
result = prime * result + (genKCondenseParProf ? 1231 : 1237);
result = prime * result + (genKCondenseParProfFat ? 1231 : 1237);
result = prime * result + (genKListeParProf ? 1231 : 1237);
result = prime * result + (genKListeParProfFat ? 1231 : 1237);
result = prime * result + (genKParEleve ? 1231 : 1237);
result = prime * result + (genKParEleveFat ? 1231 : 1237);
result = prime * result + (genKParGroupe ? 1231 : 1237);
result = prime * result + (genKParGroupeFat ? 1231 : 1237);
result = prime * result + (genKPourEleveCalendrier ? 1231 : 1237);
result = prime * result + (genKPourEleveCalendrierFat ? 1231 : 1237);
result = prime * result + (genKPourGroupeCalendrier ? 1231 : 1237);
result = prime * result + (genKPourGroupeCalendrierFat ? 1231 : 1237);
result = prime * result + (genListeGroupes ? 1231 : 1237);
result = prime * result + genMethod;
result = prime * result + ((genNumberNumber == null) ? 0 : genNumberNumber.hashCode());
result = prime * result + ((genTimeTime == null) ? 0 : genTimeTime.hashCode());
result = prime * result + ((inputFileName == null) ? 0 : inputFileName.hashCode());
result = prime * result + ((outputFileName == null) ? 0 : outputFileName.hashCode());
result = prime * result + (shouldGenGrps ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
KConfig other = (KConfig) obj;
if (genKCalendrierParProf != other.genKCalendrierParProf)
return false;
if (genKCalendrierParProfFat != other.genKCalendrierParProfFat)
return false;
if (genKCondense != other.genKCondense)
return false;
if (genKCondenseParProf != other.genKCondenseParProf)
return false;
if (genKCondenseParProfFat != other.genKCondenseParProfFat)
return false;
if (genKListeParProf != other.genKListeParProf)
return false;
if (genKListeParProfFat != other.genKListeParProfFat)
return false;
if (genKParEleve != other.genKParEleve)
return false;
if (genKParEleveFat != other.genKParEleveFat)
return false;
if (genKParGroupe != other.genKParGroupe)
return false;
if (genKParGroupeFat != other.genKParGroupeFat)
return false;
if (genKPourEleveCalendrier != other.genKPourEleveCalendrier)
return false;
if (genKPourEleveCalendrierFat != other.genKPourEleveCalendrierFat)
return false;
if (genKPourGroupeCalendrier != other.genKPourGroupeCalendrier)
return false;
if (genKPourGroupeCalendrierFat != other.genKPourGroupeCalendrierFat)
return false;
if (genListeGroupes != other.genListeGroupes)
return false;
if (genMethod != other.genMethod)
return false;
if (genNumberNumber == null) {
if (other.genNumberNumber != null)
return false;
} else if (!genNumberNumber.equals(other.genNumberNumber))
return false;
if (genTimeTime == null) {
if (other.genTimeTime != null)
return false;
} else if (!genTimeTime.equals(other.genTimeTime))
return false;
if (inputFileName == null) {
if (other.inputFileName != null)
return false;
} else if (!inputFileName.equals(other.inputFileName))
return false;
if (outputFileName == null) {
if (other.outputFileName != null)
return false;
} else if (!outputFileName.equals(other.outputFileName))
return false;
if (shouldGenGrps != other.shouldGenGrps)
return false;
return true;
}
@Override
public String toString() {
return "KConfig [shouldGenGrps=" + shouldGenGrps + ", genMethod=" + genMethod + ", genTimeTime=" + genTimeTime
+ ", genNumberNumber=" + genNumberNumber + ", outputFileName=" + outputFileName + ", inputFileName="
+ inputFileName + ", genKCondense=" + genKCondense + ", genKParEleve=" + genKParEleve
+ ", genKParEleveFat=" + genKParEleveFat + ", genKParGroupe=" + genKParGroupe + ", genKParGroupeFat="
+ genKParGroupeFat + ", genKCondenseParProf=" + genKCondenseParProf + ", genKCondenseParProfFat="
+ genKCondenseParProfFat + ", genKListeParProf=" + genKListeParProf + ", genKListeParProfFat="
+ genKListeParProfFat + ", genKCalendrierParProf=" + genKCalendrierParProf
+ ", genKCalendrierParProfFat=" + genKCalendrierParProfFat + ", genKPourEleveCalendrier="
+ genKPourEleveCalendrier + ", genKPourEleveCalendrierFat=" + genKPourEleveCalendrierFat
+ ", genKPourGroupeCalendrier=" + genKPourGroupeCalendrier + ", genKPourGroupeCalendrierFat="
+ genKPourGroupeCalendrierFat + ", genListeGroupes=" + genListeGroupes + "]";
}
}

View File

@ -0,0 +1,67 @@
package com.bernard.kholloscopinator.model;
public class Kholle {
Kholleur kholleur;
Groupe groupe;
Horaire horaire;
public Kholle(Kholleur kholleur, Groupe groupe, Horaire horaire) {
super();
this.kholleur = kholleur;
this.groupe = groupe;
this.horaire = horaire;
}
public Kholleur getKholleur() {
return kholleur;
}
public Groupe getGroupe() {
return groupe;
}
public Horaire getHoraire() {
return horaire;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((groupe == null) ? 0 : groupe.hashCode());
result = prime * result + ((horaire == null) ? 0 : horaire.hashCode());
result = prime * result + ((kholleur == null) ? 0 : kholleur.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Kholle other = (Kholle) obj;
if (groupe == null) {
if (other.groupe != null)
return false;
} else if (!groupe.equals(other.groupe))
return false;
if (horaire == null) {
if (other.horaire != null)
return false;
} else if (!horaire.equals(other.horaire))
return false;
if (kholleur == null) {
if (other.kholleur != null)
return false;
} else if (!kholleur.equals(other.kholleur))
return false;
return true;
}
}

View File

@ -0,0 +1,54 @@
package com.bernard.kholloscopinator.model;
public class Kholleur {
private String nom;
private String matière;
public Kholleur(String nom, String matière) {
this.nom = nom;
this.matière = matière;
}
public String getNom() {
return nom;
}
public String getMatière() {
return matière;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((matière == null) ? 0 : matière.hashCode());
result = prime * result + ((nom == null) ? 0 : nom.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Kholleur other = (Kholleur) obj;
if (matière == null) {
if (other.matière != null)
return false;
} else if (!matière.equals(other.matière))
return false;
if (nom == null) {
if (other.nom != null)
return false;
} else if (!nom.equals(other.nom))
return false;
return true;
}
}

View File

@ -0,0 +1,59 @@
package com.bernard.kholloscopinator.model;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Kholloscope {
List<Groupe> groupes;
Map<Semaine,Set<Kholle>> kholles;
public Kholloscope(List<Groupe> groupes, Map<Semaine, Set<Kholle>> kholles) {
super();
this.groupes = groupes;
this.kholles = kholles;
}
public List<Groupe> getGroupes() {
return groupes;
}
public Map<Semaine, Set<Kholle>> getKholles() {
return kholles;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((groupes == null) ? 0 : groupes.hashCode());
result = prime * result + ((kholles == null) ? 0 : kholles.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Kholloscope other = (Kholloscope) obj;
if (groupes == null) {
if (other.groupes != null)
return false;
} else if (!groupes.equals(other.groupes))
return false;
if (kholles == null) {
if (other.kholles != null)
return false;
} else if (!kholles.equals(other.kholles))
return false;
return true;
}
}

View File

@ -0,0 +1,64 @@
package com.bernard.kholloscopinator.model;
import java.util.List;
/**
* Definit une semaine du calendrier, indépendant du lycée, des élèves ou de quoi que ce soit, si c n'est la planète de l'utilisateur.
* @author mysaa
*
*/
public class Semaine {
int numero;
List<Horaire> contenu;
String type;
public Semaine(int numero, List<Horaire> contenu, String type) {
this.numero = numero;
this.contenu = contenu;
this.type = type;
}
public int getNumero() {
return numero;
}
public List<Horaire> getContenu() {
return contenu;
}
public String getType() {
return type;
}
/**
* Le seul discriminant de l'objet est le numéro de la semaine. les autres contenus ne sont en aucun cas testés
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + numero;
return result;
}
/**
* Le seul discriminant de l'objet est le numéro de la semaine. les autres contenus ne sont en aucun cas testés
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Semaine other = (Semaine) obj;
if (numero != other.numero)
return false;
return true;
}
}

View File

@ -0,0 +1,406 @@
package com.bernard.kholloscopinator.vue;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.io.File;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.RegEx;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import com.bernard.kholloscopinator.controlleur.FileWriter;
import com.bernard.kholloscopinator.controlleur.OfficeController;
import com.bernard.kholloscopinator.model.KConfig;
public class MainFrame extends JFrame {
private static final long serialVersionUID = -4586310718545109704L;
public MainFrame() {
this.setTitle("Kholloscopinator");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.initView();
this.addActionListeners();
this.ecrireConfig(KConfig.getDefaultConfig());
this.setSize(900, 600);
this.setLocationRelativeTo(null);//Centre
this.setVisible(true);
}
private JButton dFileShooser,templateLauncher,inputLauncher,go,outputLauncher,allInOneLauncher;
private JCheckBox shouldGenGrps;
private JRadioButton genTimeButton, genNumberButton;
private JTextField genTimeTime, genNumberNumber;
private JTextField outputFileName, inputFileName;
private JCheckBox genKCondense,genKParEleve,genKParEleveFat,genKParGroupe,genKParGroupeFat,genKCondenseParProf,genKCondenseParProfFat,genKListeParProf,genKListeParProfFat,genKCalendrierParProf,genKCalendrierParProfFat,genKPourEleveCalendrier,genKPourEleveCalendrierFat,genKPourGroupeCalendrier,genKPourGroupeCalendrierFat,genListeGroupes;
private JButton checkConfig;
private void initView() {
JPanel globalPan = new JPanel();
JPanel directoryPan = new JPanel();
directoryPan.setLayout(new BorderLayout());
JTextField directoryField = new JTextField(System.getProperty("user.home")+"/kholloscopinator/");
JLabel dLabel = new JLabel("Destination : ");
dFileShooser = new JButton("Parcourir");
directoryPan.add(dLabel,BorderLayout.WEST);
directoryPan.add(directoryField, BorderLayout.CENTER);
directoryPan.add(dFileShooser,BorderLayout.EAST);
JTabbedPane configPan = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
JPanel kPan = new JPanel();
JPanel shouldGenPan = new JPanel(new BorderLayout());
JLabel shouldGenLabel = new JLabel("Dois-je générer les groupes ?");
shouldGenGrps = new JCheckBox();
shouldGenPan.add(shouldGenGrps, BorderLayout.WEST);
shouldGenPan.add(shouldGenLabel,BorderLayout.CENTER);
kPan.setLayout(new FlowLayout());
kPan.add(shouldGenPan);
JScrollPane kPanPan = new JScrollPane(kPan);
JPanel genPan = new JPanel();
Set<TitledCheckableBorder> borders = new HashSet<>();
JPanel timePan = new JPanel(new BorderLayout());
TitledCheckableBorder timeBorder = new TitledCheckableBorder("Temps", true,borders,genPan);
timePan.setBorder(timeBorder);
genTimeButton = timeBorder.getCheckBox();
JLabel timeText = new JLabel("Temps de recherche :");
genTimeTime = new JTextField("10:00");
timePan.add(timeText, BorderLayout.WEST);
timePan.add(genTimeTime, BorderLayout.CENTER);
JPanel nombrePan = new JPanel(new BorderLayout());
TitledCheckableBorder nombreBorder = new TitledCheckableBorder("Nombre", false,borders,genPan);
nombrePan.setBorder(nombreBorder);
genNumberButton = nombreBorder.getCheckBox();
JLabel numberText1 = new JLabel("Génerer ");
JLabel numberText2 = new JLabel(" kholloscopes.");
genNumberNumber = new JTextField("42");
nombrePan.add(numberText1, BorderLayout.WEST);
nombrePan.add(genNumberNumber, BorderLayout.CENTER);
nombrePan.add(numberText2, BorderLayout.EAST);
ButtonGroup genButtonsGroup = new ButtonGroup();
genButtonsGroup.add(genTimeButton);
genButtonsGroup.add(genNumberButton);
genPan.setLayout(new BoxLayout(genPan, BoxLayout.Y_AXIS));
genPan.add(timePan);
genPan.add(nombrePan);
JPanel genPanPanPan = new JPanel(new BorderLayout());
genPanPanPan.add(genPan,BorderLayout.NORTH);
JScrollPane genPanPan = new JScrollPane(genPanPanPan);
JPanel filesPan = new JPanel();
filesPan.setLayout(new BoxLayout(filesPan, BoxLayout.Y_AXIS));
JPanel filesNamePan = new JPanel();
filesNamePan.setLayout(new GridBagLayout());
GridBagConstraints fGBC = new GridBagConstraints();
JLabel outputFileLabel = new JLabel("Nom de la sortie");
JLabel inputFileLabel = new JLabel("Nom de l'entrée");
outputFileName = new JTextField("/kholloscope.kou");
inputFileName = new JTextField("/kholloscope.kin");
checkConfig = new JButton("Tester la config");
fGBC.weightx = 0.2;
fGBC.gridx = 0;
fGBC.gridy = 0;
fGBC.fill = GridBagConstraints.HORIZONTAL;
filesNamePan.add(outputFileLabel, fGBC);
fGBC.weightx = 0.8;
fGBC.gridx = 1;
fGBC.gridy = 0;
fGBC.fill = GridBagConstraints.HORIZONTAL;
filesNamePan.add(outputFileName, fGBC);
fGBC.weightx = .2;
fGBC.gridx = 0;
fGBC.gridy = 1;
fGBC.fill = GridBagConstraints.HORIZONTAL;
filesNamePan.add(inputFileLabel, fGBC);
fGBC.weightx = .8;
fGBC.gridx = 1;
fGBC.gridy = 1;
fGBC.fill = GridBagConstraints.HORIZONTAL;
filesNamePan.add(inputFileName, fGBC);
fGBC.weightx = 1.0;
fGBC.gridx = 0;
fGBC.gridy = 2;
fGBC.gridwidth = 2;
fGBC.fill = GridBagConstraints.HORIZONTAL;
filesNamePan.add(checkConfig, fGBC);
JPanel whatFilesPan = new JPanel();
whatFilesPan.setLayout(new GridBagLayout());
whatFilesPan.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.lightGray, 1), "Que génerer"));
GridBagConstraints wGBC = new GridBagConstraints();
wGBC.fill = GridBagConstraints.HORIZONTAL;
genKCondense = new JCheckBox("Génerer le kholloscope condensé");
int theY = wGBC.gridx = wGBC.gridy = 0;
wGBC.weightx = 1.0;
whatFilesPan.add(genKCondense,wGBC);
genKParEleve = new JCheckBox("Génerer le kholloscope par élève");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKParEleve,wGBC);
genKParEleveFat = new JCheckBox("Génerer le kholloscope par élève (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKParEleveFat,wGBC);
genKParGroupe = new JCheckBox("Génerer le kholloscope par groupe");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKParGroupe,wGBC);
genKParGroupeFat = new JCheckBox("Génerer le kholloscope par groupe (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKParGroupeFat,wGBC);
genKCondenseParProf = new JCheckBox("Génerer le kholloscope condensé par professeur");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKCondenseParProf,wGBC);
genKCondenseParProfFat = new JCheckBox("Génerer le kholloscope condensé par professeur (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKCondenseParProfFat,wGBC);
genKListeParProf = new JCheckBox("Génerer le kholloscope en liste par professeur");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKListeParProf,wGBC);
genKListeParProfFat = new JCheckBox("Génerer le kholloscope en liste par professeur (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKListeParProfFat,wGBC);
genKCalendrierParProf = new JCheckBox("Génerer le kholloscope en calendrier par professeur");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKCalendrierParProf,wGBC);
genKCalendrierParProfFat = new JCheckBox("Génerer le kholloscope en calendrier par professeur (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKCalendrierParProfFat,wGBC);
genKPourEleveCalendrier = new JCheckBox("Génerer le kholloscope en calendrier par élève");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKPourEleveCalendrier,wGBC);
genKPourEleveCalendrierFat = new JCheckBox("Génerer le kholloscope en calendrier par élève (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKPourEleveCalendrierFat,wGBC);
genKPourGroupeCalendrier = new JCheckBox("Génerer le kholloscope en calendrier par groupe");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKPourGroupeCalendrier,wGBC);
genKPourGroupeCalendrierFat = new JCheckBox("Génerer le kholloscope en calendrier par groupe (fat)");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genKPourGroupeCalendrierFat,wGBC);
genListeGroupes = new JCheckBox("Génerer la liste des groupes");
wGBC.gridx = 0;
wGBC.gridy = theY++;
whatFilesPan.add(genListeGroupes,wGBC);
filesPan.add(filesNamePan);
filesPan.add(whatFilesPan);
JPanel filesPanPan = new JPanel(new BorderLayout());
filesPanPan.add(filesPan,BorderLayout.NORTH);
JScrollPane files = new JScrollPane(filesPanPan);
JPanel launcherPan = new JPanel();
GridBagLayout launcherGBL = new GridBagLayout();
launcherPan.setLayout(launcherGBL);
GridBagConstraints lGBC = new GridBagConstraints();
templateLauncher = new JButton("Template");
inputLauncher = new JButton("Lire");
go = new JButton("Génerer");
outputLauncher = new JButton("Écrire");
allInOneLauncher = new JButton("All in one");
lGBC.insets = new Insets(3, 3, 3, 3);
lGBC.weightx = 1.0;
lGBC.gridx = lGBC.gridy = 0;
lGBC.fill = GridBagConstraints.BOTH;
lGBC.gridheight = 2;
launcherPan.add(templateLauncher,lGBC);
lGBC.gridx=1;
lGBC.gridheight = 1;
launcherPan.add(inputLauncher,lGBC);
lGBC.gridx=2;
launcherPan.add(go,lGBC);
lGBC.gridx=3;
launcherPan.add(outputLauncher,lGBC);
lGBC.gridx=1;
lGBC.gridy=1;
lGBC.gridwidth=3;
launcherPan.add(allInOneLauncher,lGBC);
configPan.add(kPanPan, "Kholloscope");
configPan.add(genPanPan, "Géneraton");
configPan.add(files, "Fichiers");
// Lire les données d'un dossier et y compiler dans un fichier .khi (KHolloscope Input)
// Rechercher un kholloscope, l'algorithme !!!
// Transformer les fichiers .kho en plein de fichiers de toutes les couleurs (KHOlloscope)
globalPan.setLayout(new BorderLayout());
globalPan.add(directoryPan,BorderLayout.NORTH);
globalPan.add(configPan,BorderLayout.CENTER);
globalPan.add(launcherPan,BorderLayout.SOUTH);
this.setContentPane(globalPan);
}
public void addActionListeners() {
checkConfig.addActionListener(e -> {
try {
System.out.println(lireConfig());
JOptionPane.showMessageDialog(this, "La configuration que vous m'avez donnée me semble tout à fait corecte !", "Config : OK", JOptionPane.INFORMATION_MESSAGE);
} catch (ParseException e1) {
e1.printStackTrace();
}
});
}
public void ecrireConfig(KConfig c) {
switch (c.getGenMethod()) {
case 'n':
this.genNumberButton.setSelected(true);
this.genNumberNumber.setText(Integer.toString(c.getGenNumberNumber()));
break;
case 't':
this.genTimeButton.setSelected(true);
this.genTimeTime.setText(getFromLongTime(c.getGenTimeTime()));
break;
}
this.outputFileName.setText(c.getOutputFileName());
this.inputFileName.setText(c.getInputFileName());
this.shouldGenGrps.setSelected(true);
genKCondense.setSelected(c.isGenKCondense());
genKParEleve.setSelected(c.isGenKParEleve());
genKParEleveFat.setSelected(c.isGenKParEleveFat());
genKParGroupe.setSelected(c.isGenKParGroupe());
genKParGroupeFat.setSelected(c.isGenKParGroupeFat());
genKCondenseParProf.setSelected(c.isGenKCondenseParProf());
genKCondenseParProfFat.setSelected(c.isGenKCondenseParProfFat());
genKListeParProf.setSelected(c.isGenKListeParProf());
genKListeParProfFat.setSelected(c.isGenKListeParProfFat());
genKCalendrierParProf.setSelected(c.isGenKCalendrierParProf());
genKCalendrierParProfFat.setSelected(c.isGenKCalendrierParProfFat());
genKPourEleveCalendrier.setSelected(c.isGenKPourEleveCalendrier());
genKPourEleveCalendrierFat.setSelected(c.isGenKPourEleveCalendrierFat());
genKPourGroupeCalendrier.setSelected(c.isGenKPourGroupeCalendrier());
genKPourGroupeCalendrierFat.setSelected(c.isGenKPourGroupeCalendrierFat());
genListeGroupes.setSelected(c.isGenListeGroupes());
}
public static final String getFromLongTime(Long time) {
if(time < 60)
return Long.toString(time);
else if(time < 3600)
return String.format("%02d:%02d", time/60,time%60);
else
return String.format("%d:%02d:%02d", time/3600,(time%3600)/60,time%60);
}
public KConfig lireConfig() throws ParseException {
Long genTimeTime = null;
Character genMethod = null;
if(genTimeButton.isSelected()) {
genMethod = 't';
String genTimeT = this.genTimeTime.getText();
@RegEx
String timeRecognizer = "((([0-9]+)[huHU:])?([0-9]+)[mM:])?([0-9]+)[sS]?";
Matcher timeM = Pattern.compile(timeRecognizer).matcher(genTimeT);
if(!timeM.matches()) {
JOptionPane.showMessageDialog(this,"Le temps indiqué dans l'onglet 'Génération' n'est pas un temps valide","Erreur de lecture des données", JOptionPane.ERROR_MESSAGE);
throw new ParseException("Temps de generation",0);
}
System.out.println(IntStream.range(0, timeM.groupCount()+1).mapToObj(i->i+":"+timeM.group(i)+"\n").collect(Collectors.joining()));
genTimeTime = ((timeM.group(3)!=null)?Long.parseLong(timeM.group(3))*3600L:0L) + ((timeM.group(4)!=null)?Long.parseLong(timeM.group(4))*60L:0L) + Long.parseLong(timeM.group(5));
}
Integer genNumNum = null;;
if(genNumberButton.isSelected()) {
genMethod = 'n';
try {
genNumNum = Integer.parseInt(genNumberNumber.getText());
}catch(NumberFormatException e) {
JOptionPane.showMessageDialog(this,"Le nombre de kholloscopes indiqué dans l'onglet 'Génération' n'est pas un nombre valide","Erreur de lecture des données", JOptionPane.ERROR_MESSAGE);
throw new ParseException("Nombre de K de generation",0);
}
}
//TODO check inputfilename and outputfilename validity
return new KConfig(shouldGenGrps.isSelected(), genMethod, genTimeTime, genNumNum, outputFileName.getText(), inputFileName.getText(), genKCondense.isSelected(), genKParEleve.isSelected(), genKParEleveFat.isSelected(), genKParGroupe.isSelected(), genKParGroupeFat.isSelected(), genKCondenseParProf.isSelected(), genKCondenseParProfFat.isSelected(), genKListeParProf.isSelected(), genKListeParProfFat.isSelected(), genKCalendrierParProf.isSelected(), genKCalendrierParProfFat.isSelected(), genKPourEleveCalendrier.isSelected(), genKPourEleveCalendrierFat.isSelected(), genKPourGroupeCalendrier.isSelected(), genKPourGroupeCalendrierFat.isSelected(), genListeGroupes.isSelected());
}
public static MainFrame INSTANCE;
public static void main(String[] args) {
Locale.setDefault(new Locale("fr","FR"));
//MainFrame.INSTANCE = new MainFrame();
//System.out.println(Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
//System.out.println(Calendar.getInstance().get(Calendar.DAY_OF_WEEK_IN_MONTH));
FileWriter.genCalendar(new GregorianCalendar(2019, 9, 1).getTime(), new GregorianCalendar(2021, 6, 5).getTime(), 2, new File("./test.ods"));
//FileWriter.readCalendar(new File("./test.ods"));
System.out.println("Fermeture d'office");
OfficeController.closeOffice();
System.out.println("C'est fermé !");
}
}

View File

@ -0,0 +1,99 @@
package com.bernard.kholloscopinator.vue;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JRadioButton;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;
import javax.swing.border.TitledBorder;
public class TitledCheckableBorder extends AbstractBorder {
private static final long serialVersionUID = -510721123390206757L;
private final TitledBorder parent;
private final JRadioButton checkBox;
private final Set<TitledCheckableBorder> grp;
private final Container theParent;
public TitledCheckableBorder(String title, boolean selected,Set<TitledCheckableBorder> grp,Container theParent) {
parent = BorderFactory.createTitledBorder(title);
this.grp = grp;
grp.add(this);
checkBox = new JRadioButton(title, selected);
checkBox.setHorizontalTextPosition(SwingConstants.LEFT);
this.theParent = theParent;
}
public boolean isSelected() {
return checkBox.isSelected();
}
public void addActionListener(ActionListener listener) {
checkBox.addActionListener(listener);
}
@Override
public boolean isBorderOpaque() {
return true;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Insets borderInsets = parent.getBorderInsets(c);
Insets insets = getBorderInsets(c);
int temp = (insets.top - borderInsets.top) / 2;
parent.paintBorder(c, g, x, y + temp, width, height - temp);
Dimension size = checkBox.getPreferredSize();
final Rectangle rectangle = new Rectangle(5, 0, size.width, size.height);
final Container container = (Container) c;
container.addMouseListener(new MouseAdapter() {
private void dispatchEvent(MouseEvent me) {
if (rectangle.contains(me.getX(), me.getY())) {
Point pt = me.getPoint();
pt.translate(-5, 0);
checkBox.setBounds(rectangle);
checkBox.dispatchEvent(new MouseEvent(checkBox, me.getID(), me.getWhen(), me.getModifiersEx(), pt.x,
pt.y, me.getClickCount(), me.isPopupTrigger(), me.getButton()));
for(TitledCheckableBorder bm : grp)
if(!bm.getCheckBox().isValid()) {
theParent.repaint();
break;
}
}
}
public void mousePressed(MouseEvent me) {
dispatchEvent(me);
}
public void mouseReleased(MouseEvent me) {
dispatchEvent(me);
}
});
SwingUtilities.paintComponent(g, checkBox, container, rectangle);
}
@Override
public Insets getBorderInsets(Component c) {
Insets insets = parent.getBorderInsets(c);
insets.top = Math.max(insets.top, checkBox.getPreferredSize().height);
return insets;
}
public JRadioButton getCheckBox() {
return checkBox;
}
}