Compare commits
No commits in common. "5f817f3dfcdc877c2af956ceee7427803e344006" and "06183dd59c0a8a12f1922d13b8fcca753959f073" have entirely different histories.
5f817f3dfc
...
06183dd59c
4
pom.xml
4
pom.xml
@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -12,5 +12,30 @@ public class App {
|
|||||||
|
|
||||||
MainWindow window = new MainWindow();
|
MainWindow window = new MainWindow();
|
||||||
window.run();
|
window.run();
|
||||||
|
|
||||||
|
/*
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Document obedy = Jsoup.connect("https://objednavky.jidelnasokolska.cz/faces/secured/month.jsp?terminal=false&keyboard=&printer=")
|
||||||
|
.header("Connection", "keep-alive")
|
||||||
|
.cookie("XSRF-TOKEN", XSRF_TOKEN)
|
||||||
|
.cookie("JSESSIONID", jidelnaJSESSIONID)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
System.out.println(obedy.toString());
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TO DO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SecurityException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,8 @@ import com.googlecode.lanterna.gui2.dialogs.DialogWindow;
|
|||||||
import com.googlecode.lanterna.gui2.dialogs.MessageDialog;
|
import com.googlecode.lanterna.gui2.dialogs.MessageDialog;
|
||||||
import com.googlecode.lanterna.gui2.dialogs.MessageDialogButton;
|
import com.googlecode.lanterna.gui2.dialogs.MessageDialogButton;
|
||||||
|
|
||||||
import xyz.thastertyn.Types.InputtedCredentials;
|
import xyz.thastertyn.Tuples.Triplet;
|
||||||
|
|
||||||
/**
|
|
||||||
* A Dialog window for inputing username and password.
|
|
||||||
*/
|
|
||||||
public class CredentialsInput extends DialogWindow {
|
public class CredentialsInput extends DialogWindow {
|
||||||
|
|
||||||
private TextBox username;
|
private TextBox username;
|
||||||
@ -104,8 +101,6 @@ public class CredentialsInput extends DialogWindow {
|
|||||||
.addComponent(password)
|
.addComponent(password)
|
||||||
.addTo(mainPanel);
|
.addTo(mainPanel);
|
||||||
|
|
||||||
if(!LocalCredentials.getInstance().checkForExistingCredentials())
|
|
||||||
{
|
|
||||||
Panel rememberPanel = new Panel()
|
Panel rememberPanel = new Panel()
|
||||||
.setLayoutManager(new GridLayout(3))
|
.setLayoutManager(new GridLayout(3))
|
||||||
.setLayoutData(GridLayout.createLayoutData(
|
.setLayoutData(GridLayout.createLayoutData(
|
||||||
@ -117,7 +112,6 @@ public class CredentialsInput extends DialogWindow {
|
|||||||
rememberPanel.addComponent(new Label("Rembember?"))
|
rememberPanel.addComponent(new Label("Rembember?"))
|
||||||
.addComponent(remember)
|
.addComponent(remember)
|
||||||
.addTo(mainPanel);
|
.addTo(mainPanel);
|
||||||
}
|
|
||||||
|
|
||||||
mainPanel.addComponent(new EmptySpace(TerminalSize.ONE));
|
mainPanel.addComponent(new EmptySpace(TerminalSize.ONE));
|
||||||
|
|
||||||
@ -132,9 +126,6 @@ public class CredentialsInput extends DialogWindow {
|
|||||||
setComponent(mainPanel);
|
setComponent(mainPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* User pressed ok, check if anything is actually typed and if so, pack and return it
|
|
||||||
*/
|
|
||||||
public void onOK()
|
public void onOK()
|
||||||
{
|
{
|
||||||
this.user = username.getText();
|
this.user = username.getText();
|
||||||
@ -154,13 +145,9 @@ public class CredentialsInput extends DialogWindow {
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the inputted username, password and if user chose to keep credentials stored
|
|
||||||
* @return {@link InputtedCredentials} with username first, password second and whether to store the credentials third
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public InputtedCredentials showDialog(WindowBasedTextGUI textGUI) {
|
public Triplet<String, String, Boolean> showDialog(WindowBasedTextGUI textGUI) {
|
||||||
super.showDialog(textGUI);
|
super.showDialog(textGUI);
|
||||||
return new InputtedCredentials(user, pass, remember.isChecked());
|
return new Triplet<String,String,Boolean>(user, pass, remember.isChecked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
package xyz.thastertyn.Login;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Credentials;
|
|
||||||
|
|
||||||
public class LocalCredentials {
|
|
||||||
|
|
||||||
private static LocalCredentials localCredentials = new LocalCredentials();
|
|
||||||
|
|
||||||
private String path;
|
|
||||||
|
|
||||||
private File credentialsFile;
|
|
||||||
private File credentialsPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks for already saved credentials, at least if its file exists <br>
|
|
||||||
* for Windows it checks {@code AppData\Roaming\jecnak\credemtials.txt} <br>
|
|
||||||
* for Linux it checks {@code ~/.local/share/jecnak/credentials.txt} <br>
|
|
||||||
* @return
|
|
||||||
* <ul>
|
|
||||||
* <li> {@code true} a file exists </li>
|
|
||||||
* <li> {@code false} doesn't exist </li>
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
public boolean checkForExistingCredentials()
|
|
||||||
{
|
|
||||||
if(System.getProperty("os.name").equals("Linux"))
|
|
||||||
{
|
|
||||||
// /home/user/.local/share/jecnak/...
|
|
||||||
path = System.getProperty("user.home") + "/.local/share/jecnak/";
|
|
||||||
}else if(System.getProperty("os.name").contains("Windows"))
|
|
||||||
{
|
|
||||||
// C:\Users\\user\AppData\Roaming\...
|
|
||||||
path = System.getenv("APPDATA") + "\\jecnak\\";
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
credentialsPath = new File(path);
|
|
||||||
credentialsFile = new File(credentialsPath, "credentials.txt");
|
|
||||||
|
|
||||||
if(!credentialsFile.exists())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try reading the credentails from a local file
|
|
||||||
* @return String[] with username on index 0, and password on index 1, <br>
|
|
||||||
* can also return null if credentials are corrupted, inaccessible, etc.
|
|
||||||
*/
|
|
||||||
public Credentials getCredentialsFile()
|
|
||||||
{
|
|
||||||
// TODO Use hashmap instead of array
|
|
||||||
String user = null;
|
|
||||||
String pass = null;
|
|
||||||
|
|
||||||
if(credentialsFile == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(credentialsFile));
|
|
||||||
|
|
||||||
String line = "";
|
|
||||||
while((line = reader.readLine()) != null)
|
|
||||||
{
|
|
||||||
String[] currentValue = line.split("=");
|
|
||||||
|
|
||||||
if(currentValue[0].equals("user"))
|
|
||||||
{
|
|
||||||
user = currentValue[1];
|
|
||||||
}else if(currentValue[0].equals("pass"))
|
|
||||||
{
|
|
||||||
pass = currentValue[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(user == null || pass == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Credentials(user, pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* appends the current credentials to the file
|
|
||||||
* @param credentials the array containing username and password. Username is on index 0, password on index 1
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean saveCredentials(Credentials credentials)
|
|
||||||
{
|
|
||||||
if(credentialsFile == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!credentialsFile.exists())
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
credentialsPath.mkdirs();
|
|
||||||
credentialsFile.createNewFile();
|
|
||||||
}catch(IOException e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(credentialsFile));
|
|
||||||
writer.append(String.format(
|
|
||||||
"user=%s\npass=%s\n",
|
|
||||||
credentials.getUsername(),
|
|
||||||
credentials.getPassword()));
|
|
||||||
|
|
||||||
writer.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the credentials file
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean deleteCredentials()
|
|
||||||
{
|
|
||||||
credentialsFile.delete();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a single instance to prevent creating and loading the files all over again when not much has changed
|
|
||||||
* @return {@link LocalCredentials} instance
|
|
||||||
*/
|
|
||||||
public static LocalCredentials getInstance()
|
|
||||||
{
|
|
||||||
return localCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -12,21 +12,16 @@ import org.jsoup.Connection.Method;
|
|||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
|
|
||||||
import xyz.thastertyn.Scrape.Downloader;
|
import xyz.thastertyn.Scrape.Downloader;
|
||||||
import xyz.thastertyn.Types.Credentials;
|
|
||||||
|
|
||||||
public class Login {
|
public class Login {
|
||||||
|
|
||||||
private String Jsessionid = null;
|
private String Jsessionid = null;
|
||||||
|
|
||||||
/**
|
// Check for session expiration
|
||||||
* Tries logging into SPSE Jecna. If it succeeds it also saves the JSessionId into {@link Downloader} for ease of use. If it fails to login, the program is as good as not running at all
|
private long start;
|
||||||
* @param credentials {@link Credentials} for username anas password
|
private long lastCheck;
|
||||||
* @throws UnknownHostException Most likely no internet connection, spsejecna.cz could not be recognised as a host
|
|
||||||
* @throws IOException by Jsoup
|
public void loginJecna(String user, String pass) throws UnknownHostException, IOException, CredentialException, TimeoutException
|
||||||
* @throws CredentialException The username or password is incorrect
|
|
||||||
* @throws TimeoutException Connection timed out, most likely a very slow internet
|
|
||||||
*/
|
|
||||||
public void loginJecna(Credentials credentials) throws UnknownHostException, IOException, CredentialException, TimeoutException
|
|
||||||
{
|
{
|
||||||
//#region JSESSIONID
|
//#region JSESSIONID
|
||||||
Connection.Response response = Jsoup.connect("https://www.spsejecna.cz")
|
Connection.Response response = Jsoup.connect("https://www.spsejecna.cz")
|
||||||
@ -39,32 +34,35 @@ public class Login {
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Token3
|
//#region Token3
|
||||||
String token3 = Downloader.getConnection("https://www.spsejecna.cz/user/role?role=student")
|
String token3 = Downloader.download("https://www.spsejecna.cz/user/role?role=student")
|
||||||
.get()
|
.get()
|
||||||
.select("input[name=token3]")
|
.select("input[name=token3]")
|
||||||
.attr("value");
|
.attr("value");
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Login
|
//#region Login
|
||||||
Downloader.getConnection("https://www.spsejecna.cz/user/login")
|
Downloader.download("https://www.spsejecna.cz/user/login")
|
||||||
.method(Connection.Method.POST)
|
.method(Connection.Method.POST)
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
.header("Origin", "https://www.spsejecna.cz")
|
.header("Origin", "https://www.spsejecna.cz")
|
||||||
.data("token3", token3)
|
.data("token3", token3)
|
||||||
.data("user", credentials.getUsername())
|
.data("user", user)
|
||||||
.data("pass", credentials.getPassword())
|
.data("pass", pass)
|
||||||
.data("submit", "P%C5%99ihl%C3%A1sit+se")
|
.data("submit", "P%C5%99ihl%C3%A1sit+se")
|
||||||
.followRedirects(true)
|
.followRedirects(true)
|
||||||
.execute();
|
.execute();
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
Document test = Downloader.getConnection("https://www.spsejecna.cz/score/student")
|
Document test = Downloader.download("https://www.spsejecna.cz/score/student")
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
if(test.toString().contains("Pro pokračování se přihlaste do systému"))
|
if(test.toString().contains("Pro pokračování se přihlaste do systému"))
|
||||||
{
|
{
|
||||||
throw new CredentialException("Incorrect username or password");
|
throw new CredentialException("Incorrect username or password");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start = System.currentTimeMillis() / 1000L;
|
||||||
|
lastCheck = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loginJidelna(String user, String pass) throws UnknownHostException, IOException
|
public void loginJidelna(String user, String pass) throws UnknownHostException, IOException
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package xyz.thastertyn.Login;
|
package xyz.thastertyn.Login;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
@ -10,17 +15,12 @@ import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
|||||||
import com.googlecode.lanterna.gui2.dialogs.MessageDialog;
|
import com.googlecode.lanterna.gui2.dialogs.MessageDialog;
|
||||||
import com.googlecode.lanterna.gui2.dialogs.MessageDialogButton;
|
import com.googlecode.lanterna.gui2.dialogs.MessageDialogButton;
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Credentials;
|
import xyz.thastertyn.Tuples.Triplet;
|
||||||
import xyz.thastertyn.Types.InputtedCredentials;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merges the functionality of {@link LocalCredentials}, {@link CredentialsInput}, and {@link Login}
|
|
||||||
*/
|
|
||||||
public class LoginController {
|
public class LoginController {
|
||||||
|
|
||||||
private WindowBasedTextGUI textGUI;
|
private WindowBasedTextGUI textGUI;
|
||||||
private xyz.thastertyn.Login.CredentialsInput dialog;
|
private xyz.thastertyn.Login.CredentialsInput dialog;
|
||||||
private LocalCredentials localCredentials = LocalCredentials.getInstance();
|
|
||||||
private xyz.thastertyn.Login.Login login = new xyz.thastertyn.Login.Login();
|
private xyz.thastertyn.Login.Login login = new xyz.thastertyn.Login.Login();
|
||||||
|
|
||||||
public LoginController(WindowBasedTextGUI textGUI)
|
public LoginController(WindowBasedTextGUI textGUI)
|
||||||
@ -28,72 +28,165 @@ public class LoginController {
|
|||||||
this.textGUI = textGUI;
|
this.textGUI = textGUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void login()
|
||||||
* Picks appropriate method for logging in
|
|
||||||
* <ul>
|
|
||||||
* <li> Locally stored credentials exist, then try using them. If they arent in good shape, use GUI
|
|
||||||
* <li> Use GUI and ask the user for credentials
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
public void login(boolean forceGUI)
|
|
||||||
{
|
|
||||||
Credentials credentials;
|
|
||||||
|
|
||||||
if(!forceGUI && localCredentials.checkForExistingCredentials())
|
|
||||||
{
|
|
||||||
credentials = localCredentials.getCredentialsFile();
|
|
||||||
}else{
|
|
||||||
credentials = loginUsingGui();
|
|
||||||
}
|
|
||||||
|
|
||||||
useCredentials(credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Credentials loginUsingGui()
|
|
||||||
{
|
{
|
||||||
dialog = new CredentialsInput();
|
dialog = new CredentialsInput();
|
||||||
|
if(checkForCredentials()) // Credentials exist
|
||||||
InputtedCredentials credentials = dialog.showDialog(textGUI);
|
|
||||||
|
|
||||||
if(credentials.save())
|
|
||||||
{
|
{
|
||||||
localCredentials.saveCredentials(credentials.getCredentials());
|
if(loginUsingCredentials()) // They are accessible and can read them
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return credentials.getCredentials();
|
Triplet<String, String, Boolean> data = dialog.showDialog(textGUI); // Failed to get credentials to log in, get them from user
|
||||||
}
|
try
|
||||||
|
|
||||||
/**
|
|
||||||
* Credentials were successfully obtained and are used for logging in, although a lot can go wrong
|
|
||||||
* @param credentials
|
|
||||||
*/
|
|
||||||
private void useCredentials(Credentials credentials)
|
|
||||||
{
|
{
|
||||||
try {
|
login.loginJecna(data.getValue0(), data.getValue1());
|
||||||
login.loginJecna(credentials);
|
|
||||||
}catch (TimeoutException e)
|
}catch (TimeoutException e)
|
||||||
{
|
{
|
||||||
MessageDialog.showMessageDialog(textGUI, "Timeout", "The attempt to connect took too long. The app will quit", MessageDialogButton.OK);
|
MessageDialog.showMessageDialog(textGUI, "Timeout", "The attempt to connect took too long.", MessageDialogButton.Retry,
|
||||||
System.exit(0);
|
MessageDialogButton.Abort);
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
MessageDialog.showMessageDialog(textGUI, "No Internet connection. The app will quit",
|
MessageDialog.showMessageDialog(textGUI, "No Internet connection",
|
||||||
e.getMessage(),
|
"There seems to be no internet connection, reverting to cached data",
|
||||||
MessageDialogButton.OK);
|
MessageDialogButton.OK);
|
||||||
System.exit(0);
|
login();
|
||||||
} catch (CredentialException e)
|
} catch (CredentialException e)
|
||||||
{
|
{
|
||||||
MessageDialog.showMessageDialog(textGUI, "Incorrect username or password",
|
MessageDialog.showMessageDialog(textGUI, "Incorrect username or password",
|
||||||
e.getMessage(),
|
"The username or password you entered is incorrect",
|
||||||
MessageDialogButton.OK);
|
MessageDialogButton.OK);
|
||||||
// The credentials were most likely tampered with after save, just get rid of them and save them another time
|
login();
|
||||||
LocalCredentials.getInstance().deleteCredentials();
|
|
||||||
login(true);
|
|
||||||
} catch (IOException e)
|
} catch (IOException e)
|
||||||
{
|
{
|
||||||
MessageDialog.showMessageDialog(textGUI, "There was an error. The app will quit",
|
MessageDialog.showMessageDialog(textGUI, "There was an error",
|
||||||
e.getMessage(),
|
"Maybe try again and it will go away",
|
||||||
MessageDialogButton.Retry);
|
MessageDialogButton.Retry);
|
||||||
System.exit(0);
|
login();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zkontroluje zda jiz neexistuji ulozene udaje na systemu
|
||||||
|
* @return <ul>
|
||||||
|
* <li> {@code true} soubor existuje a neni prazdny </li>
|
||||||
|
* <li> {@code false} neexistuje, nebo je prazdny </li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
private boolean checkForCredentials()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
//File credentials = null;
|
||||||
|
|
||||||
|
//if(System.getProperty("os.name").equals("Linux"))
|
||||||
|
//{
|
||||||
|
// credentials = new File("~/.local/share/jecnak/credentials.json");
|
||||||
|
|
||||||
|
//}else if(System.getProperty("os.name").contains("Windows"))
|
||||||
|
//{
|
||||||
|
// credentials = new File(System.getenv("APPDATA\\jecnak\\"));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if(!credentials.exists() || credentials.length() == 0)
|
||||||
|
//{
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
//return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean saveCredentials(String user, String pass)
|
||||||
|
{
|
||||||
|
File credentials;
|
||||||
|
|
||||||
|
if(System.getProperty("os.name").equals("Linux"))
|
||||||
|
{
|
||||||
|
credentials = new File("~/.local/share/jecnak/credentials.json");
|
||||||
|
|
||||||
|
}else if(System.getProperty("os.name").contains("Windows"))
|
||||||
|
{
|
||||||
|
credentials = new File(System.getenv("APPDATA\\jecnak\\"));
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(credentials));
|
||||||
|
writer.append("username=" + user);
|
||||||
|
writer.append("password=" + pass);
|
||||||
|
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean loginUsingCredentials()
|
||||||
|
{
|
||||||
|
File credentials;
|
||||||
|
|
||||||
|
if(System.getProperty("os.name").equals("Linux"))
|
||||||
|
{
|
||||||
|
credentials = new File("~/.local/share/jecnak/credentials.json");
|
||||||
|
|
||||||
|
}else if(System.getProperty("os.name").contains("Windows"))
|
||||||
|
{
|
||||||
|
credentials = new File(System.getenv("APPDATA\\jecnak\\"));
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!credentials.exists() || credentials.length() == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String user = "";
|
||||||
|
String pass = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedReader reader = new BufferedReader(new FileReader(credentials));
|
||||||
|
|
||||||
|
String line = "";
|
||||||
|
while((line = reader.readLine()) != null)
|
||||||
|
{
|
||||||
|
if(line.matches("^[a-z]\\=.*$"))
|
||||||
|
{
|
||||||
|
String key = line.split("=")[0];
|
||||||
|
String value = line.split("=")[1];
|
||||||
|
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case "username":
|
||||||
|
user = value;
|
||||||
|
break;
|
||||||
|
case "password":
|
||||||
|
pass = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
login.loginJecna(user, pass);
|
||||||
|
} catch (CredentialException | IOException | TimeoutException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.Month;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
|
||||||
import xyz.thastertyn.Types.Option;
|
|
||||||
import xyz.thastertyn.Types.Options;
|
|
||||||
|
|
||||||
public class AbsenceList extends JecnaScrape {
|
|
||||||
|
|
||||||
private ArrayList<xyz.thastertyn.Types.AbsenceList> data;
|
|
||||||
private Choice currentChoice;
|
|
||||||
|
|
||||||
private Options schoolYearOptions;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download() throws IOException
|
|
||||||
{
|
|
||||||
parse("https://www.spsejecna.cz/absence/student");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download(Choice choice) throws IOException {
|
|
||||||
|
|
||||||
currentChoice = choice;
|
|
||||||
|
|
||||||
parse(String.format(
|
|
||||||
"https://www.spsejecna.cz/absence/student?schoolYearId=%s",
|
|
||||||
choice.getChoices().get(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parse(String url) throws IOException
|
|
||||||
{
|
|
||||||
data = new ArrayList<>();
|
|
||||||
schoolYearOptions = new Options("Skolni R.");
|
|
||||||
Document absenceListHTMLDocument = Downloader.download(url);
|
|
||||||
|
|
||||||
Elements absenceLists = absenceListHTMLDocument.select("table.absence-list").select("tbody").select("tr");
|
|
||||||
|
|
||||||
for(Element e : absenceLists)
|
|
||||||
{
|
|
||||||
String date = e.child(0).text();
|
|
||||||
|
|
||||||
|
|
||||||
String text = e.child(1).text();
|
|
||||||
|
|
||||||
data.add(
|
|
||||||
new xyz.thastertyn.Types.AbsenceList(
|
|
||||||
date, text));
|
|
||||||
}
|
|
||||||
|
|
||||||
Elements options = absenceListHTMLDocument.select("form.listConfigure").select("select[id=schoolYearId]").select("option");
|
|
||||||
|
|
||||||
for(Element e : options)
|
|
||||||
{
|
|
||||||
boolean isDefault = e.hasAttr("selected");
|
|
||||||
schoolYearOptions.addOption(new Option(e.text(), e.attr("value"), isDefault));
|
|
||||||
}
|
|
||||||
|
|
||||||
currentChoice = new Choice(Arrays.asList(schoolYearOptions.getOptions().get(0).getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert text to a {@link LocalDate} and try to guess the year
|
|
||||||
* @param text to be parsed
|
|
||||||
* @return {@link LocalDate} parsed
|
|
||||||
*/
|
|
||||||
// private LocalDate parseDate(String text)
|
|
||||||
// {
|
|
||||||
// int year = 0, month = 0, day = 0;
|
|
||||||
// String[] split = text.split("\\.");
|
|
||||||
|
|
||||||
// day = Integer.parseInt(split[0]);
|
|
||||||
// month = Integer.parseInt(split[1]);
|
|
||||||
|
|
||||||
// if(currentChoice == null)
|
|
||||||
// {
|
|
||||||
// // Pick the current year
|
|
||||||
// int currYear = LocalDate.now().getYear();
|
|
||||||
// int currMonth = LocalDate.now().getMonthValue();
|
|
||||||
|
|
||||||
// if(month > currMonth && currMonth < 8)
|
|
||||||
// {
|
|
||||||
// year = currYear;
|
|
||||||
// }else if(month < currMonth && currMonth > 8)
|
|
||||||
// {
|
|
||||||
// year = currYear + 1;
|
|
||||||
// }else if(month < currMonth && currMonth < 8)
|
|
||||||
// {
|
|
||||||
// year = currYear;
|
|
||||||
// }
|
|
||||||
// }else{
|
|
||||||
// year = Integer.parseInt(currentChoice.getChoices().get(0));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return LocalDate.of(year, Month.of(month), day);
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Options[] getOptions() {
|
|
||||||
return new Options[] {schoolYearOptions};
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<xyz.thastertyn.Types.AbsenceList> getData()
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return (!data.isEmpty()) ? data.toString() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
|
||||||
import xyz.thastertyn.Types.Options;
|
|
||||||
|
|
||||||
public class Canteen extends JecnaScrape {
|
|
||||||
|
|
||||||
//public void foo()
|
|
||||||
//{
|
|
||||||
// try {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Document obedy = Jsoup.connect("https://objednavky.jidelnasokolska.cz/faces/secured/month.jsp?terminal=false&keyboard=&printer=")
|
|
||||||
// .header("Connection", "keep-alive")
|
|
||||||
// .cookie("XSRF-TOKEN", XSRF_TOKEN)
|
|
||||||
// .cookie("JSESSIONID", jidelnaJSESSIONID)
|
|
||||||
// .get();
|
|
||||||
|
|
||||||
// System.out.println(obedy.toString());
|
|
||||||
|
|
||||||
// //#endregion
|
|
||||||
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// // TO DO Auto-generated catch block
|
|
||||||
// e.printStackTrace();
|
|
||||||
// } catch (SecurityException e)
|
|
||||||
// {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Options[] getOptions() {
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'getOptions'");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download(Choice choice) throws IOException {
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'download'");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download() throws IOException {
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'download'");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +1,24 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
package xyz.thastertyn.Scrape;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.jsoup.Connection;
|
import org.jsoup.Connection;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
|
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
|
|
||||||
private static String JsessionId;
|
private static String JsessionId;
|
||||||
|
|
||||||
/**
|
public static Connection download(String url)
|
||||||
* Provide a general Jsoup Connection for simplicity with some predefined values and JSessionId already set
|
|
||||||
* @param url
|
|
||||||
* @return HTML Document downloaded. If it fails, null
|
|
||||||
*/
|
|
||||||
public static Document download(String url) throws IOException
|
|
||||||
{
|
{
|
||||||
return Jsoup.connect(url)
|
Connection c = Jsoup.connect(url)
|
||||||
.header("Connection", "keep-alive")
|
|
||||||
.cookie("role", "student")
|
|
||||||
.cookie("JSESSIONID", JsessionId)
|
|
||||||
.timeout(10000)
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a basic {@link Connection} with some predefined headers
|
|
||||||
* @param url
|
|
||||||
* @return {@link Connection} with timeout for 10s, and headers needed for downloading from spsejecna.cz
|
|
||||||
*/
|
|
||||||
public static Connection getConnection(String url)
|
|
||||||
{
|
|
||||||
return Jsoup.connect(url)
|
|
||||||
.header("Connection", "keep-alive")
|
.header("Connection", "keep-alive")
|
||||||
.cookie("role", "student")
|
.cookie("role", "student")
|
||||||
.cookie("JSESSIONID", JsessionId)
|
.cookie("JSESSIONID", JsessionId)
|
||||||
.timeout(10000);
|
.timeout(10000);
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static void setJSessionId(String JsId)
|
||||||
* Sets JsessionId
|
|
||||||
* @param newJsessionId JsessionId
|
|
||||||
*/
|
|
||||||
public static void setJSessionId(String newJsessionId)
|
|
||||||
{
|
{
|
||||||
JsessionId = newJsessionId;
|
JsessionId = JsId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
|
||||||
import xyz.thastertyn.Types.Options;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract class to wrap around everything that scrapes some data. Most of them also have getData or something similiar,
|
|
||||||
* but the data types are just so vastly different, they couldnt be wrapped as abstract method and abstract class
|
|
||||||
*/
|
|
||||||
public abstract class JecnaScrape {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns possible options, like school year or half year
|
|
||||||
* @return {@link Options} array, for when there are more options available
|
|
||||||
*/
|
|
||||||
public abstract Options[] getOptions();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downloads the chosen url, given the {@link Choice} which includes all the needed data
|
|
||||||
* @param choice of any possible data like school year or half year
|
|
||||||
* @throws IOException like any other download method, in case no internet, timeout, etc.
|
|
||||||
*/
|
|
||||||
public abstract void download(Choice choice) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downloads the default url, without any parameters
|
|
||||||
* @throws IOException in case of timeout, no internet, etc.
|
|
||||||
*/
|
|
||||||
public abstract void download() throws IOException;
|
|
||||||
}
|
|
5
src/main/java/xyz/thastertyn/Scrape/Jidelna.java
Normal file
5
src/main/java/xyz/thastertyn/Scrape/Jidelna.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package xyz.thastertyn.Scrape;
|
||||||
|
|
||||||
|
public class Jidelna {
|
||||||
|
|
||||||
|
}
|
@ -1,129 +0,0 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
|
||||||
import xyz.thastertyn.Types.FinalMark;
|
|
||||||
import xyz.thastertyn.Types.Option;
|
|
||||||
import xyz.thastertyn.Types.Options;
|
|
||||||
import xyz.thastertyn.Types.Subject;
|
|
||||||
import xyz.thastertyn.Types.Mark;
|
|
||||||
|
|
||||||
public class Marks extends JecnaScrape {
|
|
||||||
|
|
||||||
// schoolYear, schoolYearId
|
|
||||||
private ArrayList<Subject> subjects;
|
|
||||||
|
|
||||||
// int znaci id roku, boolean jestli je jen prvni nebo i druhe pololeti
|
|
||||||
private Options schoolYearOptions;
|
|
||||||
private Options schoolHalfYearOptions;
|
|
||||||
|
|
||||||
public void download() throws IOException
|
|
||||||
{
|
|
||||||
download("https://www.spsejecna.cz/score/student");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download(Choice choice) throws IOException
|
|
||||||
{
|
|
||||||
download(String.format(
|
|
||||||
"https://www.spsejecna.cz/score/student?schoolYearId=%s&schoolYearHalfId=%s",
|
|
||||||
choice.getChoices().get(0),
|
|
||||||
choice.getChoices().get(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void download(String url) throws IOException
|
|
||||||
{
|
|
||||||
schoolHalfYearOptions = new Options("Pololeti");
|
|
||||||
schoolYearOptions = new Options("Skolni R.");
|
|
||||||
|
|
||||||
subjects = new ArrayList<>();
|
|
||||||
Document marksHTMLDocument = Downloader.download(url);
|
|
||||||
|
|
||||||
// Subjects stored as <tr>
|
|
||||||
Elements[] subjectRowsHTML = marksHTMLDocument
|
|
||||||
.select("table.score")
|
|
||||||
.select("tr")
|
|
||||||
.stream()
|
|
||||||
.map(Element::children)
|
|
||||||
.toArray(Elements[]::new);
|
|
||||||
|
|
||||||
int subjectIndex = 0;
|
|
||||||
|
|
||||||
for(int i = 1; i < subjectRowsHTML.length; i++)
|
|
||||||
{
|
|
||||||
String fullSubjectName = subjectRowsHTML[i].get(0).text();
|
|
||||||
|
|
||||||
// Attempt to shorten the subject name to the string in brackets
|
|
||||||
String shortSubjectName = Pattern
|
|
||||||
.compile("\\((.*?)\\)")
|
|
||||||
.matcher(fullSubjectName)
|
|
||||||
.results()
|
|
||||||
.findFirst()
|
|
||||||
.map(m -> m.group(1))
|
|
||||||
.orElse(fullSubjectName);
|
|
||||||
|
|
||||||
if(subjectRowsHTML[i].get(2).childrenSize() == 0) // Subject doesn't have final mark yet
|
|
||||||
{
|
|
||||||
subjects.add(new Subject(shortSubjectName));
|
|
||||||
}else{
|
|
||||||
String finalMark = subjectRowsHTML[i].get(2).select("a.scoreFinal").text();
|
|
||||||
subjects.add(new Subject(shortSubjectName, FinalMark.fromValue(finalMark)));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Element znamkaElement : subjectRowsHTML[i].get(1).select("a.score"))
|
|
||||||
{
|
|
||||||
int mark;
|
|
||||||
boolean isSmall = false;
|
|
||||||
|
|
||||||
String markText = znamkaElement.select("span.value").text();
|
|
||||||
|
|
||||||
mark = markText.matches("\\d") ?
|
|
||||||
Integer.parseInt(markText)
|
|
||||||
:
|
|
||||||
-1; // Most likely N (Nehodnocen)
|
|
||||||
|
|
||||||
// Small mark will be counted with smaller weight, compared to normal one
|
|
||||||
isSmall = znamkaElement.hasClass("scoreSmall");
|
|
||||||
|
|
||||||
subjects.get(subjectIndex).addMark(new Mark(mark, isSmall, markText));
|
|
||||||
}
|
|
||||||
|
|
||||||
subjectIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Element optionsPanel = marksHTMLDocument.selectFirst("form.listConfigure");
|
|
||||||
|
|
||||||
Elements schoolYears = optionsPanel.select("select[id=schoolYearId]").select("option");
|
|
||||||
Elements halfYears = optionsPanel.select("select[id=schoolYearHalfId]").select("option");
|
|
||||||
|
|
||||||
|
|
||||||
for(Element e : schoolYears)
|
|
||||||
{
|
|
||||||
boolean isDefault = e.hasAttr("selected");
|
|
||||||
schoolYearOptions.addOption(new Option(e.text(), e.attr("value"), isDefault));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Element e : halfYears)
|
|
||||||
{
|
|
||||||
boolean isDefault = e.hasAttr("selected");
|
|
||||||
schoolHalfYearOptions.addOption(new Option(e.text(), e.attr("value"), isDefault));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<Subject> getSubjects()
|
|
||||||
{
|
|
||||||
return subjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Options[] getOptions()
|
|
||||||
{
|
|
||||||
return new Options[] {schoolYearOptions, schoolHalfYearOptions};
|
|
||||||
}
|
|
||||||
}
|
|
42
src/main/java/xyz/thastertyn/Scrape/OmluvnyList.java
Normal file
42
src/main/java/xyz/thastertyn/Scrape/OmluvnyList.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package xyz.thastertyn.Scrape;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
import xyz.thastertyn.Tuples.Pair;
|
||||||
|
|
||||||
|
public class OmluvnyList {
|
||||||
|
|
||||||
|
private ArrayList<Pair<String, String>> data = new ArrayList<>();
|
||||||
|
|
||||||
|
public void downloadOmluvnyList() throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
Document omluvnyListDokumentHTML = Downloader.download("https://www.spsejecna.cz/absence/student").get();
|
||||||
|
|
||||||
|
Elements omluvneListy = omluvnyListDokumentHTML.select("table.absence-list").select("tr");
|
||||||
|
|
||||||
|
for(Element e : omluvneListy)
|
||||||
|
{
|
||||||
|
String date = e.child(0).text();
|
||||||
|
String text = e.child(1).text();
|
||||||
|
|
||||||
|
data.add(new Pair<String, String>(date, text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Pair<String, String>> getData()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return (!data.isEmpty()) ? data.toString() : null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,50 +0,0 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
|
||||||
import xyz.thastertyn.Types.Options;
|
|
||||||
|
|
||||||
public class Reports extends JecnaScrape {
|
|
||||||
|
|
||||||
ArrayList<xyz.thastertyn.Types.Reports> reportList = new ArrayList<>();
|
|
||||||
|
|
||||||
public void download() throws UnknownHostException, IOException
|
|
||||||
{
|
|
||||||
Document reportDoc = Downloader.download("https://www.spsejecna.cz/user-student/record-list");
|
|
||||||
|
|
||||||
Elements report = reportDoc.select("ul.list li");
|
|
||||||
|
|
||||||
for(Element e : report)
|
|
||||||
{
|
|
||||||
boolean isPositive = false;
|
|
||||||
String label = "";
|
|
||||||
|
|
||||||
Elements spans = e.select("li").select("a.item").select("span");
|
|
||||||
|
|
||||||
isPositive = spans.get(0).hasClass("sprite-icon-tick-16");
|
|
||||||
label = spans.get(1).select("span.label").text();
|
|
||||||
|
|
||||||
reportList.add(new xyz.thastertyn.Types.Reports(label, isPositive));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<xyz.thastertyn.Types.Reports> getSdeleni()
|
|
||||||
{
|
|
||||||
return reportList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Options[] getOptions() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download(Choice choice) throws IOException {}
|
|
||||||
}
|
|
79
src/main/java/xyz/thastertyn/Scrape/Rozvrh.java
Normal file
79
src/main/java/xyz/thastertyn/Scrape/Rozvrh.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package xyz.thastertyn.Scrape;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jeden radek v rozvrhu
|
||||||
|
*/
|
||||||
|
public class Rozvrh {
|
||||||
|
|
||||||
|
private String[][] rozvrh = new String[5][10];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stahne rozvrh z www.spsejecna.cz a dale ho zpracuje do formy
|
||||||
|
* se kterou da pracovat
|
||||||
|
* @param Jsessionid ze stranek
|
||||||
|
* @throws UnknownHostException kdyz neni pripojeni k internetu
|
||||||
|
* @throws IOException ostatni exceptiony nejsou dulezite, tak jsou zahrnuty v jednom
|
||||||
|
*/
|
||||||
|
public void downloadRozvrh() throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
Document rozvrhDokumentHTML = Downloader.download("https://www.spsejecna.cz/timetable/class").get();
|
||||||
|
|
||||||
|
Elements[] radkyRozvrhuHTML = rozvrhDokumentHTML
|
||||||
|
.select("table.timetable")
|
||||||
|
.select("tr")
|
||||||
|
.stream()
|
||||||
|
.map(Element::children)
|
||||||
|
.toArray(Elements[]::new);
|
||||||
|
|
||||||
|
for(int i = 1; i < 6; i++)
|
||||||
|
{
|
||||||
|
for(int j = 1; j < 11; j++)
|
||||||
|
{
|
||||||
|
String predmet = radkyRozvrhuHTML[i].get(j).select("span.subject").text();
|
||||||
|
|
||||||
|
// Predmety jako CEL jsou trikrat, staci ale jen jednou
|
||||||
|
String[] split = predmet.split(" ");
|
||||||
|
HashSet<String> set = new HashSet<>(Arrays.asList(split));
|
||||||
|
String pr = String.join("/", set);
|
||||||
|
|
||||||
|
rozvrh[i-1][j-1] = pr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPredmet(String pr, int d, int i)
|
||||||
|
{
|
||||||
|
rozvrh[d][i] = pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] getRozvrh()
|
||||||
|
{
|
||||||
|
return rozvrh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String s = "";
|
||||||
|
for(String[] st : rozvrh)
|
||||||
|
{
|
||||||
|
s += ("| ");
|
||||||
|
for(String str : st)
|
||||||
|
{
|
||||||
|
s += String.format("%-5s", str) + " | ";
|
||||||
|
}
|
||||||
|
s += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
46
src/main/java/xyz/thastertyn/Scrape/Sdeleni.java
Normal file
46
src/main/java/xyz/thastertyn/Scrape/Sdeleni.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package xyz.thastertyn.Scrape;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
public class Sdeleni {
|
||||||
|
|
||||||
|
ArrayList<String> sdeleniList = new ArrayList<>();
|
||||||
|
|
||||||
|
public void downloadSdeleni() throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
Document sdeleniDoc = Downloader.download("https://www.spsejecna.cz/user-student/record-list").get();
|
||||||
|
|
||||||
|
Elements sdeleni = sdeleniDoc.select("ul.list li");
|
||||||
|
|
||||||
|
for(Element e : sdeleni)
|
||||||
|
{
|
||||||
|
boolean isPositive = false;
|
||||||
|
String label = "";
|
||||||
|
|
||||||
|
Elements spans = e.select("li").select("a.item").select("span");
|
||||||
|
|
||||||
|
isPositive = spans.get(0).hasClass("sprite-icon-tick-16");
|
||||||
|
label = spans.get(1).text();
|
||||||
|
|
||||||
|
if(isPositive)
|
||||||
|
{
|
||||||
|
label = "✅" + " " + label;
|
||||||
|
}else{
|
||||||
|
label = "❌" + " " + label;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdeleniList.add(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getSdeleni()
|
||||||
|
{
|
||||||
|
return sdeleniList;
|
||||||
|
}
|
||||||
|
}
|
@ -1,112 +0,0 @@
|
|||||||
package xyz.thastertyn.Scrape;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.jsoup.nodes.Document;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
|
||||||
import xyz.thastertyn.Types.Option;
|
|
||||||
import xyz.thastertyn.Types.Options;
|
|
||||||
|
|
||||||
public class Timetable extends JecnaScrape {
|
|
||||||
|
|
||||||
private xyz.thastertyn.Types.Timetable timetable;
|
|
||||||
|
|
||||||
private Options schoolYearOptions;
|
|
||||||
private Options timetableOptions;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download() throws IOException
|
|
||||||
{
|
|
||||||
download("https://www.spsejecna.cz/timetable/class");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void download(Choice choice) throws IOException {
|
|
||||||
download(String
|
|
||||||
.format("https://www.spsejecna.cz/timetable/class?schoolYearId=%s&timetableId=%s",
|
|
||||||
choice.getChoices().get(0),
|
|
||||||
choice.getChoices().get(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void download(String url) throws IOException
|
|
||||||
{
|
|
||||||
schoolYearOptions = new Options("Skolni R.");
|
|
||||||
timetableOptions = new Options("Obdobi");
|
|
||||||
|
|
||||||
timetable = new xyz.thastertyn.Types.Timetable();
|
|
||||||
Document timetableHTMLDocument = Downloader.download(url);
|
|
||||||
|
|
||||||
Elements[] timetableHTMLRow = timetableHTMLDocument
|
|
||||||
.select("table.timetable")
|
|
||||||
.select("tr")
|
|
||||||
.stream()
|
|
||||||
.map(Element::children)
|
|
||||||
.toArray(Elements[]::new);
|
|
||||||
|
|
||||||
for(int i = 0; i < 5; i++) // Days
|
|
||||||
{
|
|
||||||
for(int j = 0; j < 10; j++) // Individual hours
|
|
||||||
{
|
|
||||||
String subject = timetableHTMLRow[i+1].get(j+1).select("span.subject").text();
|
|
||||||
|
|
||||||
// Subjects like CEL are thrice, even though everyone has them, make it single
|
|
||||||
String[] split = subject.split(" ");
|
|
||||||
HashSet<String> set = new HashSet<>(Arrays.asList(split));
|
|
||||||
String subj = String.join("/", set);
|
|
||||||
|
|
||||||
timetable.get(i).set(j, subj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Element optionsPanel = timetableHTMLDocument.selectFirst("form.listConfigure");
|
|
||||||
|
|
||||||
Elements schoolYear = optionsPanel.select("select[id=schoolYearId]").select("option");
|
|
||||||
Elements timetableId = optionsPanel.select("select[id=timetableId]").select("option");
|
|
||||||
|
|
||||||
for(Element e : schoolYear)
|
|
||||||
{
|
|
||||||
boolean isDefault = e.hasAttr("selected");
|
|
||||||
schoolYearOptions.addOption(new Option(e.text(), e.attr("value"), isDefault));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Element e : timetableId)
|
|
||||||
{
|
|
||||||
// Try to extract the precise school years to make the text shorter
|
|
||||||
String optionDisplayText = Pattern
|
|
||||||
.compile("(Od .* do .*)")
|
|
||||||
.matcher(e.text())
|
|
||||||
.results()
|
|
||||||
.findFirst()
|
|
||||||
.map(m -> m.group(1))
|
|
||||||
.orElse(e.text()); // Just use the whole thing if it doesn't follow the pattern
|
|
||||||
|
|
||||||
boolean isDefault = e.hasAttr("selected"); // To prevent the last option added be picked as default always
|
|
||||||
timetableOptions.addOption(new Option(optionDisplayText, e.attr("value"), isDefault));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public xyz.thastertyn.Types.Timetable getRozvrh()
|
|
||||||
{
|
|
||||||
return timetable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return (timetable == null) ?
|
|
||||||
"Nothing downloaded yet"
|
|
||||||
:
|
|
||||||
"All up and ready";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Options[] getOptions() {
|
|
||||||
return new Options[] {schoolYearOptions, timetableOptions};
|
|
||||||
}
|
|
||||||
}
|
|
127
src/main/java/xyz/thastertyn/Scrape/Znamky.java
Normal file
127
src/main/java/xyz/thastertyn/Scrape/Znamky.java
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package xyz.thastertyn.Scrape;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
import xyz.thastertyn.Tuples.Pair;
|
||||||
|
import xyz.thastertyn.Types.Choice;
|
||||||
|
import xyz.thastertyn.Types.Option;
|
||||||
|
import xyz.thastertyn.Types.Options;
|
||||||
|
import xyz.thastertyn.Types.Predmet;
|
||||||
|
import xyz.thastertyn.Types.Znamka;
|
||||||
|
|
||||||
|
public class Znamky {
|
||||||
|
|
||||||
|
private boolean wasDownloaded;
|
||||||
|
|
||||||
|
// schoolYear, schoolYearId
|
||||||
|
private ArrayList<Predmet> predmety = new ArrayList<>();
|
||||||
|
|
||||||
|
// int znaci id roku, boolean jestli je jen prvni nebo i druhe pololeti
|
||||||
|
private Options schoolYearOptions = new Options("Skolni R.");
|
||||||
|
private Options schoolHalfYearOptions = new Options("Pololeti");
|
||||||
|
|
||||||
|
public void downloadZnamky() throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
download("https://www.spsejecna.cz/score/student");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadZnamky(Choice choice) throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
download(String.format(
|
||||||
|
"https://www.spsejecna.cz/score/student?schoolYearId=%s&schoolYearHalfId=%s",
|
||||||
|
choice.getChoices().get(0),
|
||||||
|
choice.getChoices().get(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void download(String url) throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
//String url =
|
||||||
|
Document znamkyDokumentHTML = Downloader.download(url).get();
|
||||||
|
|
||||||
|
// Predmety ulozene v <tr>
|
||||||
|
Elements[] radkyPredmetuHTML = znamkyDokumentHTML
|
||||||
|
.select("table.score")
|
||||||
|
.select("tr")
|
||||||
|
.stream()
|
||||||
|
.map(Element::children)
|
||||||
|
.toArray(Elements[]::new);
|
||||||
|
|
||||||
|
int subjectIndex = 0;
|
||||||
|
|
||||||
|
for(int i = 1; i < radkyPredmetuHTML.length; i++)
|
||||||
|
{
|
||||||
|
String plnyNazevPredmetu = radkyPredmetuHTML[i].get(0).text();
|
||||||
|
|
||||||
|
String jmenoPredmetu = Pattern
|
||||||
|
.compile("\\((.*?)\\)")
|
||||||
|
.matcher(plnyNazevPredmetu)
|
||||||
|
.results()
|
||||||
|
.findFirst()
|
||||||
|
.map(m -> m.group(1))
|
||||||
|
.orElse(plnyNazevPredmetu);
|
||||||
|
|
||||||
|
predmety.add(new Predmet(jmenoPredmetu));
|
||||||
|
|
||||||
|
for(Element znamkaElement : radkyPredmetuHTML[i].get(1).select("a.score"))
|
||||||
|
{
|
||||||
|
int znamka;
|
||||||
|
boolean jeMala = false;
|
||||||
|
|
||||||
|
String textZnamky = znamkaElement.select("span.value").text();
|
||||||
|
|
||||||
|
znamka = textZnamky.matches("\\d") ?
|
||||||
|
Integer.parseInt(textZnamky) :
|
||||||
|
-1; // Nejspis se jedna o N (Nehodnocen)
|
||||||
|
|
||||||
|
// Mala znamka se bude pocitat jako polovicni vaha
|
||||||
|
jeMala = znamkaElement.hasClass("scoreSmall");
|
||||||
|
|
||||||
|
predmety.get(subjectIndex).addZnamka(new Znamka(znamka, jeMala, textZnamky));
|
||||||
|
}
|
||||||
|
|
||||||
|
subjectIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element optionsPanel = znamkyDokumentHTML.selectFirst("form.listConfigure");
|
||||||
|
|
||||||
|
Elements skolniRoky = optionsPanel.select("select[id=schoolYearId]").select("option");
|
||||||
|
Elements pololeti = optionsPanel.select("select[id=schoolYearHalfId]").select("option");
|
||||||
|
|
||||||
|
for(Element e : skolniRoky)
|
||||||
|
{
|
||||||
|
schoolYearOptions.addOption(new Option(e.text(), e.attr("value")));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Element e : pololeti)
|
||||||
|
{
|
||||||
|
schoolHalfYearOptions.addOption(new Option(e.text(), e.attr("value")));
|
||||||
|
}
|
||||||
|
|
||||||
|
wasDownloaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Predmet> getPredmety()
|
||||||
|
{
|
||||||
|
return predmety;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<Options, Options> getOptions()
|
||||||
|
{
|
||||||
|
return new Pair<Options, Options>(schoolYearOptions, schoolHalfYearOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return (wasDownloaded) ?
|
||||||
|
"All up and ready for use" :
|
||||||
|
"Nothing downloaded yet";
|
||||||
|
}
|
||||||
|
}
|
54
src/main/java/xyz/thastertyn/Tuples/Pair.java
Normal file
54
src/main/java/xyz/thastertyn/Tuples/Pair.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package xyz.thastertyn.Tuples;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ekvitalent Tuplu, ktery neni zabudovan v jave
|
||||||
|
*/
|
||||||
|
public class Pair<T1, T2> {
|
||||||
|
|
||||||
|
|
||||||
|
private T1 value0;
|
||||||
|
private T2 value1;
|
||||||
|
|
||||||
|
public Pair(T1 value0, T2 value1)
|
||||||
|
{
|
||||||
|
this.value0 = value0;
|
||||||
|
this.value1 = value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(T1 value0, T2 value1)
|
||||||
|
{
|
||||||
|
this.value0 = value0;
|
||||||
|
this.value1 = value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T1 getValue0()
|
||||||
|
{
|
||||||
|
return value0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T2 getValue1()
|
||||||
|
{
|
||||||
|
return value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue0(T1 value0)
|
||||||
|
{
|
||||||
|
this.value0 = value0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue1(T2 value1)
|
||||||
|
{
|
||||||
|
this.value1 = value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "[" + value0 + ", " + value1 + "]";
|
||||||
|
}
|
||||||
|
}
|
66
src/main/java/xyz/thastertyn/Tuples/Triplet.java
Normal file
66
src/main/java/xyz/thastertyn/Tuples/Triplet.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package xyz.thastertyn.Tuples;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ekvitalent Tuplu, ktery neni zabudovan v jave
|
||||||
|
*/
|
||||||
|
public class Triplet<T1, T2, T3> {
|
||||||
|
|
||||||
|
private T1 value0;
|
||||||
|
private T2 value1;
|
||||||
|
private T3 value2;
|
||||||
|
|
||||||
|
public Triplet(T1 value0, T2 value1, T3 value2)
|
||||||
|
{
|
||||||
|
this.value0 = value0;
|
||||||
|
this.value1 = value1;
|
||||||
|
this.value2 = value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Triplet()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(T1 value0, T2 value1, T3 value2)
|
||||||
|
{
|
||||||
|
this.value0 = value0;
|
||||||
|
this.value1 = value1;
|
||||||
|
this.value2 = value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T1 getValue0()
|
||||||
|
{
|
||||||
|
return value0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T2 getValue1()
|
||||||
|
{
|
||||||
|
return value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T3 getValue2()
|
||||||
|
{
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue0(T1 value0)
|
||||||
|
{
|
||||||
|
this.value0 = value0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue1(T2 value1)
|
||||||
|
{
|
||||||
|
this.value1 = value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue2(T3 value2)
|
||||||
|
{
|
||||||
|
this.value2 = value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "[" + value0 + ", " + value1 + "," + value2 + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
public class AbsenceList {
|
|
||||||
|
|
||||||
private String date;
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
public AbsenceList(String date, String description)
|
|
||||||
{
|
|
||||||
this.date = date;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDate() {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(String datum) {
|
|
||||||
this.date = datum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDescription(String popis) {
|
|
||||||
this.description = popis;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +1,17 @@
|
|||||||
package xyz.thastertyn.Types;
|
package xyz.thastertyn.Types;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
|
||||||
* A choice parsed from dropdowns on the site. Usually contains something like school year or half year id
|
|
||||||
*/
|
|
||||||
public class Choice {
|
public class Choice {
|
||||||
|
|
||||||
private List<String> choices;
|
private ArrayList<String> choices;
|
||||||
|
public Choice(String... choices)
|
||||||
public Choice(List<String> c)
|
|
||||||
{
|
{
|
||||||
this.choices = c;
|
this.choices.addAll(Arrays.asList(choices));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getChoices()
|
public ArrayList<String> getChoices()
|
||||||
{
|
{
|
||||||
return choices;
|
return choices;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores username and password
|
|
||||||
*/
|
|
||||||
public class Credentials {
|
|
||||||
|
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
public Credentials(String username, String password) {
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores a single day from the timetable as an array of strings
|
|
||||||
*/
|
|
||||||
public class DayOfTimetable {
|
|
||||||
|
|
||||||
private String[] subjects = new String[10];
|
|
||||||
|
|
||||||
public String get(int index)
|
|
||||||
{
|
|
||||||
return subjects[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(int index, String subject)
|
|
||||||
{
|
|
||||||
subjects[index] = subject;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the final mark from a subject
|
|
||||||
*/
|
|
||||||
public class FinalMark{
|
|
||||||
public static final FinalMark VYBORNY = new FinalMark(1, "1");
|
|
||||||
public static final FinalMark CHVALITEBNY = new FinalMark(2, "2");
|
|
||||||
public static final FinalMark DOBRY = new FinalMark(3, "3");
|
|
||||||
public static final FinalMark DOSTATECNY = new FinalMark(4, "4");
|
|
||||||
public static final FinalMark NEDOSTATECNY = new FinalMark(5, "5");
|
|
||||||
|
|
||||||
public static final FinalMark NOTHING = new FinalMark(0, "");
|
|
||||||
|
|
||||||
public static final FinalMark NEHODNOCEN = new FinalMark(-1, "N");
|
|
||||||
public static final FinalMark NAPOMENUT_ZA_NEKLASIFIKACI = new FinalMark(-2, "N?");
|
|
||||||
|
|
||||||
public static final FinalMark UVOLNEN = new FinalMark(-3, "U");
|
|
||||||
|
|
||||||
public static final FinalMark NAPOMENUT_ZA_ZAOSTAVANI = new FinalMark(-4, "5?");
|
|
||||||
|
|
||||||
public static final FinalMark UNKNOWN = new FinalMark(-5, "?");
|
|
||||||
// #94701b
|
|
||||||
private double value;
|
|
||||||
private String stringValue;
|
|
||||||
|
|
||||||
private FinalMark(double value, String stringValue)
|
|
||||||
{
|
|
||||||
this.stringValue = stringValue;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FinalMark(double value)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.stringValue = String.format("%.2f", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue()
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return stringValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FinalMark fromValue(String value)
|
|
||||||
{
|
|
||||||
if(!value.matches("[0-9]"))
|
|
||||||
{
|
|
||||||
return switch (value) {
|
|
||||||
case "N" -> NEHODNOCEN;
|
|
||||||
case "N?" -> NAPOMENUT_ZA_NEKLASIFIKACI;
|
|
||||||
case "5?" -> NAPOMENUT_ZA_ZAOSTAVANI;
|
|
||||||
case "U" -> UVOLNEN;
|
|
||||||
default -> UNKNOWN;
|
|
||||||
};
|
|
||||||
}else{
|
|
||||||
int numericValue = Integer.parseInt(value);
|
|
||||||
|
|
||||||
return switch (numericValue) {
|
|
||||||
case 1 -> VYBORNY;
|
|
||||||
case 2 -> CHVALITEBNY;
|
|
||||||
case 3 -> DOBRY;
|
|
||||||
case 4 -> DOSTATECNY;
|
|
||||||
case 5 -> NEDOSTATECNY;
|
|
||||||
default -> UNKNOWN;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around credentials with the change of having a boolean for whether the user wants to save the credentials or not
|
|
||||||
*/
|
|
||||||
public class InputtedCredentials extends Credentials {
|
|
||||||
|
|
||||||
private boolean save;
|
|
||||||
|
|
||||||
public InputtedCredentials(String username, String password, boolean save)
|
|
||||||
{
|
|
||||||
super(username, password);
|
|
||||||
this.save = save;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputtedCredentials(Credentials credentials, boolean save)
|
|
||||||
{
|
|
||||||
super(credentials.getUsername(), credentials.getPassword());
|
|
||||||
this.save = save;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Credentials getCredentials()
|
|
||||||
{
|
|
||||||
return new Credentials(getUsername(), getPassword());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean save() {
|
|
||||||
return save;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A single mark. holds numeric value, weight - small = 1, normal 2
|
|
||||||
*/
|
|
||||||
public class Mark {
|
|
||||||
|
|
||||||
private int mark;
|
|
||||||
private String markAsText;
|
|
||||||
private int weight;
|
|
||||||
|
|
||||||
public Mark(int mark, boolean isSmall, String markAsText)
|
|
||||||
{
|
|
||||||
this.mark = mark;
|
|
||||||
this.weight = (isSmall) ? 1 : 2;
|
|
||||||
this.markAsText = markAsText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMark()
|
|
||||||
{
|
|
||||||
return mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWeight()
|
|
||||||
{
|
|
||||||
return weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return markAsText;
|
|
||||||
}
|
|
||||||
}
|
|
13
src/main/java/xyz/thastertyn/Types/OmluvnyList.java
Normal file
13
src/main/java/xyz/thastertyn/Types/OmluvnyList.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package xyz.thastertyn.Types;
|
||||||
|
|
||||||
|
public class OmluvnyList {
|
||||||
|
|
||||||
|
private String datum;
|
||||||
|
private String popis;
|
||||||
|
|
||||||
|
public OmluvnyList(String datum, String popis)
|
||||||
|
{
|
||||||
|
this.datum = datum;
|
||||||
|
this.popis = popis;
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,27 @@
|
|||||||
package xyz.thastertyn.Types;
|
package xyz.thastertyn.Types;
|
||||||
|
|
||||||
/**
|
|
||||||
* A single option. Holds a text description, the thing displayed and a string value, the one used in url
|
|
||||||
*/
|
|
||||||
public class Option {
|
public class Option {
|
||||||
|
|
||||||
private String displayText;
|
private String text;
|
||||||
private String value;
|
private String value;
|
||||||
private boolean isDefault;
|
public Option(String text, String value) {
|
||||||
|
this.text = text;
|
||||||
public Option(String text, String value, boolean isDefault) {
|
|
||||||
this.displayText = text;
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.isDefault = isDefault;
|
|
||||||
}
|
}
|
||||||
public boolean isDefault() {
|
public String getText() {
|
||||||
return isDefault;
|
return text;
|
||||||
|
}
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
}
|
}
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return displayText;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,6 @@ package xyz.thastertyn.Types;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds all possible a single dropdown on the website can have.
|
|
||||||
*/
|
|
||||||
public class Options {
|
public class Options {
|
||||||
|
|
||||||
private ArrayList<Option> options = new ArrayList<>();
|
private ArrayList<Option> options = new ArrayList<>();
|
||||||
|
56
src/main/java/xyz/thastertyn/Types/Predmet.java
Normal file
56
src/main/java/xyz/thastertyn/Types/Predmet.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package xyz.thastertyn.Types;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Predmet {
|
||||||
|
|
||||||
|
private ArrayList<Znamka> znamky = new ArrayList<>();
|
||||||
|
private String jmenoPredmetu = "";
|
||||||
|
|
||||||
|
private int vyslednaZnamka = 0;
|
||||||
|
|
||||||
|
public Predmet(String jmenoPredmetu)
|
||||||
|
{
|
||||||
|
this.jmenoPredmetu = jmenoPredmetu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addZnamka(Znamka novaZnamka)
|
||||||
|
{
|
||||||
|
znamky.add(novaZnamka);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPrumer()
|
||||||
|
{
|
||||||
|
if(vyslednaZnamka != 0)
|
||||||
|
{
|
||||||
|
return vyslednaZnamka;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(znamky.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int celkem = znamky
|
||||||
|
.stream()
|
||||||
|
.mapToInt((z) -> z.getZnamka() * z.getVaha())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
int vahy = znamky
|
||||||
|
.stream()
|
||||||
|
.mapToInt((z) -> z.getVaha())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
return (double) celkem / vahy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJmenoPredmetu()
|
||||||
|
{
|
||||||
|
return jmenoPredmetu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Znamka> getZnamky()
|
||||||
|
{
|
||||||
|
return znamky;
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reports for parents. Holds a string of text and a boolean for positivity to determine color for display
|
|
||||||
*/
|
|
||||||
public class Reports {
|
|
||||||
|
|
||||||
private String text;
|
|
||||||
private boolean isPositive;
|
|
||||||
|
|
||||||
public Reports(String text, boolean isPositive)
|
|
||||||
{
|
|
||||||
this.text = text;
|
|
||||||
this.isPositive = isPositive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPositive()
|
|
||||||
{
|
|
||||||
return isPositive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText()
|
|
||||||
{
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subject for marks. Holds a name, all its marks and the final mark
|
|
||||||
*/
|
|
||||||
public class Subject {
|
|
||||||
|
|
||||||
private ArrayList<Mark> marks = new ArrayList<>();
|
|
||||||
private String subjectName = "";
|
|
||||||
private boolean isFinal = false;
|
|
||||||
|
|
||||||
private FinalMark finalMark = FinalMark.UNKNOWN;
|
|
||||||
|
|
||||||
public Subject(String subjectName)
|
|
||||||
{
|
|
||||||
this.subjectName = subjectName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Subject(String subjectName, FinalMark finalMark)
|
|
||||||
{
|
|
||||||
this.subjectName = subjectName;
|
|
||||||
this.finalMark = finalMark;
|
|
||||||
isFinal = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMark(Mark newMark)
|
|
||||||
{
|
|
||||||
marks.add(newMark);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateFinalMark()
|
|
||||||
{
|
|
||||||
if(marks.isEmpty())
|
|
||||||
{
|
|
||||||
this.finalMark = FinalMark.NOTHING;
|
|
||||||
}else{
|
|
||||||
int total = marks
|
|
||||||
.stream()
|
|
||||||
.mapToInt((z) -> z.getMark() * z.getWeight())
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
int weight = marks
|
|
||||||
.stream()
|
|
||||||
.mapToInt((z) -> z.getWeight())
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
double finalMark = ((double) total / weight);
|
|
||||||
|
|
||||||
this.finalMark = new FinalMark(finalMark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FinalMark getFinalMark()
|
|
||||||
{
|
|
||||||
if(!isFinal)
|
|
||||||
{
|
|
||||||
calculateFinalMark();
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalMark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFinal()
|
|
||||||
{
|
|
||||||
return isFinal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSubjectName()
|
|
||||||
{
|
|
||||||
return subjectName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<Mark> getMarks()
|
|
||||||
{
|
|
||||||
return marks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
package xyz.thastertyn.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whole timetable. holds an array of {@link DayOfTimetable} for each day
|
|
||||||
*/
|
|
||||||
public class Timetable {
|
|
||||||
|
|
||||||
private DayOfTimetable[] timetable = new DayOfTimetable[5];
|
|
||||||
|
|
||||||
public Timetable()
|
|
||||||
{
|
|
||||||
for(int i = 0; i < timetable.length; i++)
|
|
||||||
{
|
|
||||||
timetable[i] = new DayOfTimetable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DayOfTimetable get(int day)
|
|
||||||
{
|
|
||||||
return timetable[day];
|
|
||||||
}
|
|
||||||
}
|
|
30
src/main/java/xyz/thastertyn/Types/Znamka.java
Normal file
30
src/main/java/xyz/thastertyn/Types/Znamka.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package xyz.thastertyn.Types;
|
||||||
|
|
||||||
|
public class Znamka {
|
||||||
|
|
||||||
|
private int znamka;
|
||||||
|
private String znamkaJakoText;
|
||||||
|
private int vaha;
|
||||||
|
|
||||||
|
public Znamka(int znamka, boolean malaZnamka, String znamkaJakoText/*, String text, String datum*/)
|
||||||
|
{
|
||||||
|
this.znamka = znamka;
|
||||||
|
this.vaha = (malaZnamka) ? 1 : 2;
|
||||||
|
this.znamkaJakoText = znamkaJakoText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZnamka()
|
||||||
|
{
|
||||||
|
return znamka;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVaha()
|
||||||
|
{
|
||||||
|
return vaha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText()
|
||||||
|
{
|
||||||
|
return znamkaJakoText;
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Content;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.gui2.Direction;
|
|
||||||
import com.googlecode.lanterna.gui2.GridLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Label;
|
|
||||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
|
|
||||||
import xyz.thastertyn.UserInterface.Listeners.UpdateListener;
|
|
||||||
|
|
||||||
public class AbsenceList extends JecnaContent{
|
|
||||||
|
|
||||||
private xyz.thastertyn.Scrape.AbsenceList omluvnyList = new xyz.thastertyn.Scrape.AbsenceList();
|
|
||||||
|
|
||||||
public AbsenceList(UpdateListener listener)
|
|
||||||
{
|
|
||||||
super(listener);
|
|
||||||
this.mainPanel = new Panel()
|
|
||||||
.setLayoutManager(new GridLayout(1));
|
|
||||||
this.borderLabel = new Label("Omluvny L.");
|
|
||||||
super.scraper = omluvnyList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setGUI()
|
|
||||||
{
|
|
||||||
this.mainPanel.removeAllComponents();
|
|
||||||
ArrayList<xyz.thastertyn.Types.AbsenceList> a = omluvnyList.getData();
|
|
||||||
|
|
||||||
Panel content = new Panel()
|
|
||||||
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
|
||||||
.addTo(mainPanel);
|
|
||||||
|
|
||||||
for(xyz.thastertyn.Types.AbsenceList omluvnyList : a)
|
|
||||||
{
|
|
||||||
content.addComponent(new Label(omluvnyList.getDate() + " - " + omluvnyList.getDescription()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,113 +1,22 @@
|
|||||||
package xyz.thastertyn.UserInterface.Content;
|
package xyz.thastertyn.UserInterface.Content;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.gui2.Label;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
|
||||||
import xyz.thastertyn.Scrape.JecnaScrape;
|
|
||||||
import xyz.thastertyn.Types.Choice;
|
import xyz.thastertyn.Types.Choice;
|
||||||
import xyz.thastertyn.UserInterface.Dialogs.OptionsDialog;
|
|
||||||
import xyz.thastertyn.UserInterface.Listeners.UpdateListener;
|
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
|
import com.googlecode.lanterna.gui2.Label;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper to include all classes that deal with content in some way
|
* Wrapper to include all classes that deal with content in some way
|
||||||
*/
|
*/
|
||||||
public abstract class JecnaContent {
|
public abstract class JecnaContent {
|
||||||
|
|
||||||
protected Panel mainPanel;
|
public abstract Panel getPanel();
|
||||||
protected boolean hasStarted = false;
|
public abstract void downloadDefault();
|
||||||
protected Label borderLabel;
|
protected abstract void download(Choice choice);
|
||||||
protected UpdateListener listener;
|
public abstract boolean hasStarted();
|
||||||
protected JecnaScrape scraper;
|
public abstract Label getLabel();
|
||||||
|
public abstract void showOptions(final WindowBasedTextGUI textGUI);
|
||||||
/**
|
|
||||||
* Prepares it's content to be display by gettings the panel from {@link #getPanel()}
|
|
||||||
*/
|
|
||||||
protected abstract void setGUI();
|
protected abstract void setGUI();
|
||||||
|
|
||||||
public JecnaContent(UpdateListener listener)
|
|
||||||
{
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call its scraper class to download content using the provided choice
|
|
||||||
* @param choice
|
|
||||||
* @throws IOException in case download fails in some way
|
|
||||||
*/
|
|
||||||
protected void download(Choice choice) throws IOException
|
|
||||||
{
|
|
||||||
if(choice != null)
|
|
||||||
{
|
|
||||||
scraper.download(choice);
|
|
||||||
setGUI();
|
|
||||||
mainPanel.setPreferredSize(mainPanel.calculatePreferredSize());
|
|
||||||
listener.updatePanel();
|
|
||||||
}else{
|
|
||||||
scraper.download();
|
|
||||||
setGUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
hasStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells scraper to download the default content and parse it
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void downloadDefault() throws IOException
|
|
||||||
{
|
|
||||||
download(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link OptionsDialog} to display its options
|
|
||||||
* @param textGUI where to display the dialog
|
|
||||||
* @throws IOException upon ok, conent is immediatelly downloaded using {@link #download( choice_from_dialog )}
|
|
||||||
*/
|
|
||||||
public void showOptions(WindowBasedTextGUI textGUI) throws IOException {
|
|
||||||
|
|
||||||
if(scraper.getOptions() == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionsDialog dialog = new OptionsDialog(scraper.getOptions());
|
|
||||||
|
|
||||||
Choice choice = dialog.showDialog(textGUI);
|
|
||||||
|
|
||||||
if(choice != null)
|
|
||||||
{
|
|
||||||
download(choice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the panel where the content should be held and already arranged for display
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Panel getPanel()
|
|
||||||
{
|
|
||||||
return this.mainPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if something has been downloaded already
|
|
||||||
* @return true or false depending on the download state
|
|
||||||
*/
|
|
||||||
public boolean hasStarted()
|
|
||||||
{
|
|
||||||
return this.hasStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a label with the title text like "Známky", etc.
|
|
||||||
*/
|
|
||||||
public Label getLabel()
|
|
||||||
{
|
|
||||||
return this.borderLabel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package xyz.thastertyn.UserInterface.Content;
|
package xyz.thastertyn.UserInterface.Content;
|
||||||
|
|
||||||
public class Canteen {
|
public class Jidelna {
|
||||||
|
|
||||||
}
|
}
|
@ -1,117 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Content;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.TextColor;
|
|
||||||
import com.googlecode.lanterna.TextColor.ANSI;
|
|
||||||
import com.googlecode.lanterna.graphics.SimpleTheme;
|
|
||||||
import com.googlecode.lanterna.gui2.Direction;
|
|
||||||
import com.googlecode.lanterna.gui2.GridLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Label;
|
|
||||||
import com.googlecode.lanterna.gui2.LayoutData;
|
|
||||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Types.FinalMark;
|
|
||||||
import xyz.thastertyn.Types.Subject;
|
|
||||||
import xyz.thastertyn.Types.Mark;
|
|
||||||
import xyz.thastertyn.UserInterface.Listeners.UpdateListener;
|
|
||||||
|
|
||||||
public class Marks extends JecnaContent {
|
|
||||||
|
|
||||||
private final TextColor.RGB VYBORNY = new TextColor.RGB(85,212,0);
|
|
||||||
private final TextColor.RGB CHVALITEBNY = new TextColor.RGB(196,224,80);
|
|
||||||
private final TextColor.RGB DOBRY = new TextColor.RGB(255,213,42);
|
|
||||||
private final TextColor.RGB DOSTATECNY = new TextColor.RGB(255,102,0);
|
|
||||||
private final TextColor.RGB NEDOSTATECNY = new TextColor.RGB(255,48,48);
|
|
||||||
private final TextColor.RGB NEHODNOCEN = new TextColor.RGB(0,0,0);
|
|
||||||
|
|
||||||
private final LayoutData ALIGN_LEFT = GridLayout.createLayoutData(
|
|
||||||
GridLayout.Alignment.BEGINNING,
|
|
||||||
GridLayout.Alignment.BEGINNING,
|
|
||||||
false,
|
|
||||||
false);
|
|
||||||
|
|
||||||
private final LayoutData ALIGN_RIGHT = GridLayout.createLayoutData(
|
|
||||||
GridLayout.Alignment.END,
|
|
||||||
GridLayout.Alignment.BEGINNING,
|
|
||||||
true,
|
|
||||||
false);
|
|
||||||
|
|
||||||
private xyz.thastertyn.Scrape.Marks marks = new xyz.thastertyn.Scrape.Marks();
|
|
||||||
|
|
||||||
public Marks(UpdateListener listener)
|
|
||||||
{
|
|
||||||
super(listener);
|
|
||||||
|
|
||||||
this.mainPanel = new Panel()
|
|
||||||
.setLayoutManager(new GridLayout(3));
|
|
||||||
this.borderLabel = new Label("Znamky");
|
|
||||||
super.scraper = this.marks;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setGUI()
|
|
||||||
{
|
|
||||||
mainPanel.removeAllComponents();
|
|
||||||
|
|
||||||
ArrayList<Subject> subjects = marks.getSubjects();
|
|
||||||
|
|
||||||
// Colors are used a lot and instead of referencing them in lengthy lines, this seems shorter
|
|
||||||
HashMap<Integer, SimpleTheme> colors = new HashMap<>();
|
|
||||||
colors.put(1, new SimpleTheme(ANSI.BLACK, VYBORNY));
|
|
||||||
colors.put(2, new SimpleTheme(ANSI.BLACK, CHVALITEBNY));
|
|
||||||
colors.put(3, new SimpleTheme(ANSI.BLACK, DOBRY));
|
|
||||||
colors.put(4, new SimpleTheme(ANSI.BLACK, DOSTATECNY));
|
|
||||||
colors.put(5, new SimpleTheme(ANSI.BLACK, NEDOSTATECNY));
|
|
||||||
colors.put(-1, new SimpleTheme(ANSI.WHITE, NEHODNOCEN));
|
|
||||||
colors.put(-2, new SimpleTheme(ANSI.WHITE, NEHODNOCEN));
|
|
||||||
|
|
||||||
// Column for subject names
|
|
||||||
Panel subjectNames = new Panel()
|
|
||||||
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
|
||||||
.setLayoutData(ALIGN_LEFT)
|
|
||||||
.addTo(mainPanel);
|
|
||||||
|
|
||||||
// Column for marks
|
|
||||||
Panel marks = new Panel()
|
|
||||||
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
|
||||||
.setLayoutData(ALIGN_LEFT)
|
|
||||||
.addTo(mainPanel);
|
|
||||||
|
|
||||||
// Column for final mark
|
|
||||||
Panel finalMarks = new Panel()
|
|
||||||
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
|
||||||
.setLayoutData(ALIGN_RIGHT)
|
|
||||||
.addTo(mainPanel);
|
|
||||||
|
|
||||||
for(Subject subject : subjects)
|
|
||||||
{
|
|
||||||
Panel individualMarks = new Panel()
|
|
||||||
.setLayoutManager(new LinearLayout(Direction.HORIZONTAL))
|
|
||||||
.addTo(marks);
|
|
||||||
|
|
||||||
if(subject.getMarks().isEmpty())
|
|
||||||
{
|
|
||||||
individualMarks.addComponent(new Label(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Mark mark : subject.getMarks())
|
|
||||||
{
|
|
||||||
Label markLabel = new Label(mark.toString());
|
|
||||||
markLabel.setTheme(colors.get(mark.getMark()));
|
|
||||||
individualMarks.addComponent(markLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
FinalMark finalMark = subject.getFinalMark();
|
|
||||||
|
|
||||||
Label vysl = new Label(finalMark.toString());
|
|
||||||
|
|
||||||
vysl.setTheme(colors.get((int) Math.round(finalMark.getValue())));
|
|
||||||
|
|
||||||
subjectNames.addComponent(new Label(subject.getSubjectName()));
|
|
||||||
finalMarks.addComponent(vysl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,76 @@
|
|||||||
|
package xyz.thastertyn.UserInterface.Content;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.gui2.Label;
|
||||||
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
|
||||||
|
import xyz.thastertyn.Tuples.Pair;
|
||||||
|
import xyz.thastertyn.Types.Choice;
|
||||||
|
|
||||||
|
public class OmluvnyList extends JecnaContent{
|
||||||
|
|
||||||
|
private Panel omluvnyPanel = new Panel();
|
||||||
|
private Label borderLabel = new Label("Omluvny L.");
|
||||||
|
private xyz.thastertyn.Scrape.OmluvnyList omluvnyList = new xyz.thastertyn.Scrape.OmluvnyList();
|
||||||
|
|
||||||
|
private boolean hasStarted = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void downloadDefault()
|
||||||
|
{
|
||||||
|
download(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void download(Choice choice)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
omluvnyList.downloadOmluvnyList();
|
||||||
|
setGUI();
|
||||||
|
|
||||||
|
hasStarted = true;
|
||||||
|
}catch(UnknownHostException e)
|
||||||
|
{
|
||||||
|
// omluvnyPanel.addComponent(new Label("A connection error occurred"));
|
||||||
|
}catch(IOException e)
|
||||||
|
{
|
||||||
|
// omluvnyPanel.addComponent(new Label("An error occurred"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGUI()
|
||||||
|
{
|
||||||
|
ArrayList<Pair<String, String>> a = omluvnyList.getData();
|
||||||
|
|
||||||
|
for(Pair<String, String> p : a)
|
||||||
|
{
|
||||||
|
omluvnyPanel.addComponent(new Label(p.getValue0() + " - " + p.getValue1()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Panel getPanel() {
|
||||||
|
return omluvnyPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStarted() {
|
||||||
|
return hasStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Label getLabel() {
|
||||||
|
return borderLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showOptions(WindowBasedTextGUI textGUI) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new UnsupportedOperationException("Unimplemented method 'getOptions'");
|
||||||
|
}
|
||||||
|
}
|
@ -1,56 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Content;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.TextColor.ANSI;
|
|
||||||
import com.googlecode.lanterna.gui2.Direction;
|
|
||||||
import com.googlecode.lanterna.gui2.GridLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Label;
|
|
||||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
|
|
||||||
import xyz.thastertyn.UserInterface.Listeners.UpdateListener;
|
|
||||||
|
|
||||||
public class Reports extends JecnaContent {
|
|
||||||
|
|
||||||
private xyz.thastertyn.Scrape.Reports reports = new xyz.thastertyn.Scrape.Reports();
|
|
||||||
|
|
||||||
public Reports(UpdateListener listener)
|
|
||||||
{
|
|
||||||
super(listener);
|
|
||||||
this.mainPanel = new Panel().setLayoutManager(new GridLayout(1)
|
|
||||||
.setLeftMarginSize(1)
|
|
||||||
.setRightMarginSize(1));
|
|
||||||
this.borderLabel = new Label("Sdeleni R.");
|
|
||||||
super.scraper = this.reports;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setGUI()
|
|
||||||
{
|
|
||||||
mainPanel.removeAllComponents();
|
|
||||||
|
|
||||||
ArrayList<xyz.thastertyn.Types.Reports> reportsList = reports.getSdeleni();
|
|
||||||
|
|
||||||
for(xyz.thastertyn.Types.Reports reports : reportsList)
|
|
||||||
{
|
|
||||||
Panel row = new Panel().setLayoutManager(new LinearLayout(Direction.HORIZONTAL));
|
|
||||||
|
|
||||||
Label checkmark = new Label("");
|
|
||||||
Label text = new Label(reports.getText());
|
|
||||||
|
|
||||||
if(reports.isPositive())
|
|
||||||
{
|
|
||||||
checkmark.setForegroundColor(ANSI.GREEN);
|
|
||||||
checkmark.setText("✓");
|
|
||||||
}else{
|
|
||||||
checkmark.setForegroundColor(ANSI.RED);
|
|
||||||
checkmark.setText("✗");
|
|
||||||
}
|
|
||||||
|
|
||||||
row.addComponent(checkmark)
|
|
||||||
.addComponent(text)
|
|
||||||
.addTo(mainPanel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,94 @@
|
|||||||
|
package xyz.thastertyn.UserInterface.Content;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.gui2.Label;
|
||||||
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
import com.googlecode.lanterna.gui2.table.Table;
|
||||||
|
|
||||||
|
import xyz.thastertyn.Types.Choice;
|
||||||
|
|
||||||
|
public class Rozvrh extends JecnaContent {
|
||||||
|
|
||||||
|
private Panel rozvrhPanel = new Panel();
|
||||||
|
private Label borderLabel = new Label("Rozvrh");
|
||||||
|
private xyz.thastertyn.Scrape.Rozvrh rozvrh = new xyz.thastertyn.Scrape.Rozvrh();
|
||||||
|
|
||||||
|
private boolean hasStarted = false;
|
||||||
|
|
||||||
|
private String[] labels = {"Den", "7:30-8:15", "8:25-9:10", "9:20-10:05", "10:20-11:05", "11:15-12:00", "12:10-12:55", "13:05-13:50", "14:00-14:45", "14:55-15:40", "15:50-16:35"};
|
||||||
|
//private String[] labels = {"Den", "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10."};
|
||||||
|
|
||||||
|
String[] daysLabels = {"PO", "UT", "ST", "CT", "PA"};
|
||||||
|
|
||||||
|
Table<String> t = new Table<>(labels);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void downloadDefault()
|
||||||
|
{
|
||||||
|
download(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void download(Choice choice)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
rozvrh.downloadRozvrh();
|
||||||
|
setGUI();
|
||||||
|
|
||||||
|
hasStarted = true;
|
||||||
|
}catch(UnknownHostException e)
|
||||||
|
{
|
||||||
|
rozvrhPanel.addComponent(new Label("A connection error occurred"));
|
||||||
|
}catch(IOException e)
|
||||||
|
{
|
||||||
|
rozvrhPanel.addComponent(new Label("An error occurred"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGUI()
|
||||||
|
{
|
||||||
|
String[][] rozvrhArray = rozvrh.getRozvrh();
|
||||||
|
|
||||||
|
String[] den = new String[11];
|
||||||
|
|
||||||
|
for(int i = 0; i < rozvrhArray.length; i++)
|
||||||
|
{
|
||||||
|
den[0] = daysLabels[i];
|
||||||
|
for(int j = 1; j < rozvrhArray[i].length + 1; j++)
|
||||||
|
{
|
||||||
|
den[j] = (rozvrhArray[i][j - 1].isBlank()) ? " - " : rozvrhArray[i][j - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
t.getTableModel().addRow(den);
|
||||||
|
}
|
||||||
|
rozvrhPanel.addComponent(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStarted()
|
||||||
|
{
|
||||||
|
return hasStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Panel getPanel()
|
||||||
|
{
|
||||||
|
return rozvrhPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Label getLabel()
|
||||||
|
{
|
||||||
|
return borderLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showOptions(WindowBasedTextGUI textGUI) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new UnsupportedOperationException("Unimplemented method 'getOptions'");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package xyz.thastertyn.UserInterface.Content;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.gui2.GridLayout;
|
||||||
|
import com.googlecode.lanterna.gui2.Label;
|
||||||
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
|
||||||
|
import xyz.thastertyn.Types.Choice;
|
||||||
|
|
||||||
|
public class Sdeleni extends JecnaContent {
|
||||||
|
|
||||||
|
private Panel sdeleniPanel = new Panel();
|
||||||
|
private Label borderLabel = new Label("Sdeleni R.");
|
||||||
|
|
||||||
|
private xyz.thastertyn.Scrape.Sdeleni sdeleni = new xyz.thastertyn.Scrape.Sdeleni();
|
||||||
|
|
||||||
|
private boolean hasStarted = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void downloadDefault()
|
||||||
|
{
|
||||||
|
download(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void download(Choice choice)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
sdeleni.downloadSdeleni();
|
||||||
|
|
||||||
|
hasStarted = true;
|
||||||
|
}catch(UnknownHostException e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}catch(IOException e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGUI()
|
||||||
|
{
|
||||||
|
sdeleniPanel.setLayoutManager(new GridLayout(1)
|
||||||
|
.setLeftMarginSize(1)
|
||||||
|
.setRightMarginSize(1));
|
||||||
|
|
||||||
|
ArrayList<String> sdeleniList = sdeleni.getSdeleni();
|
||||||
|
|
||||||
|
for(String s : sdeleniList)
|
||||||
|
{
|
||||||
|
sdeleniPanel.addComponent(new Label(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Label getLabel() {
|
||||||
|
return borderLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Panel getPanel() {
|
||||||
|
return sdeleniPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStarted() {
|
||||||
|
return hasStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showOptions(WindowBasedTextGUI textGUI) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new UnsupportedOperationException("Unimplemented method 'getOptions'");
|
||||||
|
}
|
||||||
|
}
|
@ -1,58 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Content;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.gui2.Label;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
import com.googlecode.lanterna.gui2.table.Table;
|
|
||||||
|
|
||||||
import xyz.thastertyn.UserInterface.Listeners.UpdateListener;
|
|
||||||
|
|
||||||
public class Timetable extends JecnaContent {
|
|
||||||
|
|
||||||
private xyz.thastertyn.Scrape.Timetable rozvrh = new xyz.thastertyn.Scrape.Timetable();
|
|
||||||
|
|
||||||
private String[] labels = {"Den", "7:30-8:15", "8:25-9:10", "9:20-10:05", "10:20-11:05", "11:15-12:00", "12:10-12:55", "13:05-13:50", "14:00-14:45", "14:55-15:40", "15:50-16:35"};
|
|
||||||
//private String[] labels = {"Den", "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10."};
|
|
||||||
|
|
||||||
String[] daysLabels = {"PO", "UT", "ST", "CT", "PA"};
|
|
||||||
|
|
||||||
Table<String> table;
|
|
||||||
|
|
||||||
public Timetable(UpdateListener listener)
|
|
||||||
{
|
|
||||||
super(listener);
|
|
||||||
this.mainPanel = new Panel();
|
|
||||||
this.borderLabel = new Label("Rozvrh");
|
|
||||||
super.scraper = this.rozvrh;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setGUI()
|
|
||||||
{
|
|
||||||
mainPanel.removeAllComponents();
|
|
||||||
table = new Table<>(labels);
|
|
||||||
xyz.thastertyn.Types.Timetable timetable = rozvrh.getRozvrh();
|
|
||||||
|
|
||||||
for(int day = 0; day < 5; day++)
|
|
||||||
{
|
|
||||||
List<String> currentRow = new ArrayList<>();
|
|
||||||
|
|
||||||
// Set the day (Po, Ut, St,...)
|
|
||||||
currentRow.add(daysLabels[day]);
|
|
||||||
|
|
||||||
// Add the classes
|
|
||||||
for(int hour = 0; hour < 10; hour++)
|
|
||||||
{
|
|
||||||
currentRow.add((timetable.get(day).get(hour).isBlank()) ?
|
|
||||||
" - " // Empty class, nothing taught at that moment
|
|
||||||
:
|
|
||||||
timetable.get(day).get(hour)); // Get class
|
|
||||||
}
|
|
||||||
|
|
||||||
table.getTableModel().addRow(currentRow);
|
|
||||||
}
|
|
||||||
mainPanel.addComponent(table);
|
|
||||||
}
|
|
||||||
}
|
|
168
src/main/java/xyz/thastertyn/UserInterface/Content/Znamky.java
Normal file
168
src/main/java/xyz/thastertyn/UserInterface/Content/Znamky.java
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
package xyz.thastertyn.UserInterface.Content;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.TextColor;
|
||||||
|
import com.googlecode.lanterna.TextColor.ANSI;
|
||||||
|
import com.googlecode.lanterna.graphics.SimpleTheme;
|
||||||
|
import com.googlecode.lanterna.gui2.Direction;
|
||||||
|
import com.googlecode.lanterna.gui2.GridLayout;
|
||||||
|
import com.googlecode.lanterna.gui2.Label;
|
||||||
|
import com.googlecode.lanterna.gui2.LayoutData;
|
||||||
|
import com.googlecode.lanterna.gui2.LinearLayout;
|
||||||
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
|
||||||
|
import xyz.thastertyn.Types.Choice;
|
||||||
|
import xyz.thastertyn.Types.Predmet;
|
||||||
|
import xyz.thastertyn.Types.Znamka;
|
||||||
|
import xyz.thastertyn.UserInterface.Dialogs.OptionsDialog;
|
||||||
|
|
||||||
|
public class Znamky extends JecnaContent {
|
||||||
|
|
||||||
|
private final TextColor.RGB VYBORNY = new TextColor.RGB(85,212,0);
|
||||||
|
private final TextColor.RGB CHVALITEBNY = new TextColor.RGB(196,224,80);
|
||||||
|
private final TextColor.RGB DOBRY = new TextColor.RGB(255,213,42);
|
||||||
|
private final TextColor.RGB DOSTATECNY = new TextColor.RGB(255,102,0);
|
||||||
|
private final TextColor.RGB NEDOSTATECNY = new TextColor.RGB(255,48,48);
|
||||||
|
private final TextColor.RGB NEHODNOCEN = new TextColor.RGB(0,0,0);
|
||||||
|
|
||||||
|
private final LayoutData ALIGN_LEFT = GridLayout.createLayoutData(
|
||||||
|
GridLayout.Alignment.BEGINNING,
|
||||||
|
GridLayout.Alignment.BEGINNING,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
|
|
||||||
|
private final LayoutData ALIGN_RIGHT = GridLayout.createLayoutData(
|
||||||
|
GridLayout.Alignment.END,
|
||||||
|
GridLayout.Alignment.BEGINNING,
|
||||||
|
true,
|
||||||
|
false);
|
||||||
|
|
||||||
|
private Panel mainPanel = new Panel()
|
||||||
|
.setLayoutManager(new GridLayout(3));
|
||||||
|
|
||||||
|
private Label borderLabel = new Label("Znamky");
|
||||||
|
private xyz.thastertyn.Scrape.Znamky znamky = new xyz.thastertyn.Scrape.Znamky();
|
||||||
|
|
||||||
|
private boolean hasStarted = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void downloadDefault()
|
||||||
|
{
|
||||||
|
download(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void download(Choice choice)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
if(choice != null)
|
||||||
|
{
|
||||||
|
znamky.downloadZnamky(choice);
|
||||||
|
}else{
|
||||||
|
znamky.downloadZnamky();
|
||||||
|
}
|
||||||
|
|
||||||
|
setGUI();
|
||||||
|
|
||||||
|
hasStarted = true;
|
||||||
|
}catch(IOException e)
|
||||||
|
{
|
||||||
|
mainPanel.addComponent(new Label("An error has occured"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setGUI()
|
||||||
|
{
|
||||||
|
ArrayList<Predmet> predmety = znamky.getPredmety();
|
||||||
|
|
||||||
|
HashMap<Integer, SimpleTheme> barvy = new HashMap<>();
|
||||||
|
barvy.put(1, new SimpleTheme(ANSI.BLACK, VYBORNY));
|
||||||
|
barvy.put(2, new SimpleTheme(ANSI.BLACK, CHVALITEBNY));
|
||||||
|
barvy.put(3, new SimpleTheme(ANSI.BLACK, DOBRY));
|
||||||
|
barvy.put(4, new SimpleTheme(ANSI.BLACK, DOSTATECNY));
|
||||||
|
barvy.put(5, new SimpleTheme(ANSI.BLACK, NEDOSTATECNY));
|
||||||
|
barvy.put(-1, new SimpleTheme(ANSI.WHITE, NEHODNOCEN));
|
||||||
|
|
||||||
|
// Sloupec pro jmena predmetu
|
||||||
|
Panel jmemaPredmetu = new Panel()
|
||||||
|
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
||||||
|
.setLayoutData(ALIGN_LEFT)
|
||||||
|
.addTo(mainPanel);
|
||||||
|
|
||||||
|
// Sloupec pro znamky z predmetu
|
||||||
|
Panel znamky = new Panel()
|
||||||
|
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
||||||
|
.setLayoutData(ALIGN_LEFT)
|
||||||
|
.addTo(mainPanel);
|
||||||
|
|
||||||
|
// Sloupec pro vyslednou znamku
|
||||||
|
Panel vysledneZnamky = new Panel()
|
||||||
|
.setLayoutManager(new LinearLayout(Direction.VERTICAL))
|
||||||
|
.setLayoutData(ALIGN_RIGHT)
|
||||||
|
.addTo(mainPanel);
|
||||||
|
|
||||||
|
for(Predmet predmet : predmety)
|
||||||
|
{
|
||||||
|
Panel jednotliveZnamky = new Panel()
|
||||||
|
.setLayoutManager(new LinearLayout(Direction.HORIZONTAL))
|
||||||
|
.addTo(znamky);
|
||||||
|
|
||||||
|
if(predmet.getZnamky().isEmpty())
|
||||||
|
{
|
||||||
|
jednotliveZnamky.addComponent(new Label(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Znamka znamka : predmet.getZnamky())
|
||||||
|
{
|
||||||
|
Label znamkaLabel = new Label(znamka.getText());
|
||||||
|
znamkaLabel.setTheme(barvy.get(znamka.getZnamka()));
|
||||||
|
jednotliveZnamky.addComponent(znamkaLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
double prumer = predmet.getPrumer();
|
||||||
|
|
||||||
|
Label vysl = new Label(String.format("%.2f", prumer));
|
||||||
|
|
||||||
|
vysl.setTheme(barvy.get((int) Math.round(prumer)));
|
||||||
|
|
||||||
|
jmemaPredmetu.addComponent(new Label(predmet.getJmenoPredmetu()));
|
||||||
|
vysledneZnamky.addComponent(vysl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Panel getPanel()
|
||||||
|
{
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStarted()
|
||||||
|
{
|
||||||
|
return hasStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Label getLabel()
|
||||||
|
{
|
||||||
|
return borderLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showOptions(WindowBasedTextGUI textGUI) {
|
||||||
|
OptionsDialog d = new OptionsDialog(znamky.getOptions().getValue0(), znamky.getOptions().getValue1());
|
||||||
|
|
||||||
|
Choice c = d.showDialog(textGUI);
|
||||||
|
|
||||||
|
if(c != null)
|
||||||
|
{
|
||||||
|
download(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,80 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Dialogs;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.gui2.Button;
|
|
||||||
import com.googlecode.lanterna.gui2.Direction;
|
|
||||||
import com.googlecode.lanterna.gui2.GridLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
import com.googlecode.lanterna.gui2.Window;
|
|
||||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
|
||||||
import com.googlecode.lanterna.gui2.dialogs.DialogWindow;
|
|
||||||
|
|
||||||
import xyz.thastertyn.Login.LocalCredentials;
|
|
||||||
import xyz.thastertyn.Login.LoginController;
|
|
||||||
import xyz.thastertyn.UserInterface.Listeners.ContentResetListener;
|
|
||||||
|
|
||||||
public class EscapeDialog extends DialogWindow {
|
|
||||||
|
|
||||||
private WindowBasedTextGUI textGUI;
|
|
||||||
private ContentResetListener resetListener;
|
|
||||||
|
|
||||||
public EscapeDialog(WindowBasedTextGUI textGUI, ContentResetListener resetListener)
|
|
||||||
{
|
|
||||||
super("Escape Menu");
|
|
||||||
this.textGUI = textGUI;
|
|
||||||
this.resetListener = resetListener;
|
|
||||||
|
|
||||||
Panel mainPanel = new Panel()
|
|
||||||
.setLayoutManager(new GridLayout(1)
|
|
||||||
.setLeftMarginSize(1)
|
|
||||||
.setRightMarginSize(1));
|
|
||||||
|
|
||||||
new Panel()
|
|
||||||
.setLayoutManager(
|
|
||||||
new LinearLayout(Direction.VERTICAL))
|
|
||||||
.addComponent(new Button("Return", this::onReturn))
|
|
||||||
.addComponent(new Button("Logout", this::onLogout))
|
|
||||||
.addComponent(new Button("Delete stored login", this::onDeleteLogin))
|
|
||||||
.addComponent(new Button("Exit", this::onExit))
|
|
||||||
.addTo(mainPanel);
|
|
||||||
|
|
||||||
setHints(Arrays.asList(Window.Hint.CENTERED));
|
|
||||||
setComponent(mainPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onReturn()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDeleteLogin()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
LocalCredentials.getInstance().deleteCredentials();
|
|
||||||
LoginController controller = new LoginController(textGUI);
|
|
||||||
controller.loginUsingGui();
|
|
||||||
resetListener.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLogout()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
LoginController controller = new LoginController(textGUI);
|
|
||||||
controller.login(true);
|
|
||||||
resetListener.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onExit()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object showDialog(WindowBasedTextGUI textGUI) {
|
|
||||||
super.showDialog(textGUI);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package xyz.thastertyn.UserInterface.Dialogs;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.gui2.Button;
|
import com.googlecode.lanterna.gui2.Button;
|
||||||
import com.googlecode.lanterna.gui2.ComboBox;
|
import com.googlecode.lanterna.gui2.ComboBox;
|
||||||
@ -25,7 +25,7 @@ public class OptionsDialog extends DialogWindow {
|
|||||||
|
|
||||||
private boolean useData = false;
|
private boolean useData = false;
|
||||||
|
|
||||||
public OptionsDialog(Options[] options)
|
public OptionsDialog(Options... options)
|
||||||
{
|
{
|
||||||
super("Choose from below");
|
super("Choose from below");
|
||||||
|
|
||||||
@ -36,17 +36,6 @@ public class OptionsDialog extends DialogWindow {
|
|||||||
boxs.add(new ComboBox<Option>(o.getOptions()));
|
boxs.add(new ComboBox<Option>(o.getOptions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < options.length; i++)
|
|
||||||
{
|
|
||||||
for(int j = 0; j < options[i].getOptions().size(); j++)
|
|
||||||
{
|
|
||||||
if(options[i].getOptions().get(j).isDefault())
|
|
||||||
{
|
|
||||||
boxs.get(i).setSelectedIndex(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Panel mainPanel = new Panel()
|
Panel mainPanel = new Panel()
|
||||||
.setLayoutManager(new GridLayout(1)
|
.setLayoutManager(new GridLayout(1)
|
||||||
.setLeftMarginSize(1)
|
.setLeftMarginSize(1)
|
||||||
@ -102,13 +91,11 @@ public class OptionsDialog extends DialogWindow {
|
|||||||
super.showDialog(textGUI);
|
super.showDialog(textGUI);
|
||||||
|
|
||||||
return (useData) ?
|
return (useData) ?
|
||||||
// User pressed Ok
|
new Choice( // User pressed ok
|
||||||
new Choice(boxs.stream()
|
boxs.stream()
|
||||||
.map(box -> box.getSelectedItem().getValue())
|
.map(b -> b.getSelectedItem().toString())
|
||||||
.collect(Collectors.toList()))
|
.toArray(String[]::new))
|
||||||
// Why did .toList() stop working?
|
|
||||||
:
|
:
|
||||||
// User pressed Cancel
|
null; // User pressed Cancel
|
||||||
null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Listeners;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for when accounts have been switched and a complete wipe of content is needed
|
|
||||||
*/
|
|
||||||
public interface ContentResetListener {
|
|
||||||
public void reset();
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Listeners;
|
|
||||||
|
|
||||||
public interface UpdateListener {
|
|
||||||
/**
|
|
||||||
* Redraw the screen when panel changes due to Choice being used
|
|
||||||
*/
|
|
||||||
public void updatePanel();
|
|
||||||
}
|
|
@ -1,236 +0,0 @@
|
|||||||
package xyz.thastertyn.UserInterface.Listeners;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import com.googlecode.lanterna.TerminalPosition;
|
|
||||||
import com.googlecode.lanterna.TerminalSize;
|
|
||||||
import com.googlecode.lanterna.gui2.Borders;
|
|
||||||
import com.googlecode.lanterna.gui2.Direction;
|
|
||||||
import com.googlecode.lanterna.gui2.Label;
|
|
||||||
import com.googlecode.lanterna.gui2.LinearLayout;
|
|
||||||
import com.googlecode.lanterna.gui2.Panel;
|
|
||||||
import com.googlecode.lanterna.gui2.Window;
|
|
||||||
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
|
||||||
import com.googlecode.lanterna.gui2.WindowListener;
|
|
||||||
import com.googlecode.lanterna.gui2.dialogs.MessageDialog;
|
|
||||||
import com.googlecode.lanterna.gui2.dialogs.MessageDialogButton;
|
|
||||||
import com.googlecode.lanterna.input.KeyStroke;
|
|
||||||
import com.googlecode.lanterna.input.KeyType;
|
|
||||||
|
|
||||||
import xyz.thastertyn.UserInterface.Content.JecnaContent;
|
|
||||||
import xyz.thastertyn.UserInterface.Content.AbsenceList;
|
|
||||||
import xyz.thastertyn.UserInterface.Content.Timetable;
|
|
||||||
import xyz.thastertyn.UserInterface.Content.Reports;
|
|
||||||
import xyz.thastertyn.UserInterface.Content.Marks;
|
|
||||||
import xyz.thastertyn.UserInterface.Dialogs.EscapeDialog;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds all the content displayables and moves between them when needed on tab, or shift tab press
|
|
||||||
*/
|
|
||||||
// The biggest and greatest.
|
|
||||||
public class WindowSwitchListener implements WindowListener, UpdateListener, ContentResetListener {
|
|
||||||
private WindowBasedTextGUI textGUI;
|
|
||||||
|
|
||||||
private JecnaContent[] contents = {
|
|
||||||
new Timetable(this),
|
|
||||||
new Marks(this), // This being first doesn't resize properly for some reason
|
|
||||||
new Reports(this),
|
|
||||||
new AbsenceList(this)
|
|
||||||
};
|
|
||||||
|
|
||||||
private Label[] tabs = new Label[contents.length];
|
|
||||||
|
|
||||||
private Panel tabsPanel = new Panel()
|
|
||||||
.setLayoutManager(new LinearLayout(Direction.HORIZONTAL));
|
|
||||||
private Panel holderPanel = new Panel();
|
|
||||||
|
|
||||||
int current = contents.length - 1;
|
|
||||||
|
|
||||||
public WindowSwitchListener(Panel holder, WindowBasedTextGUI textGUI)
|
|
||||||
{
|
|
||||||
this.textGUI = textGUI;
|
|
||||||
holder.addComponent(tabsPanel);
|
|
||||||
holder.addComponent(holderPanel.withBorder(Borders.singleLine()));
|
|
||||||
|
|
||||||
for(int i = 0; i < contents.length; i++)
|
|
||||||
{
|
|
||||||
this.tabs[i] = contents[i].getLabel();
|
|
||||||
tabsPanel.addComponent(this.tabs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void next()
|
|
||||||
{
|
|
||||||
if(current + 1 == contents.length)
|
|
||||||
{
|
|
||||||
current = 0;
|
|
||||||
}else{
|
|
||||||
current++;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadPanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void previous()
|
|
||||||
{
|
|
||||||
if(current - 1 == -1)
|
|
||||||
{
|
|
||||||
current = contents.length - 1;
|
|
||||||
}else{
|
|
||||||
current--;
|
|
||||||
}
|
|
||||||
loadPanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadPanel()
|
|
||||||
{
|
|
||||||
checkIfDownloaded();
|
|
||||||
|
|
||||||
holderPanel.removeAllComponents();
|
|
||||||
tabsPanel.removeAllComponents();
|
|
||||||
|
|
||||||
setPanelPreferedSize();
|
|
||||||
updateLabels();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkIfDownloaded()
|
|
||||||
{
|
|
||||||
if(!contents[current].hasStarted())
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
contents[current].downloadDefault();
|
|
||||||
}catch(IOException e)
|
|
||||||
{
|
|
||||||
MessageDialog.showMessageDialog(textGUI, "Something failed", e.getMessage(), MessageDialogButton.OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a panel is smaller than the bar with labels, make it at least the bar size
|
|
||||||
*/
|
|
||||||
private void setPanelPreferedSize()
|
|
||||||
{
|
|
||||||
contents[current].getPanel().setSize(contents[current].getPanel().calculatePreferredSize()); // Fix for reports not being big enough
|
|
||||||
|
|
||||||
int labelTabColumnSize = tabsPanel
|
|
||||||
.getSize()
|
|
||||||
.getColumns();
|
|
||||||
|
|
||||||
int currentPanelColumnSize = contents[current]
|
|
||||||
.getPanel()
|
|
||||||
.getSize()
|
|
||||||
.getColumns();
|
|
||||||
|
|
||||||
if(currentPanelColumnSize < labelTabColumnSize)
|
|
||||||
{
|
|
||||||
int currentPanelRowSize = contents[current].getPanel().getPreferredSize().getRows();
|
|
||||||
holderPanel.addComponent(
|
|
||||||
contents[current]
|
|
||||||
.getPanel()
|
|
||||||
.setPreferredSize(new TerminalSize(
|
|
||||||
labelTabColumnSize,
|
|
||||||
currentPanelRowSize))); // Pretty janky, but basically just create a new TerminalSize with height the same and the width of label bar
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
holderPanel.addComponent(contents[current].getPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all labels again and properly sets their borders to single or double depending on {@link #current}
|
|
||||||
*/
|
|
||||||
private void updateLabels()
|
|
||||||
{
|
|
||||||
for(int i = 0; i < tabs.length; i++)
|
|
||||||
{
|
|
||||||
if(i == current)
|
|
||||||
{
|
|
||||||
tabsPanel.addComponent(tabs[i].withBorder(Borders.doubleLine()));
|
|
||||||
}else{
|
|
||||||
tabsPanel.addComponent(tabs[i].withBorder(Borders.singleLine()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the {@link #current}'s showOptions with a textGui
|
|
||||||
*/
|
|
||||||
private void showOptions()
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
contents[current].showOptions(textGUI);
|
|
||||||
}catch(IOException e)
|
|
||||||
{
|
|
||||||
MessageDialog.showMessageDialog(textGUI, "Something failed", "An error with connection has occured, either no connection at all, or connection timed out", MessageDialogButton.OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInput(Window basePane, KeyStroke keyStroke, AtomicBoolean deliverEvent) {
|
|
||||||
KeyType type = keyStroke.getKeyType();
|
|
||||||
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case Tab:
|
|
||||||
next();
|
|
||||||
break;
|
|
||||||
case ReverseTab: // Shift + Tab
|
|
||||||
previous();
|
|
||||||
break;
|
|
||||||
case Character:
|
|
||||||
if(keyStroke.getCharacter() == ' ')
|
|
||||||
{
|
|
||||||
showOptions();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Escape:
|
|
||||||
EscapeDialog dialog = new EscapeDialog(textGUI, this);
|
|
||||||
dialog.showDialog(textGUI);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUnhandledInput(Window basePane, KeyStroke keyStroke, AtomicBoolean hasBeenHandled) {
|
|
||||||
hasBeenHandled.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResized(Window window, TerminalSize oldSize, TerminalSize newSize) {
|
|
||||||
window.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMoved(Window window, TerminalPosition oldPosition, TerminalPosition newPosition) {
|
|
||||||
window.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePanel() {
|
|
||||||
holderPanel.removeAllComponents();
|
|
||||||
setPanelPreferedSize();
|
|
||||||
holderPanel.addComponent(contents[current].getPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On user change should wipe everything
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
contents = new JecnaContent[] {
|
|
||||||
new Timetable(this),
|
|
||||||
new Marks(this),
|
|
||||||
new Reports(this),
|
|
||||||
new AbsenceList(this)
|
|
||||||
};
|
|
||||||
loadPanel();
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
|
|||||||
import com.googlecode.lanterna.terminal.Terminal;
|
import com.googlecode.lanterna.terminal.Terminal;
|
||||||
|
|
||||||
import xyz.thastertyn.Login.LoginController;
|
import xyz.thastertyn.Login.LoginController;
|
||||||
import xyz.thastertyn.UserInterface.Listeners.WindowSwitchListener;
|
|
||||||
|
|
||||||
public class MainWindow {
|
public class MainWindow {
|
||||||
|
|
||||||
@ -28,14 +27,7 @@ public class MainWindow {
|
|||||||
private Window window;
|
private Window window;
|
||||||
private MultiWindowTextGUI textGUI;
|
private MultiWindowTextGUI textGUI;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create:
|
|
||||||
* <ul>
|
|
||||||
* <li> All the main components like Terminal, and Screen </li>
|
|
||||||
* <li> {@link LoginController} and try logging in using any of its methods </li>
|
|
||||||
* <li> {@link WindowSwitchListener} for the purpose of switching between tabs using {@code Tab} and {@code ReverseTab} (Shift + Tab) </li>
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -54,25 +46,25 @@ public class MainWindow {
|
|||||||
textGUI = new MultiWindowTextGUI(screen, new DefaultWindowManager(), new EmptySpace(TextColor.ANSI.BLACK_BRIGHT));
|
textGUI = new MultiWindowTextGUI(screen, new DefaultWindowManager(), new EmptySpace(TextColor.ANSI.BLACK_BRIGHT));
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
// Create panel to hold all components
|
// Create panel to hold components
|
||||||
final Panel mainPanel = new Panel();
|
final Panel mainPanel = new Panel();
|
||||||
mainPanel.setLayoutManager(new LinearLayout(Direction.VERTICAL));
|
mainPanel.setLayoutManager(new LinearLayout(Direction.VERTICAL));
|
||||||
|
|
||||||
window.setComponent(mainPanel);
|
window.setComponent(mainPanel);
|
||||||
|
|
||||||
// Create a secondary panel, as working with the mainPanel is quite buggy
|
String title = "Jecnak";
|
||||||
|
|
||||||
Panel content = new Panel();
|
Panel content = new Panel();
|
||||||
mainPanel.addComponent(content.withBorder(Borders.singleLine("Jecnak")));
|
mainPanel.addComponent(content.withBorder(Borders.singleLine(title)));
|
||||||
|
|
||||||
// Try logging in using any method
|
|
||||||
LoginController controller = new LoginController(textGUI);
|
LoginController controller = new LoginController(textGUI);
|
||||||
controller.login(false);
|
controller.login();
|
||||||
|
|
||||||
// Create a WindowListener for tab and shift tab for moving between tabs
|
window.addWindowListener(new WindowSwitchListener(content, title, textGUI));
|
||||||
window.addWindowListener(new WindowSwitchListener(content, textGUI));
|
|
||||||
|
|
||||||
textGUI.addWindowAndWait(window);
|
textGUI.addWindowAndWait(window);
|
||||||
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
package xyz.thastertyn.UserInterface;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.TerminalPosition;
|
||||||
|
import com.googlecode.lanterna.TerminalSize;
|
||||||
|
import com.googlecode.lanterna.gui2.Borders;
|
||||||
|
import com.googlecode.lanterna.gui2.Direction;
|
||||||
|
import com.googlecode.lanterna.gui2.Label;
|
||||||
|
import com.googlecode.lanterna.gui2.LinearLayout;
|
||||||
|
import com.googlecode.lanterna.gui2.Panel;
|
||||||
|
import com.googlecode.lanterna.gui2.Window;
|
||||||
|
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
|
||||||
|
import com.googlecode.lanterna.gui2.WindowListener;
|
||||||
|
import com.googlecode.lanterna.gui2.dialogs.MessageDialog;
|
||||||
|
import com.googlecode.lanterna.gui2.dialogs.MessageDialogButton;
|
||||||
|
import com.googlecode.lanterna.input.KeyStroke;
|
||||||
|
import com.googlecode.lanterna.input.KeyType;
|
||||||
|
|
||||||
|
import xyz.thastertyn.UserInterface.Content.JecnaContent;
|
||||||
|
import xyz.thastertyn.UserInterface.Content.OmluvnyList;
|
||||||
|
import xyz.thastertyn.UserInterface.Content.Rozvrh;
|
||||||
|
import xyz.thastertyn.UserInterface.Content.Sdeleni;
|
||||||
|
import xyz.thastertyn.UserInterface.Content.Znamky;
|
||||||
|
|
||||||
|
public class WindowSwitchListener implements WindowListener {
|
||||||
|
|
||||||
|
private WindowBasedTextGUI textGUI;
|
||||||
|
|
||||||
|
private JecnaContent[] contents = {
|
||||||
|
new Rozvrh(),
|
||||||
|
new Znamky(),
|
||||||
|
new Sdeleni(),
|
||||||
|
new OmluvnyList()
|
||||||
|
};
|
||||||
|
|
||||||
|
private Label[] tabs = new Label[contents.length];
|
||||||
|
|
||||||
|
private Panel tabsPanel = new Panel().setLayoutManager(new LinearLayout(Direction.HORIZONTAL));
|
||||||
|
private Panel holderPanel = new Panel();
|
||||||
|
|
||||||
|
private Panel errorPanel = new Panel().addComponent(new Label("Something went wrong"));
|
||||||
|
|
||||||
|
int current = contents.length - 1;
|
||||||
|
|
||||||
|
public WindowSwitchListener(Panel holder, String title, WindowBasedTextGUI textGUI)
|
||||||
|
{
|
||||||
|
this.textGUI = textGUI;
|
||||||
|
holder.addComponent(tabsPanel);
|
||||||
|
holder.addComponent(holderPanel.withBorder(Borders.singleLine()));
|
||||||
|
|
||||||
|
for(int i = 0; i < contents.length; i++)
|
||||||
|
{
|
||||||
|
this.tabs[i] = contents[i].getLabel();
|
||||||
|
tabsPanel.addComponent(this.tabs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void next()
|
||||||
|
{
|
||||||
|
if(current + 1 == contents.length)
|
||||||
|
{
|
||||||
|
current = 0;
|
||||||
|
}else{
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!contents[current].hasStarted())
|
||||||
|
{
|
||||||
|
contents[current].downloadDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
holderPanel.removeAllComponents();
|
||||||
|
tabsPanel.removeAllComponents();
|
||||||
|
|
||||||
|
if(contents[current].hasStarted())
|
||||||
|
{
|
||||||
|
int tabColumns = tabsPanel.getSize().getColumns();
|
||||||
|
|
||||||
|
if(contents[current].getPanel().getSize().getColumns() < tabColumns)
|
||||||
|
{
|
||||||
|
holderPanel.addComponent(
|
||||||
|
contents[current].getPanel().setPreferredSize(new TerminalSize(tabColumns,
|
||||||
|
contents[current].getPanel().getPreferredSize().getRows())));
|
||||||
|
|
||||||
|
}else{
|
||||||
|
holderPanel.addComponent(contents[current].getPanel());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
holderPanel.addComponent(errorPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < tabs.length; i++)
|
||||||
|
{
|
||||||
|
if(i == current)
|
||||||
|
{
|
||||||
|
tabsPanel.addComponent(tabs[i].withBorder(Borders.doubleLine()));
|
||||||
|
}else{
|
||||||
|
tabsPanel.addComponent(tabs[i].withBorder(Borders.singleLine()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInput(Window basePane, KeyStroke keyStroke, AtomicBoolean deliverEvent) {
|
||||||
|
KeyType type = keyStroke.getKeyType();
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case Tab:
|
||||||
|
next();
|
||||||
|
break;
|
||||||
|
case Character:
|
||||||
|
if(keyStroke.getCharacter() == ' ')
|
||||||
|
{
|
||||||
|
contents[current].showOptions(textGUI);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Escape:
|
||||||
|
MessageDialog.showMessageDialog(textGUI, "Options", "Loging out and some other stuff soon", MessageDialogButton.OK);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnhandledInput(Window basePane, KeyStroke keyStroke, AtomicBoolean hasBeenHandled) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResized(Window window, TerminalSize oldSize, TerminalSize newSize) {
|
||||||
|
window.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoved(Window window, TerminalPosition oldPosition, TerminalPosition newPosition) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,9 @@
|
|||||||
package xyz.thastertyn;
|
package xyz.thastertyn;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import xyz.thastertyn.Types.FinalMark;
|
|
||||||
import xyz.thastertyn.Types.Mark;
|
|
||||||
import xyz.thastertyn.Types.Subject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for simple App.
|
* Unit test for simple App.
|
||||||
*/
|
*/
|
||||||
@ -24,50 +19,21 @@ public class AppTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noMarksPresentTest()
|
public void hasJavaAbove11()
|
||||||
{
|
{
|
||||||
// No marks are present on start
|
// https://stackoverflow.com/questions/2591083/getting-java-version-at-runtime#2591122
|
||||||
Subject subject = new Subject("Test Subject");
|
String version = System.getProperty("java.version");
|
||||||
|
int v;
|
||||||
|
|
||||||
assertTrue(subject.getMarks().isEmpty());
|
if(version.startsWith("1."))
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void correctAverage()
|
|
||||||
{
|
{
|
||||||
Subject subject = new Subject("Test");
|
version = version.substring(2, 3);
|
||||||
|
}else {
|
||||||
// Average is calculated properly
|
int dot = version.indexOf(".");
|
||||||
subject.addMark(new Mark(1, false, "1"));
|
if(dot != -1) { version = version.substring(0, dot); }
|
||||||
subject.addMark(new Mark(3, false, "3"));
|
|
||||||
|
|
||||||
assertTrue(subject.getFinalMark().getValue() == 2.0);
|
|
||||||
}
|
}
|
||||||
|
v = Integer.parseInt(version);
|
||||||
|
|
||||||
@Test
|
assertTrue("Java >= 11 is required", (v >= 11));
|
||||||
public void correctSmallMarkAverage()
|
|
||||||
{
|
|
||||||
// Small marks are calculated properly
|
|
||||||
Subject subject = new Subject("Test");
|
|
||||||
|
|
||||||
subject.addMark(new Mark(1, false, "1"));
|
|
||||||
subject.addMark(new Mark(3, false, "3"));
|
|
||||||
subject.addMark(new Mark(5, true, "5"));
|
|
||||||
subject.addMark(new Mark(5, true, "5"));
|
|
||||||
|
|
||||||
assertTrue(subject.getFinalMark().getValue() == 3.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void marksDontChangeFinalMark()
|
|
||||||
{
|
|
||||||
// Once a final mark is given, no additional marks should change it
|
|
||||||
Subject subject = new Subject("Test", FinalMark.NEDOSTATECNY);
|
|
||||||
subject.addMark(new Mark(1, false, "a"));
|
|
||||||
subject.addMark(new Mark(1, false, "a"));
|
|
||||||
subject.addMark(new Mark(1, false, "a"));
|
|
||||||
subject.addMark(new Mark(1, false, "a"));
|
|
||||||
|
|
||||||
assertEquals(FinalMark.NEDOSTATECNY, subject.getFinalMark());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user