What hackathon did we participate
We participated in this hackathon called the OpenHack. It was our first hackathon and a hackathon of over 700 participants. It was certainly a fun experience, and we went on attending over seven other hackathon events. This Hackathon was generally well organized - it had a dozen admins organizing the chat and the event. This also gave us inspiration on whether we want to host our own online hackathon.
Why Java?
There were mainly two reasons behind why we wanted to use Java at this hackathon:
- Our school's design class required us to make a Java application, and so we decided to just carry on with the language.
- We also wanted to use this chance to practice Java since we wanted to take the AP CS exam.
What is the software
Our project was composed of two things:
- An advanced group generator that generates groups based on discriminators such as nationality, gender, hobby and more.
In a typical group generator, the only decider for the groups is randomness. However, in an international school, randomness sometimes isn't the ideal decider for group activities, assignments, and school tasks. Our group generator can let the teacher decide, for instance, whether to mix up all the people by nationality or to mix up all the people who agree and disagree with a topic.
- An online education facilitator that generates google meet links or zoom links along with the groups.
Secondly, we noticed during the Covid-19 pandemic that our secondary teachers needed a better way of creating and sharing Google Meet links with their students. For instance, many times, they wanted to schedule a Google Meet in advance, but the links expired, and they were not able to do this. Other times, they simply wanted to create breakout Meets but had to ask one of the students to create meet links for them. However, our software combines this with group generation, by automatically embedding google meet/zoom links inside emails sent to each of the groups. This makes group work and activities easier for online learning, hence improving and creating new ways in which teachers can structure their online classes.
How we made it
Our software can be separated into two parts that are parallel to the two main functions of the group generator: the group generating algorithm and google meet/zoom link extraction.
Group generating algorithm:
It was a straightforward fact that we were dealing with the properties of each student, which means we would first create a student class and organize the students into objects.
package sample;
public class Student {
private String name;
private String nationality;
private String homeRoom;
private String gender;
private String email;
public Student(String name, String gender, String nationality, String homeRoom, String email){
this.name = name;
this.email = email;
this.nationality = nationality;
this.homeRoom = homeRoom;
this.gender = gender;
}
public String getName() {
return name;
}
public String getEmail(){
return email;
}
public void setName(String name) {
this.name = name;
}
public String getNationality() {
return nationality;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
public String getHomeRoom() {
return homeRoom;
}
public void setHomeRoom(String homeRoom) {
this.homeRoom = homeRoom;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", nationality='" + nationality + '\'' +
", homeRoom='" + homeRoom + '\'' +
", gender='" + gender + '\'' +
'}';
}
}
The next goal was to evenly distribute the students based on two user inputs: number of groups and the discriminator the grouping process would be based on. To execute this grouping method in a very organized and structured manner, we decided to format it with
List<List<Student>>
. Using the List Interface, we wrapped the student objects with a list, representing each group, and we wrapped that with another list, representing all the groups.
List<>
is a single group;
List<List<Student>>
is a group of groups.
Then, we created a function that sorts the groups. In our sorting class, as we were reading the student’s information from a CSV file, we set up a constructor that syncs the file path to a local variable. After that, we implemented the method of distributing the groups - this method was suggested by an answer to my StackOverflow post, a very succinct and effective method. Below is a snippet of our function:
public List> sort(String type, int groupNum) {
this.groupNum = groupNum;
ReadFile p = new ReadFile(filePath);
List people = new ArrayList<>();
for (int i = 1; i < new ReadFile(filePath).readLine(); i ++) {
people.add(
new Student(
p.read(i, 0),
p.read(i, 1),
p.read(i, 2),
p.read(i, 3),
p.read(i, 4)
)
//(name, gender, nationality, homeroom, email)
);
}
Collections.shuffle(people);//randomize the list of people
Function discriminator;
//check the type of sorting the user wants
switch(type) {
case "homeroom":
discriminator = Student::getHomeRoom;
break;
case "gender":
discriminator = Student::getGender;
break;
case "nationality":
discriminator = Student::getNationality;
break;
case "random":
discriminator = Student::getName;
break;
default:
discriminator = Student::getName;
System.out.println("ERROR");
}
AtomicInteger index = new AtomicInteger();
List> groups = new ArrayList<>(people.stream()
.sorted(Comparator.comparing(discriminator))
.collect(Collectors.groupingBy(e -> index.getAndIncrement() % groupNum))
.values());
return groups;//returns List>
}
This was especially novel to us due to its usage of AtomicIntegers and a unique sorting method. Even though I don't fully understand how to manipulate these elements, using some high-level Java techniques does make it very efficient.
Link Extraction:
For the second part of our code, our goal was to make the code to extract Google Meet and Zoom links automatically. We decided to use Selenium. At first, we thought Selenium was a very esoteric thing that was extremely hard to use. However, it is pretty straightforward.
First of all, we downloaded a Chrome driver and pointed it in our code.
public void setBrowserConfigure(){
System.setProperty("webdriver.chrome.driver", driverr);
}
We created separate functions for Zoom and Google Meet. Below is the code for Google Meet:
public String[] generateGoogleMeetLinks(int numLinks){
//System.setProperty("webdriver.chrome.driver", driverr);//put your driver exe here
final String baseUrl = "https://meet.google.com/new";
ChromeOptions options = new ChromeOptions();
WebDriver driver = new ChromeDriver(options);
// driver.manage().window().setPosition(new Point(-2000, 0));//put it to the left
meetLinksList = new String[numLinks];
for(int i = 0; i < numLinks; i++){
try {
driver.get(baseUrl);
if(i == 0) { //for the first link, we need to log into google
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@id='identifierId']"))).sendKeys(teacherAddress);
driver.findElement(By.id("identifierNext")).click();
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@name='password']"))).sendKeys(teacherPassword);
driver.findElement(By.id("passwordNext")).click();
}
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"yDmH0d\"]/div[3]/div/div[2]/span")));
driver.findElement(By.xpath("//*[@id=\"yDmH0d\"]/div[3]/div/div[2]/span")).click();//clicking in the middle of the page
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"yDmH0d\"]/div[3]/div/div[2]/div[3]/div/span/span")));
driver.findElement(By.xpath("//*[@id=\"yDmH0d\"]/div[3]/div/div[2]/div[3]/div/span/span")).click();//clicks dismiss
//new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body")));
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"yDmH0d\"]/c-wiz/div/div/div[4]/div[3]/div/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div/div[1]")));
link = driver.findElement(By.xpath("//*[@id=\"yDmH0d\"]/c-wiz/div/div/div[4]/div[3]/div/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div/div[1]")).getText();
meetLinksList[i] = link;//filling the list
}catch(InterruptedException e){
e.printStackTrace();
}catch(TimeoutException e){
System.out.println("Time out!");
e.printStackTrace();
}
}
driver.close();
return meetLinksList;
}
In the code, we have a for-loop, which generates meet links for the number of the group the user requested.
Then, to be able to deal with the browser, as to extract specific elements from the web page, we had to utilize two Selenium elements:
WebDriverWait()
and
findElement()
.
WebDriverWait()
waits until the requested element is loaded through calling another function called
until()
right behind it.
findElement()
finds elements - in our code we used XPath, but there are a number of other options to specify the elements on the website. For this specific process, it logs into the Google account, directs to the Google Meet page, and finally copies the meet link. The link then goes through our Email functions and gets sent off to the groups. This took us a long time to calibrate.
Check out our competition page
here.
Challenges
- Frontend
Using JavaFX to create the frontend was highly tedious. We spent 540 lines of compact Java codes for a simple layout. If you see the pictures below, our layout looks similar to software from the last century - it doesn't look good! This was both due to time constraints(the algorithm and selenium took us the whole day) and the lack of frontend support from Javafx. This is because no one uses JavaFX to create a desktop application. Java shouldn't be used for any frontend development.
- "headless" webdriver
Every time the software extracts links from the web, it automatically opens up the driver, which is just like a normal browser. We wanted the window to be "headless,” which simply means not showing. However, after multiple trials, it just didn't work!
- Deployment
This is probably the most annoying challenge I have ever faced. If we produce a piece of software, the aim is for other people to test it and use it. However, Oracle decided to remove the packaging ability for Java application. If we don't use add-ons like Gradle or Maven(these are super complicated), or to use an older JDK, we can't deploy the software. Even if we use JDK 8, deployment is still a pain. And, with an extra dependency of Webdriver from Selenium, deployment was simply impossible. We probably spent over 15 hours researching for the solution of this single problem.
- Collaboration
We were deciding over whether to use GitHub or a real-time collaboration tool for this project. For this project, we went on and used Floobits - a real-time collaboration add-on to Intellij Idea(the IDE we used). I’d say this was effective since we were participating in a Hackathon, and we needed “real-time” collaboration. However, outside of hackathons, we should stick with Git as it is just a better version control system and allows us to keep track of our codes more efficiently. It is also what professional programmers do.
How to use it
- Choose the classroom csv/excel file that you would like the groups to be from(you can also choose past groups). Then, type the desired number of groups.
- Select the group customization.
- Type the your google account or your zoom account. Then, select whether you would like to generate zoom or google meet links - you can also choose not to generate links.
- Type any announcement you would like to be sent along with the links to each individual groups
- Click Generate.
Check out our source code here