diff --git a/.github/workflows/build-gradle.yml b/.github/workflows/build-gradle.yml
new file mode 100644
index 0000000..06bfe16
--- /dev/null
+++ b/.github/workflows/build-gradle.yml
@@ -0,0 +1,18 @@
+name: Build with Gradle and run
+on: [push, workflow_dispatch]
+
+jobs:
+ build_with_gradle:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Get Repo
+ uses: actions/checkout@v4.1.5
+ - name: Setup Java
+ uses: actions/setup-java@v4.2.1
+ with:
+ java-version: 21
+ distribution: 'temurin'
+ - name: Build Project with Gradle
+ run: gradle clean build
+ - name: Run Application
+ run: java -jar build/libs/java-trainee-edu-1.0-SNAPSHOT.jar
diff --git a/.github/workflows/build-maven.yml b/.github/workflows/build-maven.yml
new file mode 100644
index 0000000..73d92f2
--- /dev/null
+++ b/.github/workflows/build-maven.yml
@@ -0,0 +1,19 @@
+name: Build with Maven and run
+on: [push, workflow_dispatch]
+
+jobs:
+ build_with_maven:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Get Repo
+ uses: actions/checkout@v4.1.5
+ - name: Setup Java
+ uses: actions/setup-java@v4.2.1
+ with:
+ java-version: 21
+ distribution: 'temurin'
+ cache: 'maven'
+ - name: Build Project with Maven
+ run: mvn clean package
+ - name: Run Application
+ run: java -jar java-trainee-edu/target/java-trainee-edu-1.0-SNAPSHOT.jar
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..7eba534
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,35 @@
+plugins {
+ id 'java'
+ id 'application'
+}
+
+group 'com.rtemi'
+version '1.0-SNAPSHOT'
+
+java{
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(21)
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'com.fasterxml.jackson.core:jackson-core:2.17.1'
+ implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1'
+}
+
+application {
+ mainClassName = 'com.rtemi.services.CustomDataStructures'
+}
+
+jar {
+ manifest {
+ attributes(
+ 'Main-Class': 'com.rtemi.services.CustomDataStructures'
+ )
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 0ab8a7a..899653e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
com.rtemi
- trainee-edu-hw2
+ java-trainee-edu
1.0-SNAPSHOT
@@ -13,6 +13,34 @@
21
UTF-8
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.2.0
+
+
+
+ true
+ com.rtemi.services.CustomDataStructures
+
+
+
+
+
+
+
com.fasterxml.jackson.core
diff --git a/screenshot/Screenshot_4.png b/screenshot/Screenshot_4.png
deleted file mode 100644
index ab8a1f1..0000000
Binary files a/screenshot/Screenshot_4.png and /dev/null differ
diff --git a/screenshot/busticketvalidator.png b/screenshot/busticketvalidator.png
deleted file mode 100644
index a113e91..0000000
Binary files a/screenshot/busticketvalidator.png and /dev/null differ
diff --git a/src/main/java/com/rtemi/model/ConcertTicket.java b/src/main/java/com/rtemi/model/ConcertTicket.java
index 42b92f5..03bf02a 100644
--- a/src/main/java/com/rtemi/model/ConcertTicket.java
+++ b/src/main/java/com/rtemi/model/ConcertTicket.java
@@ -18,7 +18,7 @@ public class ConcertTicket extends TicketUID implements Printable, Shareable {
private static final int WEIGHT_PRECISION = 3;
private String concertTicketId;
- @NullableWarning(key = "Variable [concertHall] is null in [Ticket]!”")
+ @NullableWarning(key = "Variable [concertHall] is null in [Ticket]!")
private String concertHall;
private int eventCode;
private long ticketPurchaseTime;
@@ -88,8 +88,7 @@ public String toString() {
", isPromo - " + isPromo +
", sector - " + sector +
", maxWeight - " + maxWeight.setScale(WEIGHT_PRECISION,RoundingMode.HALF_UP) +
- ", ticketPrice - " + ticketPrice.setScale(PRICE_PRECISION,RoundingMode.HALF_UP) +
- '}';
+ ", ticketPrice - " + ticketPrice.setScale(PRICE_PRECISION,RoundingMode.HALF_UP);
}
@Override
diff --git a/src/main/java/com/rtemi/model/CustomArrayList.java b/src/main/java/com/rtemi/model/CustomArrayList.java
new file mode 100644
index 0000000..11d6e3c
--- /dev/null
+++ b/src/main/java/com/rtemi/model/CustomArrayList.java
@@ -0,0 +1,77 @@
+package com.rtemi.model;
+import java.util.Arrays;
+import java.util.Arrays;
+
+/**
+ * Custom implementation of an ArrayList.
+ */
+public class CustomArrayList {
+ private static final int DEFAULT_CAPACITY = 10;
+ private Object[] elements;
+ private int size = 0;
+
+ public CustomArrayList() {
+ elements = new Object[DEFAULT_CAPACITY];
+ }
+
+ /**
+ * Adds an element to the list.
+ * @param element The element to add.
+ */
+ public void put(T element) {
+ if (size == elements.length) {
+ resize();
+ }
+ elements[size++] = element;
+ }
+
+ /**
+ * Gets an element by its index.
+ * @param index The index of the element.
+ * @return The element at the specified index.
+ * @throws IndexOutOfBoundsException if the index is out of range.
+ */
+ @SuppressWarnings("unchecked")
+ public T get(int index) {
+ if (index >= size || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ return (T) elements[index];
+ }
+
+ /**
+ * Removes an element by its index.
+ * @param index The index of the element to remove.
+ * @return The removed element.
+ * @throws IndexOutOfBoundsException if the index is out of range.
+ */
+ @SuppressWarnings("unchecked")
+ public T delete(int index) {
+ if (index >= size || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ T element = (T) elements[index];
+ int numMoved = size - index - 1;
+ if (numMoved > 0) {
+ System.arraycopy(elements, index + 1, elements, index, numMoved);
+ }
+ elements[--size] = null; // clear to let GC do its work
+ return element;
+ }
+
+ /**
+ * Returns the size of the list.
+ * @return The size of the list.
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Resizes the internal array to accommodate more elements.
+ */
+ private void resize() {
+ int newSize = elements.length * 2;
+ elements = Arrays.copyOf(elements, newSize);
+ }
+}
diff --git a/src/main/java/com/rtemi/model/CustomHashSet.java b/src/main/java/com/rtemi/model/CustomHashSet.java
new file mode 100644
index 0000000..d5f61cc
--- /dev/null
+++ b/src/main/java/com/rtemi/model/CustomHashSet.java
@@ -0,0 +1,121 @@
+package com.rtemi.model;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * Custom implementation of a HashSet.
+ */
+public class CustomHashSet implements Iterable {
+ private static final int DEFAULT_CAPACITY = 16;
+ private static final float LOAD_FACTOR = 0.75f;
+ private LinkedList[] buckets;
+ private int size = 0;
+
+ public CustomHashSet() {
+ buckets = new LinkedList[DEFAULT_CAPACITY];
+ }
+
+ /**
+ * Adds an element to the set.
+ * @param element The element to add.
+ */
+ public void put(T element) {
+ if (contains(element)) {
+ return;
+ }
+ if (size + 1 > LOAD_FACTOR * buckets.length) {
+ resize();
+ }
+ int index = getIndex(element);
+ if (buckets[index] == null) {
+ buckets[index] = new LinkedList<>();
+ }
+ buckets[index].add(element);
+ size++;
+ }
+
+ /**
+ * Checks if the set contains the specified element.
+ * @param element The element to check.
+ * @return True if the set contains the element, false otherwise.
+ */
+ public boolean contains(T element) {
+ int index = getIndex(element);
+ LinkedList bucket = buckets[index];
+ return bucket != null && bucket.contains(element);
+ }
+
+ /**
+ * Removes an element from the set.
+ * @param element The element to remove.
+ * @return True if the element was removed, false otherwise.
+ */
+ public boolean remove(T element) {
+ int index = getIndex(element);
+ LinkedList bucket = buckets[index];
+ if (bucket != null && bucket.remove(element)) {
+ size--;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the size of the set.
+ * @return The size of the set.
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns an iterator over the elements in the set.
+ * @return An iterator.
+ */
+ @Override
+ public Iterator iterator() {
+ return new Iterator() {
+ private int bucketIndex = 0;
+ private Iterator bucketIterator = buckets[bucketIndex] == null ? null : buckets[bucketIndex].iterator();
+
+ @Override
+ public boolean hasNext() {
+ while ((bucketIterator == null || !bucketIterator.hasNext()) && bucketIndex < buckets.length - 1) {
+ bucketIndex++;
+ bucketIterator = buckets[bucketIndex] == null ? null : buckets[bucketIndex].iterator();
+ }
+ return bucketIterator != null && bucketIterator.hasNext();
+ }
+
+ @Override
+ public T next() {
+ return bucketIterator.next();
+ }
+ };
+ }
+
+ /**
+ * Gets the index of the bucket for the specified element.
+ * @param element The element.
+ * @return The index of the bucket.
+ */
+ private int getIndex(T element) {
+ return element == null ? 0 : Math.abs(element.hashCode() % buckets.length);
+ }
+
+ /**
+ * Resizes the internal array to accommodate more elements.
+ */
+ private void resize() {
+ LinkedList[] oldBuckets = buckets;
+ buckets = new LinkedList[oldBuckets.length * 2];
+ size = 0;
+ for (LinkedList bucket : oldBuckets) {
+ if (bucket != null) {
+ for (T element : bucket) {
+ put(element);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/rtemi/services/BusTicketService.java b/src/main/java/com/rtemi/services/BusTicketService.java
new file mode 100644
index 0000000..18a8a05
--- /dev/null
+++ b/src/main/java/com/rtemi/services/BusTicketService.java
@@ -0,0 +1,91 @@
+package com.rtemi.services;
+
+import com.rtemi.interfaces.Printable;
+import com.rtemi.model.BusTicket;
+import com.rtemi.model.TicketUID;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * Service class to manage bus tickets.
+ * Provides functionalities to create, store, remove, and search bus tickets.
+ */
+public class BusTicketService extends TicketUID implements Printable {
+ private static List ticketList = new ArrayList<>();
+ private static AtomicInteger idCounter = new AtomicInteger();
+ /**
+ * Creates a new bus ticket and stores it in memory.
+ * @param ticketClass The class of the ticket (e.g., Standard, VIP, Super).
+ * @param ticketType The type of the ticket (e.g., Month, Year, Daily).
+ * @param startDate The start date of the ticket.
+ * @param price The price of the ticket.
+ * @return The created BusTicket.
+ */
+ public BusTicket createBusTicket(String ticketClass, String ticketType, String startDate, BigDecimal price) {
+ BusTicket ticket = new BusTicket(startDate, ticketType, ticketClass, price);
+ ticket.setTicketUid(idCounter.incrementAndGet());
+ ticketList.add(ticket);
+ return ticket;
+ }
+
+ public boolean removeBusTicketById(int ticketUID) {
+ return ticketList.removeIf(ticket -> ticket.getTicketUid() == ticketUID);
+ }
+
+ public BusTicket getTicketById(int ticketUID) {
+ Optional ticket = ticketList.stream()
+ .filter(t -> t.getTicketUid() == ticketUID)
+ .findFirst();
+ return ticket.orElse(null);
+ }
+ /**
+ * Searches for bus tickets by type and price range.
+ * @param ticketType The type of the ticket.
+ * @param minPrice The minimum price.
+ * @param maxPrice The maximum price.
+ * @return A list of matching BusTickets.
+ */
+ public static List searchTicketsByTypeAndPrice(String ticketType, BigDecimal minPrice, BigDecimal maxPrice) {
+ return ticketList.stream()
+ .filter(ticket -> ticket.getTicketType().equalsIgnoreCase(ticketType)
+ && ticket.getPrice().compareTo(minPrice) >= 0
+ && ticket.getPrice().compareTo(maxPrice) <= 0)
+ .collect(Collectors.toList());
+ }
+
+ public static void main(String[] args) {
+ BusTicketService service = new BusTicketService();
+
+ System.out.println(service.createBusTicket("STD", "MONTH", "2024-06-27", BigDecimal.valueOf(100)));
+ System.out.println(service.createBusTicket("SUP", "YEAR", "2024-06-28", BigDecimal.valueOf(500)));
+ System.out.println(service.createBusTicket("VIP", "DAY", "2024-06-29", BigDecimal.valueOf(1000)));
+
+ for (int i = 0; i < ticketList.size(); i++) {
+ System.out.println(ticketList.get(i).getTicketUid() +" "+ ticketList.get(i) );
+ }
+
+ // Get and print a ticket by ID
+ BusTicket ticket = service.getTicketById(1);
+ if (ticket != null) {
+ ticket.toString();
+ }
+
+ // Search and print tickets by type and price range
+ List searchedTickets = service.searchTicketsByTypeAndPrice("Economy", new BigDecimal("10.00"), new BigDecimal("16.00"));
+ searchedTickets.forEach(ticket1 -> System.out.println(ticket1));
+
+ // Remove a ticket by ID
+ boolean removed = service.removeBusTicketById(1);
+ System.out.println("Ticket with ID 1 removed: " + removed);
+
+ for (int i = 0; i < ticketList.size(); i++) {
+ System.out.println(ticketList.get(i).getTicketUid() +" "+ ticketList.get(i) );
+ }
+ }
+
+}
diff --git a/src/main/java/com/rtemi/services/CustomDataStructures.java b/src/main/java/com/rtemi/services/CustomDataStructures.java
new file mode 100644
index 0000000..88c761f
--- /dev/null
+++ b/src/main/java/com/rtemi/services/CustomDataStructures.java
@@ -0,0 +1,32 @@
+package com.rtemi.services;
+
+import com.rtemi.model.CustomArrayList;
+import com.rtemi.model.CustomHashSet;
+
+public class CustomDataStructures {
+ public static void main(String[] args) {
+ CustomArrayList customArrayList = new CustomArrayList<>();
+ customArrayList.put(1);
+ customArrayList.put(2);
+ customArrayList.put(3);
+ System.out.println("ArrayList size: " + customArrayList.size());
+ System.out.println("Element at index 1: " + customArrayList.get(1));
+ customArrayList.delete(1);
+ System.out.println("Element at index 1 after removing: " + customArrayList.get(1));
+
+
+ CustomHashSet customHashSet = new CustomHashSet<>();
+ customHashSet.put("a");
+ customHashSet.put("b");
+ customHashSet.put("c");
+ System.out.println("HashSet size: " + customHashSet.size());
+ System.out.println("Contains 'a': " + customHashSet.contains("a"));
+ customHashSet.remove("a");
+ System.out.println("Contains 'a' after removal: " + customHashSet.contains("a"));
+
+ System.out.println("Iterating over CustomHashSet:");
+ for (String s : customHashSet) {
+ System.out.println(s);
+ }
+ }
+}