From 75dec87085b9bd6e41a32a716eb478ea0bfea876 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 21:51:37 +0000 Subject: [PATCH 1/5] add deadline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d20aaf9..7071577 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/339Lr3BJ) ### How the tests work (and Docker requirement) This project ships with an end‑to‑end CLI integration test suite that uses Testcontainers to spin up a temporary MySQL database. From 683af624c817438880b35b2fdf21e58fc3320b46 Mon Sep 17 00:00:00 2001 From: Tatjana Date: Sun, 30 Nov 2025 18:52:35 +0100 Subject: [PATCH 2/5] First commit --- mvnw | 1 + pom.xml | 5 + src/main/java/com/example/Main.java | 200 +++++++++++++++++- src/test/{ => java}/com/example/CliAppIT.java | 2 +- 4 files changed, 204 insertions(+), 4 deletions(-) mode change 100644 => 100755 mvnw rename src/test/{ => java}/com/example/CliAppIT.java (99%) diff --git a/mvnw b/mvnw old mode 100644 new mode 100755 index bd8896b..47442ae --- a/mvnw +++ b/mvnw @@ -1,4 +1,5 @@ #!/bin/sh + # ---------------------------------------------------------------------------- # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file diff --git a/pom.xml b/pom.xml index 002ff66..8ba1ee0 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,11 @@ org.apache.maven.plugins maven-failsafe-plugin 3.5.4 + + + 1.44 + + integration-test diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6dc6fbd..6f5766a 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,9 +1,8 @@ package com.example; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; +import java.sql.*; import java.util.Arrays; +import java.util.Scanner; public class Main { @@ -20,6 +19,8 @@ public void run() { String dbUser = resolveConfig("APP_DB_USER", "APP_DB_USER"); String dbPass = resolveConfig("APP_DB_PASS", "APP_DB_PASS"); + Scanner sc = new Scanner(System.in); + if (jdbcUrl == null || dbUser == null || dbPass == null) { throw new IllegalStateException( "Missing DB configuration. Provide APP_JDBC_URL, APP_DB_USER, APP_DB_PASS " + @@ -27,10 +28,16 @@ public void run() { } try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { + if(!loginHandler(connection, sc)){ + return; + } + menuHandler(connection, sc); + } catch (SQLException e) { throw new RuntimeException(e); } //Todo: Starting point for your code + } /** @@ -59,4 +66,191 @@ private static String resolveConfig(String propertyKey, String envKey) { } return (v == null || v.trim().isEmpty()) ? null : v.trim(); } + + private boolean loginHandler(Connection conn, Scanner sc) throws SQLException { + System.out.println("Username: "); + String user = sc.nextLine().trim(); + System.out.println("Password: "); + String password = sc.nextLine().trim(); + + String sql = """ + SELECT user_id + FROM account + WHERE name = ? AND password = ? + """; + try(PreparedStatement ps = conn.prepareStatement(sql)){ + ps.setString(1, user); + ps.setString(2, password); + ResultSet rs = ps.executeQuery(); + if (rs.next()){ + return true; + } + System.out.println("Invalid username or password"); + return false; + } + } + + private void menuHandler(Connection connection, Scanner sc) throws SQLException{ + + while(true){ + + System.out.println("-----Menu options-----"); + System.out.println("1. List moon missions (prints spacecraft names from `moon_mission`)"); + System.out.println("2. Get a moon mission by mission_id (prints details for that mission)"); + System.out.println("3. Count missions for a given year (prompts: year; prints the number of missions launched that year)"); + System.out.println("4. Create an account (prompts: first name, last name, ssn, password; prints confirmation)"); + System.out.println("5. Update an account password (prompts: user_id, new password; prints confirmation)"); + System.out.println("6. Delete an account (prompts: user_id; prints confirmation)"); + System.out.println("0. Exit"); + + System.out.println("Enter an option: "); + int choice = Integer.parseInt(sc.nextLine().trim()); + + switch (choice){ + case 1 -> listMoonMissions(connection); + case 2 -> getMissionById(connection, sc); + case 3 -> missionsCountByYear(connection, sc); + case 4 -> createAccount(connection, sc); + case 5 -> updateAccount(connection, sc); + case 6 -> deleteAccount(connection, sc); + case 0 -> {return;} + default -> + System.out.println("Invalid option. Please try again."); + } + } + } + + public void listMoonMissions(Connection connection) throws SQLException{ + String sql = """ + SELECT spacecraft + FROM moon_mission + """; + + try(PreparedStatement ps = connection.prepareStatement(sql); + ResultSet rs = ps.executeQuery()){ + + while (rs.next()){ + String spacecraft = rs.getString("spacecraft"); + System.out.println(spacecraft); + } + } + } + + public void getMissionById(Connection connection, Scanner sc) throws SQLException{ + System.out.println("MissionId: "); + int missionId = Integer.parseInt(sc.nextLine().trim()); + + String sql = """ + SELECT * + FROM moon_mission + WHERE mission_id = ? + """; + try(PreparedStatement ps = connection.prepareStatement(sql)){ + ps.setInt(1, missionId); + ResultSet rs = ps.executeQuery(); + + if (rs.next()) { + System.out.println("=== Moon Mission Details ==="); + System.out.println("ID: " + rs.getInt("mission_id")); + System.out.println("Spacecraft: " + rs.getString("spacecraft")); + System.out.println("Launch Date: " + rs.getDate("launch_date")); + System.out.println("Carrier Rocket: " + rs.getString("carrier_rocket")); + System.out.println("Operator: " + rs.getString("operator")); + System.out.println("Mission Type: " + rs.getString("mission_type")); + System.out.println("Outcome: " + rs.getString("outcome")); + } else { + System.out.println(" No mission found with ID: " + missionId); + } + } + + } + + public void missionsCountByYear(Connection connection, Scanner sc) throws SQLException{ + System.out.println("Launch date:"); + int launchYear = Integer.parseInt(sc.nextLine().trim()); + + String sql = """ + SELECT COUNT(*) AS missionCount + FROM moon_mission + WHERE YEAR(launch_date) = ? + """; + try(PreparedStatement ps = connection.prepareStatement(sql)){ + ps.setInt(1, launchYear); + ResultSet rs = ps.executeQuery(); + if(rs.next()){ + int count = rs.getInt("missionCount"); + System.out.println("Number of mission in " + launchYear + ": " + count); + } else{ + System.out.println("No result found."); + } + } + } + + public void createAccount(Connection connection, Scanner sc) throws SQLException{ + System.out.println("First name: "); + String firstName = sc.nextLine().trim(); + System.out.println("Last name: "); + String lastName = sc.nextLine().trim(); + System.out.println("SSN: "); + String ssn = sc.nextLine().trim(); + System.out.println("Password: "); + String password = sc.nextLine().trim(); + + String sql = """ + INSERT INTO account (first_name, last_name, ssn, password) + VALUES (?, ?, ?, ?); + """; + + try(PreparedStatement ps = connection.prepareStatement(sql)){ + ps.setString(1, firstName); + ps.setString(2, lastName); + ps.setString(3, ssn); + ps.setString(4, password); + + ps.executeUpdate(); + } + System.out.println("account created"); + } + + public void updateAccount(Connection connection, Scanner sc) throws SQLException{ + System.out.println("User id:"); + String userId = sc.nextLine().trim(); + System.out.println("New password: "); + String newPassword = sc.nextLine().trim(); + + String sql = """ + UPDATE account + SET password = ? + WHERE user_id = ? + """; + + try(PreparedStatement ps = connection.prepareStatement(sql)){ + ps.setString(1, newPassword); + ps.setString(2, userId); + + ps.executeUpdate(); + } + System.out.println("Password updated"); + } + + private void deleteAccount(Connection connection, Scanner sc) throws SQLException{ + System.out.println("User id: "); + int userId = Integer.parseInt(sc.nextLine().trim()); + + String sql = """ + DELETE FROM account + WHERE user_id = ? + """; + try(PreparedStatement ps = connection.prepareStatement(sql)){ + ps.setInt(1, userId); + + ps.executeUpdate(); + } + System.out.println("Account deleted"); + } + + } + + + diff --git a/src/test/com/example/CliAppIT.java b/src/test/java/com/example/CliAppIT.java similarity index 99% rename from src/test/com/example/CliAppIT.java rename to src/test/java/com/example/CliAppIT.java index 7d1eafb..a4cb292 100644 --- a/src/test/com/example/CliAppIT.java +++ b/src/test/java/com/example/CliAppIT.java @@ -207,7 +207,7 @@ void getMoonMissionById_printsDetails() throws Exception { ) + System.lineSeparator(); String out = runMainWithInput(input); - + System.out.println(out); assertThat(out) .as("CLI should print details that include the spacecraft name for the selected mission") .contains("Luna 3") From 4ba8a463f693fca17cec63071814bf60ef064647 Mon Sep 17 00:00:00 2001 From: Tatjana Date: Sun, 30 Nov 2025 19:26:08 +0100 Subject: [PATCH 3/5] Second commit after rabbit --- src/main/java/com/example/Main.java | 36 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6f5766a..6deb714 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -138,7 +138,16 @@ public void listMoonMissions(Connection connection) throws SQLException{ public void getMissionById(Connection connection, Scanner sc) throws SQLException{ System.out.println("MissionId: "); - int missionId = Integer.parseInt(sc.nextLine().trim()); + + int missionId; + while(true) { + try { + missionId = Integer.parseInt(sc.nextLine().trim()); + break; + } catch (NumberFormatException e) { + System.out.println("Invalid input. Please enter a number."); + } + } String sql = """ SELECT * @@ -159,14 +168,14 @@ public void getMissionById(Connection connection, Scanner sc) throws SQLExceptio System.out.println("Mission Type: " + rs.getString("mission_type")); System.out.println("Outcome: " + rs.getString("outcome")); } else { - System.out.println(" No mission found with ID: " + missionId); + System.out.println("No missions found with ID: " + missionId); } } } public void missionsCountByYear(Connection connection, Scanner sc) throws SQLException{ - System.out.println("Launch date:"); + System.out.println("Launch year:"); int launchYear = Integer.parseInt(sc.nextLine().trim()); String sql = """ @@ -179,7 +188,7 @@ WHERE YEAR(launch_date) = ? ResultSet rs = ps.executeQuery(); if(rs.next()){ int count = rs.getInt("missionCount"); - System.out.println("Number of mission in " + launchYear + ": " + count); + System.out.println("Number of missions in " + launchYear + ": " + count); } else{ System.out.println("No result found."); } @@ -195,17 +204,20 @@ public void createAccount(Connection connection, Scanner sc) throws SQLException String ssn = sc.nextLine().trim(); System.out.println("Password: "); String password = sc.nextLine().trim(); + String name = firstName.substring(0, Math.min(3, firstName.length())) + + lastName.substring(0, Math.min(3, lastName.length())); String sql = """ - INSERT INTO account (first_name, last_name, ssn, password) - VALUES (?, ?, ?, ?); + INSERT INTO account (name,first_name, last_name, ssn, password) + VALUES (?, ?, ?, ?, ?); """; try(PreparedStatement ps = connection.prepareStatement(sql)){ - ps.setString(1, firstName); - ps.setString(2, lastName); - ps.setString(3, ssn); - ps.setString(4, password); + ps.setString(1, name); + ps.setString(2, firstName); + ps.setString(3, lastName); + ps.setString(4, ssn); + ps.setString(5, password); ps.executeUpdate(); } @@ -214,7 +226,7 @@ INSERT INTO account (first_name, last_name, ssn, password) public void updateAccount(Connection connection, Scanner sc) throws SQLException{ System.out.println("User id:"); - String userId = sc.nextLine().trim(); + int userId = Integer.parseInt(sc.nextLine().trim()); System.out.println("New password: "); String newPassword = sc.nextLine().trim(); @@ -226,7 +238,7 @@ public void updateAccount(Connection connection, Scanner sc) throws SQLException try(PreparedStatement ps = connection.prepareStatement(sql)){ ps.setString(1, newPassword); - ps.setString(2, userId); + ps.setInt(2, userId); ps.executeUpdate(); } From 3c7ca7e369e26b7582b57326f323e635ab582d9d Mon Sep 17 00:00:00 2001 From: Tatjana Date: Sun, 30 Nov 2025 19:36:28 +0100 Subject: [PATCH 4/5] Third commit after rabbit --- src/main/java/com/example/Main.java | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6deb714..999e301 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -19,15 +19,14 @@ public void run() { String dbUser = resolveConfig("APP_DB_USER", "APP_DB_USER"); String dbPass = resolveConfig("APP_DB_PASS", "APP_DB_PASS"); - Scanner sc = new Scanner(System.in); - if (jdbcUrl == null || dbUser == null || dbPass == null) { throw new IllegalStateException( "Missing DB configuration. Provide APP_JDBC_URL, APP_DB_USER, APP_DB_PASS " + "as system properties (-Dkey=value) or environment variables."); } - try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { + try (Scanner sc = new Scanner(System.in); + Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { if(!loginHandler(connection, sc)){ return; } @@ -226,7 +225,14 @@ INSERT INTO account (name,first_name, last_name, ssn, password) public void updateAccount(Connection connection, Scanner sc) throws SQLException{ System.out.println("User id:"); - int userId = Integer.parseInt(sc.nextLine().trim()); + int userId; + try { + userId = Integer.parseInt(sc.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.println("Invalid input. Please enter a valid user ID."); + return; + } + System.out.println("New password: "); String newPassword = sc.nextLine().trim(); @@ -246,8 +252,15 @@ public void updateAccount(Connection connection, Scanner sc) throws SQLException } private void deleteAccount(Connection connection, Scanner sc) throws SQLException{ - System.out.println("User id: "); - int userId = Integer.parseInt(sc.nextLine().trim()); + System.out.println("User id:"); + int userId; + try { + userId = Integer.parseInt(sc.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.println("Invalid input. Please enter a valid user ID."); + return; + } + String sql = """ DELETE FROM account From 8e85d3821aa0ae84b6f86675a0955079a5a9bb02 Mon Sep 17 00:00:00 2001 From: Tatjana Date: Sun, 30 Nov 2025 19:40:50 +0100 Subject: [PATCH 5/5] Fourth commit --- src/test/java/com/example/CliAppIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/example/CliAppIT.java b/src/test/java/com/example/CliAppIT.java index a4cb292..7d1eafb 100644 --- a/src/test/java/com/example/CliAppIT.java +++ b/src/test/java/com/example/CliAppIT.java @@ -207,7 +207,7 @@ void getMoonMissionById_printsDetails() throws Exception { ) + System.lineSeparator(); String out = runMainWithInput(input); - System.out.println(out); + assertThat(out) .as("CLI should print details that include the spacecraft name for the selected mission") .contains("Luna 3")