Get new things
This commit is contained in:
		
							parent
							
								
									88d43259a4
								
							
						
					
					
						commit
						cfa48663e2
					
				
					 619 changed files with 283313 additions and 311 deletions
				
			
		
							
								
								
									
										5
									
								
								.idea/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | # Default ignored files | ||||||
|  | /shelf/ | ||||||
|  | /workspace.xml | ||||||
|  | # Editor-based HTTP Client requests | ||||||
|  | /httpRequests/ | ||||||
							
								
								
									
										7
									
								
								.idea/misc.xml
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.idea/misc.xml
									
										
									
										generated
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="ScalaSbtSettings"> | ||||||
|  |     <option name="customLauncherPath" /> | ||||||
|  |     <option name="customVMPath" /> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
|  | @ -13,12 +13,9 @@ submission { | ||||||
|     // Setzen Sie im folgenden Bereich Ihre TU-ID (NICHT Ihre Matrikelnummer!), Ihren Nachnamen und Ihren Vornamen |     // Setzen Sie im folgenden Bereich Ihre TU-ID (NICHT Ihre Matrikelnummer!), Ihren Nachnamen und Ihren Vornamen | ||||||
|     // in Anführungszeichen (z.B. "ab12cdef" für Ihre TU-ID) ein! |     // in Anführungszeichen (z.B. "ab12cdef" für Ihre TU-ID) ein! | ||||||
|     // BEISPIEL: |     // BEISPIEL: | ||||||
|     // studentId = "ab12cdef" |     studentId = "ab12cdef" | ||||||
|     // firstName = "sol_first" |     firstName = "sol_first" | ||||||
|     // lastName = "sol_last" |     lastName = "sol_last" | ||||||
|     studentId = "" |  | ||||||
|     firstName = "" |  | ||||||
|     lastName = "" |  | ||||||
| 
 | 
 | ||||||
|     // Optionally require own tests for mainBuildSubmission task. Default is false |     // Optionally require own tests for mainBuildSubmission task. Default is false | ||||||
|     requireTests = false |     requireTests = false | ||||||
|  |  | ||||||
|  | @ -5,6 +5,10 @@ import fopbot.Robot; | ||||||
| import fopbot.RobotFamily; | import fopbot.RobotFamily; | ||||||
| import fopbot.World; | import fopbot.World; | ||||||
| 
 | 
 | ||||||
|  | import java.util.function.Function; | ||||||
|  | import java.util.stream.IntStream; | ||||||
|  | import java.util.stream.Stream; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Main entry point in executing the program. |  * Main entry point in executing the program. | ||||||
|  */ |  */ | ||||||
|  | @ -30,43 +34,103 @@ public class Main { | ||||||
|         setupWorld(); |         setupWorld(); | ||||||
| 
 | 
 | ||||||
|         // TODO: H0.4 - Initializing FOPBot |         // TODO: H0.4 - Initializing FOPBot | ||||||
| 
 |         var kaspar = new Robot(0, 0, Direction.DOWN, 4, RobotFamily.SQUARE_BLUE); | ||||||
|  |         var alfred = new Robot(0, 3, Direction.DOWN, 0, RobotFamily.SQUARE_GREEN); | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 0) return; // DO NOT TOUCH! |         if (runToSubtask == 0) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.5.1 - Turning with repeated instructions |         // TODO: H0.5.1 - Turning with repeated instructions | ||||||
| 
 |         IntStream.rangeClosed(0, 1) | ||||||
|  |             .forEach(x -> alfred.turnLeft()); | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 1) return; // DO NOT TOUCH! |         if (runToSubtask == 1) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.5.2 - Turning with for-loop |         // TODO: H0.5.2 - Turning with for-loop | ||||||
| 
 |         for (int i = 0; i < 1; i++) { | ||||||
|  |             IntStream.rangeClosed(0, 1) | ||||||
|  |                 .forEach(x -> alfred.turnLeft()); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 2) return; // DO NOT TOUCH! |         if (runToSubtask == 2) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.5.3 - Turning with while-loop |         // TODO: H0.5.3 - Turning with while-loop | ||||||
| 
 |         boolean b = false; | ||||||
|  |         while (b = !b) { | ||||||
|  |             Stream.generate(Object::new) | ||||||
|  |                 .takeWhile( x -> !kaspar.isFacingRight()) | ||||||
|  |                 .forEach(x -> kaspar.turnLeft()); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 3) return; // DO NOT TOUCH! |         if (runToSubtask == 3) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.6.1 - Put with repeated instructions |         // TODO: H0.6.1 - Put with repeated instructions | ||||||
| 
 |         kaspar.putCoin(); | ||||||
|  |         Stream.generate(Object::new) | ||||||
|  |             .takeWhile( x -> kaspar.isFrontClear()) | ||||||
|  |             .forEach(x -> kaspar.move()); | ||||||
|  |         kaspar.turnLeft(); | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 4) return; // DO NOT TOUCH! |         if (runToSubtask == 4) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.6.2 - Pick with repeated instructions |         // TODO: H0.6.2 - Pick with repeated instructions | ||||||
| 
 |         Stream.generate(Object::new) | ||||||
|  |             .takeWhile( x -> alfred.isFrontClear()) | ||||||
|  |             .map(x -> { | ||||||
|  |                 alfred.move(); | ||||||
|  |                 return alfred.isOnACoin(); | ||||||
|  |             }) | ||||||
|  |             .filter(x -> x) | ||||||
|  |             .forEach(x -> alfred.pickCoin()); | ||||||
|  |         alfred.turnLeft(); | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 5) return; // DO NOT TOUCH! |         if (runToSubtask == 5) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.6.3 - Put with for-loop |         // TODO: H0.6.3 - Put with for-loop | ||||||
|  |         for (int i = 0; i < 1; i++) { | ||||||
|  |             kaspar.putCoin(); | ||||||
|  |             Stream.generate(Object::new) | ||||||
|  |                 .takeWhile( x -> kaspar.isFrontClear()) | ||||||
|  |                 .forEach(x -> kaspar.move()); | ||||||
|  |             kaspar.turnLeft(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 6) return; // DO NOT TOUCH! |         if (runToSubtask == 6) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.7.1 - Pick with while-loop |         // TODO: H0.7.1 - Pick with while-loop | ||||||
| 
 |         b = false; | ||||||
|  |         while (b = !b) { | ||||||
|  |             Stream.generate(Object::new) | ||||||
|  |                 .takeWhile( x -> alfred.isFrontClear()) | ||||||
|  |                 .map(x -> { | ||||||
|  |                     alfred.move(); | ||||||
|  |                     return alfred.isOnACoin(); | ||||||
|  |                 }) | ||||||
|  |                 .filter(x -> x) | ||||||
|  |                 .forEach(x -> alfred.pickCoin()); | ||||||
|  |             alfred.turnLeft(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 7) return; // DO NOT TOUCH! |         if (runToSubtask == 7) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.7.2 - Pick and put with while-loop |         // TODO: H0.7.2 - Pick and put with while-loop | ||||||
| 
 |         b = false; | ||||||
|  |         while (b = !b) { | ||||||
|  |             kaspar.putCoin(); | ||||||
|  |             Stream.generate(Object::new) | ||||||
|  |                 .takeWhile( x -> alfred.isFrontClear()) | ||||||
|  |                 .forEach(x -> { | ||||||
|  |                     alfred.move(); | ||||||
|  |                     kaspar.move(); | ||||||
|  |                 }); | ||||||
|  |             kaspar.turnLeft(); | ||||||
|  |             alfred.pickCoin(); | ||||||
|  |             alfred.turnLeft(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (runToSubtask == 8) return; // DO NOT TOUCH! |         if (runToSubtask == 8) return; // DO NOT TOUCH! | ||||||
|         // TODO: H0.7.3 - Put with reversed for-loop |         // TODO: H0.7.3 - Put with reversed for-loop | ||||||
| 
 |         for (int i = alfred.getNumberOfCoins(); i == alfred.getNumberOfCoins() ; i--) { | ||||||
|  |             Stream.generate(Object::new) | ||||||
|  |                 .takeWhile( x -> alfred.hasAnyCoins()) | ||||||
|  |                 .forEach(x -> { | ||||||
|  |                     alfred.putCoin(); | ||||||
|  |                     alfred.move(); | ||||||
|  |                 }); | ||||||
|  |             alfred.turnLeft(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -79,7 +143,7 @@ public class Main { | ||||||
| 
 | 
 | ||||||
|         // speed of how fast the world gets refreshed (e.g. how fast the robot(s) act) |         // speed of how fast the world gets refreshed (e.g. how fast the robot(s) act) | ||||||
|         // the lower the number, the faster the refresh |         // the lower the number, the faster the refresh | ||||||
|         World.setDelay(delay); |         // World.setDelay(delay); | ||||||
| 
 | 
 | ||||||
|         // make it possible to see the world window |         // make it possible to see the world window | ||||||
|         World.setVisible(true); |         World.setVisible(true); | ||||||
|  |  | ||||||
|  | @ -7,6 +7,8 @@ import h01.template.Families; | ||||||
| import h01.template.Ghost; | import h01.template.Ghost; | ||||||
| import h01.template.TickBased; | import h01.template.TickBased; | ||||||
| 
 | 
 | ||||||
|  | import java.util.stream.Stream; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * The {@link BlueGhost} is a {@link Robot} that looks like a blue ghost. |  * The {@link BlueGhost} is a {@link Robot} that looks like a blue ghost. | ||||||
|  * It tries to move in a circle. |  * It tries to move in a circle. | ||||||
|  | @ -29,6 +31,6 @@ public class BlueGhost extends Robot implements Ghost, TickBased { | ||||||
|     @Override |     @Override | ||||||
|     @StudentImplementationRequired("H2.1") |     @StudentImplementationRequired("H2.1") | ||||||
|     public void doMove() { |     public void doMove() { | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.1 - Remove if implemented"); |             FuckBot.exec("<<<(<!|)^", this); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										72
									
								
								H01/src/main/java/h01/FuckBot.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								H01/src/main/java/h01/FuckBot.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | package h01; | ||||||
|  | 
 | ||||||
|  | import fopbot.Robot; | ||||||
|  | 
 | ||||||
|  | public class FuckBot { | ||||||
|  | 
 | ||||||
|  |     public static void exec(String proc, Robot... robots) { | ||||||
|  |         var r = robots[0]; | ||||||
|  |         int isp = 0; | ||||||
|  | 
 | ||||||
|  |         while (isp < proc.length()) { | ||||||
|  |             switch (proc.charAt(isp)) { | ||||||
|  |                 case '<' -> r.turnLeft(); | ||||||
|  |                 case '^' -> r.move(); | ||||||
|  |                 case '.' -> r.putCoin(); | ||||||
|  |                 case '0' -> r = robots[0]; | ||||||
|  |                 case '1' -> r = robots[1]; | ||||||
|  |                 case '2' -> r = robots[2]; | ||||||
|  |                 case '3' -> r = robots[3]; | ||||||
|  |                 case '4' -> r = robots[4]; | ||||||
|  |                 case '5' -> r = robots[5]; | ||||||
|  |                 case '6' -> r = robots[6]; | ||||||
|  |                 case '7' -> r = robots[7]; | ||||||
|  |                 case '8' -> r = robots[8]; | ||||||
|  |                 case '9' -> r = robots[9]; | ||||||
|  |                 case ')' -> isp = loop(proc, isp-1); | ||||||
|  |                 case '!' -> { | ||||||
|  |                     isp++; | ||||||
|  |                     switch (proc.charAt(isp)) { | ||||||
|  |                         case '|' -> { | ||||||
|  |                             if (!r.isFrontClear()) { | ||||||
|  |                                 isp = loop(proc, isp); | ||||||
|  |                             } else { | ||||||
|  |                                 isp++; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 case '?' -> { | ||||||
|  |                     isp++; | ||||||
|  |                     switch (proc.charAt(isp)) { | ||||||
|  |                         case '|' -> { | ||||||
|  |                             if (r.isFrontClear()) { | ||||||
|  |                                 isp = loop(proc, isp); | ||||||
|  |                             } else { | ||||||
|  |                                 isp++; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             isp++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static int loop(String proc, int isp) { | ||||||
|  |         var closed = 1; | ||||||
|  | 
 | ||||||
|  |         for (int i = isp; i >= 0; i--) { | ||||||
|  |             switch (proc.charAt(i)) { | ||||||
|  |                 case ')' -> closed++; | ||||||
|  |                 case '(' -> closed--; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (closed == 0) { | ||||||
|  |                 return i; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -34,6 +34,21 @@ public class OrangeGhost extends Robot implements Ghost, TickBased { | ||||||
|     @Override |     @Override | ||||||
|     @StudentImplementationRequired("H2.3") |     @StudentImplementationRequired("H2.3") | ||||||
|     public void doMove() { |     public void doMove() { | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.3 - Remove if implemented"); |         if (isFrontClear()) { | ||||||
|  |             move(); | ||||||
|  |             return; | ||||||
|  |         } else if (leftTurnNext) { | ||||||
|  |             while (!isFrontClear()) { | ||||||
|  |                 turnLeft(); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             while (!isFrontClear()) { | ||||||
|  |                 turnLeft(); | ||||||
|  |                 turnLeft(); | ||||||
|  |                 turnLeft(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         leftTurnNext = !leftTurnNext; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ import h01.template.Controllable; | ||||||
| import h01.template.Families; | import h01.template.Families; | ||||||
| import h01.template.TickBased; | import h01.template.TickBased; | ||||||
| 
 | 
 | ||||||
|  | import javax.xml.xpath.XPathConstants; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * {@link Pacman} is a {@link Robot} that can be controlled by the user and |  * {@link Pacman} is a {@link Robot} that can be controlled by the user and | ||||||
|  * looks like Pacman. |  * looks like Pacman. | ||||||
|  | @ -36,6 +38,19 @@ public class Pacman extends Robot implements Controllable, TickBased { | ||||||
|     @Override |     @Override | ||||||
|     @StudentImplementationRequired("H1.1") |     @StudentImplementationRequired("H1.1") | ||||||
|     public void handleKeyInput(int k) { |     public void handleKeyInput(int k) { | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H1.1 - Remove if implemented"); |         if (k < 0 || k > 3) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var dir = Direction.values()[k]; | ||||||
|  |         while (getDirection() != dir) { | ||||||
|  |             turnLeft(); | ||||||
|  |         } | ||||||
|  |         if (isFrontClear()) { | ||||||
|  |             move(); | ||||||
|  |         } | ||||||
|  |         if (isOnACoin()) { | ||||||
|  |             pickCoin(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,10 @@ import h01.template.Ghost; | ||||||
| import h01.template.TickBased; | import h01.template.TickBased; | ||||||
| import h01.template.Util; | import h01.template.Util; | ||||||
| 
 | 
 | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.stream.IntStream; | ||||||
|  | import java.util.stream.Stream; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * The {@link PinkGhost} is a {@link Robot} that looks like a pink ghost. |  * The {@link PinkGhost} is a {@link Robot} that looks like a pink ghost. | ||||||
|  * It tries to move in a random direction. |  * It tries to move in a random direction. | ||||||
|  | @ -31,6 +35,19 @@ public class PinkGhost extends Robot implements Ghost, TickBased { | ||||||
|     @Override |     @Override | ||||||
|     @StudentImplementationRequired("H2.2") |     @StudentImplementationRequired("H2.2") | ||||||
|     public void doMove() { |     public void doMove() { | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.2 - Remove if implemented"); |         var dirs = IntStream.range(0, 4) | ||||||
|  |         .mapToObj(x -> { | ||||||
|  |             turnLeft(); | ||||||
|  |             return isFrontClear(); | ||||||
|  |         }) | ||||||
|  |             .filter(x -> x) | ||||||
|  |         .map(x -> getDirection()) | ||||||
|  |             .toList(); | ||||||
|  |         var i = Util.getRandomInteger(1, dirs.size()); | ||||||
|  |         var dir = dirs.get(i-1); | ||||||
|  |         while (dir != getDirection()) { | ||||||
|  |             turnLeft(); | ||||||
|  |         } | ||||||
|  |         move(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -34,6 +34,13 @@ public class RedGhost extends Robot implements Ghost, TickBased { | ||||||
|     @Override |     @Override | ||||||
|     @StudentImplementationRequired("H2.4") |     @StudentImplementationRequired("H2.4") | ||||||
|     public void doMove() { |     public void doMove() { | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.4 - Remove if implemented"); |         var dir = Util.furthestDirection(chased, this); | ||||||
|  |         while (getDirection() != dir) { | ||||||
|  |             turnLeft(); | ||||||
|  |         } | ||||||
|  |         while (!isFrontClear()) { | ||||||
|  |             turnLeft(); | ||||||
|  |         } | ||||||
|  |         move(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ import java.util.Optional; | ||||||
|  * The {@link FourWins} class represents the main class of the FourWins game. |  * The {@link FourWins} class represents the main class of the FourWins game. | ||||||
|  */ |  */ | ||||||
| public class FourWins { | public class FourWins { | ||||||
|     private final InputHandler inputHandler = new InputHandler(this); |     public final InputHandler inputHandler = new InputHandler(this); | ||||||
|     /** |     /** | ||||||
|      * The width of the game board. |      * The width of the game board. | ||||||
|      */ |      */ | ||||||
|  | @ -70,7 +70,17 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.1") |     @StudentImplementationRequired("H2.2.1") | ||||||
|     public static boolean validateInput(final int column, final RobotFamily[][] stones) { |     public static boolean validateInput(final int column, final RobotFamily[][] stones) { | ||||||
|         // TODO: H2.2.1 |         // TODO: H2.2.1 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.2.1 - Remove if implemented"); |         if (column < 0 || column >= World.getWidth()) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int y = 0; y < World.getHeight(); y++) { | ||||||
|  |             if (stones[y][column] == null) { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -86,7 +96,14 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.2") |     @StudentImplementationRequired("H2.2.2") | ||||||
|     public static int getDestinationRow(final int column, final RobotFamily[][] stones) { |     public static int getDestinationRow(final int column, final RobotFamily[][] stones) { | ||||||
|         // TODO: H2.2.2 |         // TODO: H2.2.2 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.2.2 - Remove if implemented"); | 
 | ||||||
|  |         for (int y = 0; y < World.getHeight(); y++) { | ||||||
|  |             if (stones[y][column] == null) { | ||||||
|  |                 return y; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -105,7 +122,14 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.2") |     @StudentImplementationRequired("H2.2.2") | ||||||
|     public static void dropStone(final int column, final RobotFamily[][] stones, final RobotFamily currentPlayer) { |     public static void dropStone(final int column, final RobotFamily[][] stones, final RobotFamily currentPlayer) { | ||||||
|         // TODO: H2.2.2 |         // TODO: H2.2.2 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.2.2 - Remove if implemented"); |         var robot = new Robot(column, World.getHeight()-1, Direction.DOWN, 0, currentPlayer); | ||||||
|  |         var row = getDestinationRow(column, stones); | ||||||
|  |         while (robot.getY() != row) { | ||||||
|  |             robot.move(); | ||||||
|  |         } | ||||||
|  |         robot.turnLeft(); | ||||||
|  |         robot.turnLeft(); | ||||||
|  |         stones[robot.getY()][robot.getX()] = robot.getRobotFamily(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -121,7 +145,7 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.3") |     @StudentImplementationRequired("H2.2.3") | ||||||
|     public static boolean testWinConditions(final RobotFamily[][] stones, final RobotFamily currentPlayer) { |     public static boolean testWinConditions(final RobotFamily[][] stones, final RobotFamily currentPlayer) { | ||||||
|         // TODO: H2.2.3 |         // TODO: H2.2.3 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.2.3 - Remove if implemented"); |         return testWinDiagonal(stones, currentPlayer) || testWinVertical(stones, currentPlayer) || testWinHorizontal(stones, currentPlayer); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -135,7 +159,20 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.3") |     @StudentImplementationRequired("H2.2.3") | ||||||
|     public static boolean testWinHorizontal(final RobotFamily[][] stones, final RobotFamily currentPlayer) { |     public static boolean testWinHorizontal(final RobotFamily[][] stones, final RobotFamily currentPlayer) { | ||||||
|         // TODO: H2.2.3 |         // TODO: H2.2.3 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.2.3 - Remove if implemented"); |         for (int y = 0; y < World.getHeight(); y++) { | ||||||
|  |             int count = 0; | ||||||
|  |             for (int x = 0; x < World.getWidth(); x++) { | ||||||
|  |                 if (stones[y][x] == currentPlayer) { | ||||||
|  |                     count++; | ||||||
|  |                 } else { | ||||||
|  |                     count = 0; | ||||||
|  |                 } | ||||||
|  |                 if (count == 4) { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -149,7 +186,20 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.3") |     @StudentImplementationRequired("H2.2.3") | ||||||
|     public static boolean testWinVertical(final RobotFamily[][] stones, final RobotFamily currentPlayer) { |     public static boolean testWinVertical(final RobotFamily[][] stones, final RobotFamily currentPlayer) { | ||||||
|         // TODO: H2.2.3 |         // TODO: H2.2.3 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.2.3 - Remove if implemented"); |         for (int x = 0; x < World.getWidth(); x++) { | ||||||
|  |             int count = 0; | ||||||
|  |             for (int y = 0; y < World.getHeight(); y++) { | ||||||
|  |                 if (stones[y][x] == currentPlayer) { | ||||||
|  |                     count++; | ||||||
|  |                 } else { | ||||||
|  |                     count = 0; | ||||||
|  |                 } | ||||||
|  |                 if (count == 4) { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -208,7 +258,10 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.4") |     @StudentImplementationRequired("H2.2.4") | ||||||
|     public static RobotFamily nextPlayer(final RobotFamily currentPlayer) { |     public static RobotFamily nextPlayer(final RobotFamily currentPlayer) { | ||||||
|         // TODO: H2.2.4 |         // TODO: H2.2.4 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.2.4 - Remove if implemented"); |         return currentPlayer == RobotFamily.SQUARE_BLUE | ||||||
|  |             ? RobotFamily.SQUARE_RED | ||||||
|  |             : RobotFamily.SQUARE_BLUE; | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -219,7 +272,7 @@ public class FourWins { | ||||||
|         inputHandler.displayDrawStatus(); |         inputHandler.displayDrawStatus(); | ||||||
| 
 | 
 | ||||||
|         // TODO: H2.2.4 |         // TODO: H2.2.4 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.2.4 - Remove if implemented"); |         System.out.println("No valid columns found. Hence, game ends with a draw."); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -232,7 +285,7 @@ public class FourWins { | ||||||
|         inputHandler.displayWinnerStatus(winner); |         inputHandler.displayWinnerStatus(winner); | ||||||
| 
 | 
 | ||||||
|         // TODO: H2.2.4 |         // TODO: H2.2.4 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.2.4 - Remove if implemented"); |         System.out.printf("Player %s wins the game!\n", winner); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -244,7 +297,11 @@ public class FourWins { | ||||||
|     @StudentImplementationRequired("H2.2.4") |     @StudentImplementationRequired("H2.2.4") | ||||||
|     public static void colorFieldBackground(final RobotFamily winner) { |     public static void colorFieldBackground(final RobotFamily winner) { | ||||||
|         // TODO: H2.2.4 |         // TODO: H2.2.4 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.2.4 - Remove if implemented"); |         for (int y = 0; y < World.getHeight(); y++) { | ||||||
|  |             for (int x = 0; x < World.getWidth(); x++) { | ||||||
|  |                 setFieldColor(x, y, winner); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -266,7 +323,7 @@ public class FourWins { | ||||||
|         while (!finished) { |         while (!finished) { | ||||||
|             // TODO: H2.2.4 |             // TODO: H2.2.4 | ||||||
|             // set next player |             // set next player | ||||||
|             org.tudalgo.algoutils.student.Student.crash("H2.2.4 - Remove if implemented"); |             currentPlayer = nextPlayer(currentPlayer); | ||||||
| 
 | 
 | ||||||
|             // wait for click in column (DO NOT TOUCH) |             // wait for click in column (DO NOT TOUCH) | ||||||
|             finished = draw = isGameBoardFull(stones); |             finished = draw = isGameBoardFull(stones); | ||||||
|  | @ -278,7 +335,8 @@ public class FourWins { | ||||||
|             // TODO: H2.2.4 |             // TODO: H2.2.4 | ||||||
|             // let stone drop |             // let stone drop | ||||||
|             // test win conditions |             // test win conditions | ||||||
|             org.tudalgo.algoutils.student.Student.crash("H2.2.4 - Remove if implemented"); |             dropStone(column, stones, currentPlayer); | ||||||
|  |             finished = testWinConditions(stones, currentPlayer); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // displaying either draw or winner (DO NOT TOUCH) |         // displaying either draw or winner (DO NOT TOUCH) | ||||||
|  | @ -341,5 +399,4 @@ public class FourWins { | ||||||
|     public boolean isFinished() { |     public boolean isFinished() { | ||||||
|         return finished; |         return finished; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,6 +4,8 @@ import fopbot.RobotFamily; | ||||||
| import fopbot.World; | import fopbot.World; | ||||||
| import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
| 
 | 
 | ||||||
|  | import java.util.Arrays; | ||||||
|  | 
 | ||||||
| import static org.tudalgo.algoutils.student.io.PropertyUtils.getIntProperty; | import static org.tudalgo.algoutils.student.io.PropertyUtils.getIntProperty; | ||||||
| import static org.tudalgo.algoutils.student.test.StudentTestUtils.printTestResults; | import static org.tudalgo.algoutils.student.test.StudentTestUtils.printTestResults; | ||||||
| import static org.tudalgo.algoutils.student.test.StudentTestUtils.testEquals; | import static org.tudalgo.algoutils.student.test.StudentTestUtils.testEquals; | ||||||
|  | @ -41,7 +43,10 @@ public class Main { | ||||||
|     @StudentImplementationRequired("H2.3") |     @StudentImplementationRequired("H2.3") | ||||||
|     public static void sanityChecksH211() { |     public static void sanityChecksH211() { | ||||||
|         // TODO: H2.3 |         // TODO: H2.3 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.3 - Remove if implemented"); |         var arr = new int[0]; | ||||||
|  |         arr = OneDimensionalArrayStuff.push(arr, 4); | ||||||
|  |         arr = OneDimensionalArrayStuff.push(arr, 2); | ||||||
|  |         testEquals(true, Arrays.equals(arr, new int[]{4,2})); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -63,7 +68,11 @@ public class Main { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         // TODO: H2.3 |         // TODO: H2.3 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.3 - Remove if implemented"); |         var x = TwoDimensionalArrayStuff.meanOccurrencesPerLine(simpleTest, "a"); | ||||||
|  |         testEquals(1.0f, x); | ||||||
|  | 
 | ||||||
|  |         var y = TwoDimensionalArrayStuff.meanOccurrencesPerLine(complexTest, "a"); | ||||||
|  |         testEquals(2.0f, y); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -93,7 +102,6 @@ public class Main { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         // TODO: H2.4 |         // TODO: H2.4 | ||||||
|         org.tudalgo.algoutils.student.Student.crash("H2.4 - Remove if implemented"); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,8 +24,12 @@ public class OneDimensionalArrayStuff { | ||||||
|     @SuppressWarnings("ManualArrayCopy") |     @SuppressWarnings("ManualArrayCopy") | ||||||
|     @StudentImplementationRequired("H2.1.1") |     @StudentImplementationRequired("H2.1.1") | ||||||
|     public static int[] push(final int[] array, final int value) { |     public static int[] push(final int[] array, final int value) { | ||||||
|         // TODO: H2.1.1 |         var newarr = new int[array.length+1]; | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.1.1 - Remove if implemented"); |         for (int i = 0; i < array.length; i++) { | ||||||
|  |             newarr[i] = array[i]; | ||||||
|  |         } | ||||||
|  |         newarr[array.length] = value; | ||||||
|  |         return newarr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -37,8 +41,9 @@ public class OneDimensionalArrayStuff { | ||||||
|      */ |      */ | ||||||
|     @StudentImplementationRequired("H2.1.1") |     @StudentImplementationRequired("H2.1.1") | ||||||
|     public static int[] calculateNextFibonacci(final int[] array) { |     public static int[] calculateNextFibonacci(final int[] array) { | ||||||
|         // TODO: H2.1.1 |         var a = array[array.length-2]; | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.1.1 - Remove if implemented"); |         var b = array[array.length-1]; | ||||||
|  |         return push(array, a+b); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -48,8 +53,15 @@ public class OneDimensionalArrayStuff { | ||||||
|      * @return the n-th Fibonacci number |      * @return the n-th Fibonacci number | ||||||
|      */ |      */ | ||||||
|     @StudentImplementationRequired("H2.1.1") |     @StudentImplementationRequired("H2.1.1") | ||||||
|     public static int fibonacci(final int n) { |     public static int fibonacci(int n) { | ||||||
|         // TODO: H2.1.1 |         var arr = new int[] {0, 1}; | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.1.1 - Remove if implemented"); |         if (n < 2) { | ||||||
|  |             return arr[n]; | ||||||
|  |         } | ||||||
|  |         n -= 2; | ||||||
|  |         while (n --> 0) { | ||||||
|  |             arr = calculateNextFibonacci(arr); | ||||||
|  |         } | ||||||
|  |         return arr[arr.length-1]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,7 +3,11 @@ package h02; | ||||||
| import org.tudalgo.algoutils.student.annotation.DoNotTouch; | import org.tudalgo.algoutils.student.annotation.DoNotTouch; | ||||||
| import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
| 
 | 
 | ||||||
|  | import java.util.regex.*; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | import java.util.stream.IntStream; | ||||||
|  | import java.util.stream.Stream; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This class serves as a container for the methods that are to be implemented by the students for exercise H2.1.2. |  * This class serves as a container for the methods that are to be implemented by the students for exercise H2.1.2. | ||||||
|  | @ -27,7 +31,17 @@ public class TwoDimensionalArrayStuff { | ||||||
|     @StudentImplementationRequired("H2.1.2") |     @StudentImplementationRequired("H2.1.2") | ||||||
|     public static int[] occurrences(final String[][] input, final String query) { |     public static int[] occurrences(final String[][] input, final String query) { | ||||||
|         // TODO: H2.1.2 |         // TODO: H2.1.2 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.1.2 - Remove if implemented"); |         return Stream.of(input) | ||||||
|  |             .map(line -> String.join("\0", line)) | ||||||
|  |             .mapToInt(line -> { | ||||||
|  |                 var m = Pattern.compile(query).matcher(line); | ||||||
|  |                 var i = 0; | ||||||
|  |                 while (m.find()) { | ||||||
|  |                     i++; | ||||||
|  |                 } | ||||||
|  |                 return i; | ||||||
|  |             }) | ||||||
|  |             .toArray(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -39,7 +53,7 @@ public class TwoDimensionalArrayStuff { | ||||||
|     @StudentImplementationRequired("H2.1.2") |     @StudentImplementationRequired("H2.1.2") | ||||||
|     public static float mean(final int[] input) { |     public static float mean(final int[] input) { | ||||||
|         // TODO: H2.1.2 |         // TODO: H2.1.2 | ||||||
|         return org.tudalgo.algoutils.student.Student.crash("H2.1.2 - Remove if implemented"); |         return (float) (IntStream.of(input).sum()) / input.length; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  |  | ||||||
|  | @ -1,6 +1,14 @@ | ||||||
| package h03; | package h03; | ||||||
| 
 | 
 | ||||||
| import fopbot.World; | import fopbot.World; | ||||||
|  | import h03.robots.DoublePowerRobot; | ||||||
|  | import h03.robots.HackingRobot; | ||||||
|  | import h03.robots.MovementType; | ||||||
|  | import h03.robots.VersatileRobot; | ||||||
|  | 
 | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | import java.util.stream.Stream; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Main entry point in executing the program. |  * Main entry point in executing the program. | ||||||
|  | @ -15,5 +23,33 @@ public class Main { | ||||||
|         // Create a 5x5 world and make it visible |         // Create a 5x5 world and make it visible | ||||||
|         World.setSize(5, 5); |         World.setSize(5, 5); | ||||||
|         World.setVisible(true); |         World.setVisible(true); | ||||||
|  | 
 | ||||||
|  |         var haxxor = new HackingRobot(3, 2, true); | ||||||
|  |         var olaf = new HackingRobot(1, 4, false); | ||||||
|  | 
 | ||||||
|  |         var versi = new VersatileRobot(4, 3, true, false); | ||||||
|  |         while (versi.getType() != MovementType.DIAGONAL)  { | ||||||
|  |             versi = new VersatileRobot(4, 3, true, false); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var doubleTrouble1 = new DoublePowerRobot(2, 1, true); | ||||||
|  |         var doubleTrouble2 = new DoublePowerRobot(2, 1, false); | ||||||
|  |         var doubleTrouble3 = new DoublePowerRobot(2, 3, true); | ||||||
|  | 
 | ||||||
|  |         var set = Stream.of(doubleTrouble1, doubleTrouble2, doubleTrouble3) | ||||||
|  |             .flatMap(x -> Stream.of(x.getType(), x.getNextType())) | ||||||
|  |             .collect(Collectors.toSet()); | ||||||
|  |         while (set.size() < 3) { | ||||||
|  |             doubleTrouble1 = new DoublePowerRobot(2, 1, true); | ||||||
|  |             doubleTrouble2 = new DoublePowerRobot(2, 1, false); | ||||||
|  |             doubleTrouble3 = new DoublePowerRobot(2, 3, true); | ||||||
|  | 
 | ||||||
|  |             set = Stream.of(doubleTrouble1, doubleTrouble2, doubleTrouble3) | ||||||
|  |                 .flatMap(x -> Stream.of(x.getType(), x.getNextType())) | ||||||
|  |                 .collect(Collectors.toSet()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var challenge = new RobotsChallenge(0, 4, doubleTrouble1, doubleTrouble2, doubleTrouble3); | ||||||
|  |         System.out.println(Arrays.deepToString(challenge.findWinners())); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										65
									
								
								H03/src/main/java/h03/RobotsChallenge.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								H03/src/main/java/h03/RobotsChallenge.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | ||||||
|  | package h03; | ||||||
|  | 
 | ||||||
|  | import h03.robots.DoublePowerRobot; | ||||||
|  | import h03.robots.MovementType; | ||||||
|  | 
 | ||||||
|  | import javax.swing.text.html.parser.TagElement; | ||||||
|  | import java.awt.*; | ||||||
|  | 
 | ||||||
|  | public class RobotsChallenge { | ||||||
|  | 
 | ||||||
|  |     private final int winThreshold = 2; | ||||||
|  | 
 | ||||||
|  |     private final int begin; | ||||||
|  | 
 | ||||||
|  |     private final int goal; | ||||||
|  | 
 | ||||||
|  |     private final DoublePowerRobot[] robots; | ||||||
|  | 
 | ||||||
|  |     public RobotsChallenge(int begin, int goal, DoublePowerRobot... robots) { | ||||||
|  |         this.goal = goal; | ||||||
|  |         this.robots = robots; | ||||||
|  |         this.begin = begin / 2; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int calculateStepsDiagonal() { | ||||||
|  |         return Math.abs(begin - goal); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int calculateStepsOverstep() { | ||||||
|  |         var diff = Math.abs(begin - goal); | ||||||
|  |         if (diff % 2 == 0) { | ||||||
|  |             return diff; | ||||||
|  |         } | ||||||
|  |         return diff+1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int calculateStepsTeleport() { | ||||||
|  |         var diff = Math.abs(begin - goal); | ||||||
|  |         if (diff % 2 == 0) { | ||||||
|  |             return diff / 2; | ||||||
|  |         } | ||||||
|  |         return (diff / 2) + 2; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int calculateSteps(MovementType type) { | ||||||
|  |         return switch (type) { | ||||||
|  |             case DIAGONAL -> calculateStepsDiagonal(); | ||||||
|  |             case OVERSTEP -> calculateStepsOverstep(); | ||||||
|  |             case TELEPORT -> calculateStepsTeleport(); | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public DoublePowerRobot[] findWinners() { | ||||||
|  |         var arr = new DoublePowerRobot[robots.length]; | ||||||
|  |         int index = 0; | ||||||
|  | 
 | ||||||
|  |         for (var r : robots) { | ||||||
|  |             if (Math.min(calculateSteps(r.getType()), calculateSteps(r.getNextType())) <= winThreshold) { | ||||||
|  |                 arr[index++] = r; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return arr; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								H03/src/main/java/h03/robots/DoublePowerRobot.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								H03/src/main/java/h03/robots/DoublePowerRobot.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | package h03.robots; | ||||||
|  | 
 | ||||||
|  | public class DoublePowerRobot extends HackingRobot { | ||||||
|  | 
 | ||||||
|  |     private MovementType[] doublePowerTypes = new MovementType[2]; | ||||||
|  | 
 | ||||||
|  |     public DoublePowerRobot(int x, int y, boolean order) { | ||||||
|  |         super(x, y, order); | ||||||
|  |         doublePowerTypes[0] = getType(); | ||||||
|  |         doublePowerTypes[1] = getNextType(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void shuffle() { | ||||||
|  |         super.shuffle(); | ||||||
|  |         doublePowerTypes[0] = getType(); | ||||||
|  |         doublePowerTypes[1] = getNextType(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean shuffle(int itNr) { | ||||||
|  |         var changed = super.shuffle(itNr); | ||||||
|  |         doublePowerTypes[0] = getType(); | ||||||
|  |         doublePowerTypes[1] = getNextType(); | ||||||
|  |         return changed; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										62
									
								
								H03/src/main/java/h03/robots/HackingRobot.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								H03/src/main/java/h03/robots/HackingRobot.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | ||||||
|  | package h03.robots; | ||||||
|  | 
 | ||||||
|  | import fopbot.Robot; | ||||||
|  | import fopbot.RobotTrace; | ||||||
|  | 
 | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.Random; | ||||||
|  | 
 | ||||||
|  | public class HackingRobot extends Robot { | ||||||
|  | 
 | ||||||
|  |     private MovementType type; | ||||||
|  | 
 | ||||||
|  |     private MovementType[] robotTypes = new MovementType[] { | ||||||
|  |         MovementType.TELEPORT, MovementType.OVERSTEP, MovementType.DIAGONAL | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public HackingRobot(int x, int y, boolean order) { | ||||||
|  |         super(x, y); | ||||||
|  | 
 | ||||||
|  |         if (order) { // right shift | ||||||
|  |             var t = robotTypes[2]; | ||||||
|  |             robotTypes[2] = robotTypes[1]; | ||||||
|  |             robotTypes[1] = robotTypes[0]; | ||||||
|  |             robotTypes[0] = t; | ||||||
|  |         } else { // left shift | ||||||
|  |             var t = robotTypes[0]; | ||||||
|  |             robotTypes[0] = robotTypes[1]; | ||||||
|  |             robotTypes[1] = robotTypes[2]; | ||||||
|  |             robotTypes[2] = t; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         type = robotTypes[0]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public MovementType getType() { | ||||||
|  |         return type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public MovementType getNextType() { | ||||||
|  |         var i = Arrays.asList(robotTypes).indexOf(type); | ||||||
|  |         i = (i + 1) % 3; | ||||||
|  |         return robotTypes[i]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getRandom(int limit) { | ||||||
|  |         return new Random().nextInt(limit); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean shuffle(int itNr) { | ||||||
|  |         var old = type; | ||||||
|  |         for (int i = 0; i < itNr; i++) { | ||||||
|  |             int index = getRandom(3); | ||||||
|  |             type = robotTypes[index]; | ||||||
|  |         } | ||||||
|  |         return type != old; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void shuffle() { | ||||||
|  |         while (!shuffle(1)); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								H03/src/main/java/h03/robots/MovementType.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								H03/src/main/java/h03/robots/MovementType.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | package h03.robots; | ||||||
|  | 
 | ||||||
|  | public enum MovementType { | ||||||
|  |     DIAGONAL, OVERSTEP, TELEPORT | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								H03/src/main/java/h03/robots/VersatileRobot.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								H03/src/main/java/h03/robots/VersatileRobot.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | package h03.robots; | ||||||
|  | 
 | ||||||
|  | public class VersatileRobot extends HackingRobot { | ||||||
|  | 
 | ||||||
|  |     public VersatileRobot(int x, int y, boolean order, boolean exchange) { | ||||||
|  |         super(x, y, order); | ||||||
|  | 
 | ||||||
|  |         if (exchange) { | ||||||
|  |             setField(y, x); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (getType() == MovementType.DIAGONAL) { | ||||||
|  |             setY(getX()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean shuffle(int itNr) { | ||||||
|  |         var changed = super.shuffle(itNr); | ||||||
|  | 
 | ||||||
|  |         if (getType() == MovementType.DIAGONAL) { | ||||||
|  |             setY(getX()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return changed; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void shuffle() { | ||||||
|  |         super.shuffle(); | ||||||
|  | 
 | ||||||
|  |         if (getType() == MovementType.DIAGONAL) { | ||||||
|  |             setY(getX()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,9 +1,12 @@ | ||||||
| package h04; | package h04; | ||||||
| 
 | 
 | ||||||
|  | import fopbot.Robot; | ||||||
| import h04.template.ChessUtils; | import h04.template.ChessUtils; | ||||||
| import h04.template.GameControllerTemplate; | import h04.template.GameControllerTemplate; | ||||||
| import h04.chesspieces.King; | import h04.chesspieces.King; | ||||||
| 
 | 
 | ||||||
|  | import java.util.stream.Stream; | ||||||
|  | 
 | ||||||
| public class GameController extends GameControllerTemplate { | public class GameController extends GameControllerTemplate { | ||||||
|     public GameController() { |     public GameController() { | ||||||
|         super(); |         super(); | ||||||
|  | @ -13,6 +16,7 @@ public class GameController extends GameControllerTemplate { | ||||||
|     @Override |     @Override | ||||||
|     public boolean checkWinCondition() { |     public boolean checkWinCondition() { | ||||||
|         //TODO H4.1 |         //TODO H4.1 | ||||||
|         return false; |         var kings = ChessUtils.getKings(); | ||||||
|  |         return Stream.of(kings).anyMatch(Robot::isTurnedOff); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,13 +1,15 @@ | ||||||
| package h04.chesspieces; | package h04.chesspieces; | ||||||
| 
 | 
 | ||||||
| import fopbot.Robot; | import fopbot.Robot; | ||||||
|  | import h04.movement.DiagonalMover; | ||||||
|  | import h04.movement.MoveStrategy; | ||||||
| //Wichtig für Implementation | //Wichtig für Implementation | ||||||
| //import h04.movement.MoveStrategy; | //import h04.movement.MoveStrategy; | ||||||
| 
 | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| public class Bishop extends Robot { | public class Bishop extends Robot implements DiagonalMover { | ||||||
| 
 | 
 | ||||||
|     private final Team team; |     private final Team team; | ||||||
| 
 | 
 | ||||||
|  | @ -21,4 +23,13 @@ public class Bishop extends Robot { | ||||||
|     public Team getTeam() { return team;} |     public Team getTeam() { return team;} | ||||||
| 
 | 
 | ||||||
|     //TODO H4.5 |     //TODO H4.5 | ||||||
|  |     @Override | ||||||
|  |     public void moveStrategy(int dx, int dy, MoveStrategy strategy) { | ||||||
|  |         strategy.move(this, dx, dy); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Point[] getPossibleMoveFields() { | ||||||
|  |         return getDiagonalMoves(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ package h04.chesspieces; | ||||||
| //Wichtig für Implementation | //Wichtig für Implementation | ||||||
| //import h04.movement.MoveStrategy; | //import h04.movement.MoveStrategy; | ||||||
| 
 | 
 | ||||||
|  | import h04.movement.MoveStrategy; | ||||||
|  | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
| 
 | 
 | ||||||
| public interface ChessPiece { | public interface ChessPiece { | ||||||
|  | @ -17,4 +19,7 @@ public interface ChessPiece { | ||||||
|     void turnOff(); |     void turnOff(); | ||||||
| 
 | 
 | ||||||
|     //TODO H4.3 |     //TODO H4.3 | ||||||
|  |     void moveStrategy(int dx, int dy, MoveStrategy strategy); | ||||||
|  | 
 | ||||||
|  |     Point[] getPossibleMoveFields(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,9 +3,12 @@ package h04.chesspieces; | ||||||
| import fopbot.Robot; | import fopbot.Robot; | ||||||
| //Wichtig für Implementation | //Wichtig für Implementation | ||||||
| //import h04.movement.MoveStrategy; | //import h04.movement.MoveStrategy; | ||||||
|  | import fopbot.World; | ||||||
|  | import h04.movement.MoveStrategy; | ||||||
| import h04.template.ChessUtils; | import h04.template.ChessUtils; | ||||||
| 
 | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
|  | import java.util.ArrayList; | ||||||
| 
 | 
 | ||||||
| public class King extends Robot implements ChessPiece { | public class King extends Robot implements ChessPiece { | ||||||
| 
 | 
 | ||||||
|  | @ -22,4 +25,79 @@ public class King extends Robot implements ChessPiece { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //TODO H4.4 |     //TODO H4.4 | ||||||
|  |     @Override | ||||||
|  |     public void moveStrategy(int dx, int dy, MoveStrategy strategy) { | ||||||
|  |         strategy.move(this, dx, dy); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Point[] getPossibleMoveFields() { | ||||||
|  |         var list = new ArrayList<Point>(); | ||||||
|  | 
 | ||||||
|  |         if (getX() > 0) { | ||||||
|  |             if (getY() > 0) { | ||||||
|  |                 var target = new Point(getX()-1, getY()-1); | ||||||
|  |                 var r = ChessUtils.getPieceAt(target); | ||||||
|  |                 if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                     list.add(target); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var target = new Point(getX()-1, getY()); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (getY() < World.getHeight()-1) { | ||||||
|  |                 target = new Point(getX()-1, getY()+1); | ||||||
|  |                 r = ChessUtils.getPieceAt(target); | ||||||
|  |                 if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                     list.add(target); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (getY() > 0) { | ||||||
|  |             var target = new Point(getX(), getY()-1); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (getY() < World.getHeight()-1) { | ||||||
|  |             var target = new Point(getX(), getY()+1); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (getX() < World.getWidth()-1) { | ||||||
|  |             if (getY() > 0) { | ||||||
|  |                 var target = new Point(getX()+1, getY()-1); | ||||||
|  |                 var r = ChessUtils.getPieceAt(target); | ||||||
|  |                 if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                     list.add(target); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var target = new Point(getX()+1, getY()); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (getY() < World.getHeight()-1) { | ||||||
|  |                 target = new Point(getX()+1, getY()+1); | ||||||
|  |                 r = ChessUtils.getPieceAt(target); | ||||||
|  |                 if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                     list.add(target); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return list.toArray(Point[]::new); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package h04.chesspieces; | ||||||
| import fopbot.Robot; | import fopbot.Robot; | ||||||
| //Wichtig für Implementation | //Wichtig für Implementation | ||||||
| //import h04.movement.MoveStrategy; | //import h04.movement.MoveStrategy; | ||||||
|  | import h04.movement.MoveStrategy; | ||||||
| import h04.template.ChessUtils; | import h04.template.ChessUtils; | ||||||
| 
 | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
|  | @ -21,14 +22,12 @@ public class Knight extends Robot implements ChessPiece { | ||||||
|         return team; |         return team; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //Wichtig für Implementation |  | ||||||
|     /* |  | ||||||
|     @Override |     @Override | ||||||
|     public void moveStrategy(final int dx, final int dy, final MoveStrategy strategy) { |     public void moveStrategy(final int dx, final int dy, final MoveStrategy strategy) { | ||||||
|         strategy.move(this, dx, dy); |         strategy.move(this, dx, dy); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     */ |  | ||||||
|     public Point[] getPossibleMoveFields() { |     public Point[] getPossibleMoveFields() { | ||||||
|         final Point[] possibleMoves = new Point[8]; |         final Point[] possibleMoves = new Point[8]; | ||||||
|         int index = 0; |         int index = 0; | ||||||
|  |  | ||||||
|  | @ -1,8 +1,7 @@ | ||||||
| package h04.chesspieces; | package h04.chesspieces; | ||||||
| 
 | 
 | ||||||
| import fopbot.Robot; | import fopbot.Robot; | ||||||
| //Wichtig für Implementation | import h04.movement.MoveStrategy; | ||||||
| //import h04.movement.MoveStrategy; |  | ||||||
| 
 | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
| 
 | 
 | ||||||
|  | @ -24,15 +23,13 @@ public class Pawn extends Robot implements ChessPiece { | ||||||
|         return team; |         return team; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //Wichtig für Implementation |  | ||||||
|     /* |  | ||||||
|     @Override |     @Override | ||||||
|     public void moveStrategy(final int dx, final int dy, final MoveStrategy strategy) { |     public void moveStrategy(final int dx, final int dy, final MoveStrategy strategy) { | ||||||
|         strategy.move(this, dx, dy); |         strategy.move(this, dx, dy); | ||||||
|         firstMove = false; |         firstMove = false; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     */ |  | ||||||
|     public Point[] getPossibleMoveFields() { |     public Point[] getPossibleMoveFields() { | ||||||
|         final Point[] possibleMoves = new Point[4]; |         final Point[] possibleMoves = new Point[4]; | ||||||
|         int index = 0; |         int index = 0; | ||||||
|  |  | ||||||
|  | @ -3,11 +3,15 @@ package h04.chesspieces; | ||||||
| import fopbot.Robot; | import fopbot.Robot; | ||||||
| //Wichtig für Implementation | //Wichtig für Implementation | ||||||
| //import h04.movement.MoveStrategy; | //import h04.movement.MoveStrategy; | ||||||
|  | import h04.movement.DiagonalMover; | ||||||
|  | import h04.movement.MoveStrategy; | ||||||
|  | import h04.movement.OrthogonalMover; | ||||||
| import h04.template.ChessUtils; | import h04.template.ChessUtils; | ||||||
| 
 | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
|  | import java.util.stream.Stream; | ||||||
| 
 | 
 | ||||||
| public class Queen extends Robot { | public class Queen extends Robot implements OrthogonalMover, DiagonalMover { | ||||||
|     private final Team team; |     private final Team team; | ||||||
| 
 | 
 | ||||||
|     public Queen(final int x, final int y, final Team team) { |     public Queen(final int x, final int y, final Team team) { | ||||||
|  | @ -22,4 +26,15 @@ public class Queen extends Robot { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //TODO H4.6 |     //TODO H4.6 | ||||||
|  |     @Override | ||||||
|  |     public void moveStrategy(int dx, int dy, MoveStrategy strategy) { | ||||||
|  |         strategy.move(this, dx, dy); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Point[] getPossibleMoveFields() { | ||||||
|  |         return Stream.of(getOrthogonalMoves(), getDiagonalMoves()) | ||||||
|  |             .flatMap(Stream::of) | ||||||
|  |             .toArray(Point[]::new); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,11 +3,13 @@ package h04.chesspieces; | ||||||
| import fopbot.Robot; | import fopbot.Robot; | ||||||
| //Wichtig für Implementation | //Wichtig für Implementation | ||||||
| //import h04.movement.MoveStrategy; | //import h04.movement.MoveStrategy; | ||||||
|  | import h04.movement.MoveStrategy; | ||||||
|  | import h04.movement.OrthogonalMover; | ||||||
| import h04.template.ChessUtils; | import h04.template.ChessUtils; | ||||||
| 
 | 
 | ||||||
| import java.awt.Point; | import java.awt.Point; | ||||||
| 
 | 
 | ||||||
| public class Rook extends Robot { | public class Rook extends Robot implements OrthogonalMover { | ||||||
|     private final Team team; |     private final Team team; | ||||||
| 
 | 
 | ||||||
|     public Rook(final int x, final int y, final Team team){ |     public Rook(final int x, final int y, final Team team){ | ||||||
|  | @ -22,4 +24,13 @@ public class Rook extends Robot { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //TODO H4.5 |     //TODO H4.5 | ||||||
|  |     @Override | ||||||
|  |     public void moveStrategy(int dx, int dy, MoveStrategy strategy) { | ||||||
|  |         strategy.move(this, dx, dy); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Point[] getPossibleMoveFields() { | ||||||
|  |         return getOrthogonalMoves(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										53
									
								
								H04/src/main/java/h04/movement/DiagonalMover.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								H04/src/main/java/h04/movement/DiagonalMover.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | package h04.movement; | ||||||
|  | 
 | ||||||
|  | import fopbot.World; | ||||||
|  | import h04.chesspieces.ChessPiece; | ||||||
|  | import h04.template.ChessUtils; | ||||||
|  | 
 | ||||||
|  | import java.awt.*; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | 
 | ||||||
|  | public interface DiagonalMover extends ChessPiece { | ||||||
|  | 
 | ||||||
|  |     default Point[] getDiagonalMoves() { | ||||||
|  |         var list = new ArrayList<Point>(); | ||||||
|  | 
 | ||||||
|  |         for (int i = 1; getX()-i >= 0 && getY()-i >= 0; i++) { | ||||||
|  |             var target = new Point(getX()-i, getY()-i); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = 1; getX()+i < World.getWidth() && getY()-i >= 0; i++) { | ||||||
|  |             var target = new Point(getX()+i, getY()-i); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = 1; getX()-i >= 0 && getY()+i < World.getHeight(); i++) { | ||||||
|  |             var target = new Point(getX()-i, getY()+i); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = 1; getX()+i < World.getWidth() && getY()+i < World.getHeight(); i++) { | ||||||
|  |             var target = new Point(getX()+i, getY()+i); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return list.toArray(Point[]::new); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								H04/src/main/java/h04/movement/MoveStrategy.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								H04/src/main/java/h04/movement/MoveStrategy.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | package h04.movement; | ||||||
|  | 
 | ||||||
|  | import fopbot.Robot; | ||||||
|  | 
 | ||||||
|  | public interface MoveStrategy { | ||||||
|  | 
 | ||||||
|  |     void move(Robot robot, int dx, int dy); | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								H04/src/main/java/h04/movement/OrthogonalMover.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								H04/src/main/java/h04/movement/OrthogonalMover.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | package h04.movement; | ||||||
|  | 
 | ||||||
|  | import fopbot.World; | ||||||
|  | import h04.chesspieces.ChessPiece; | ||||||
|  | import h04.template.ChessUtils; | ||||||
|  | 
 | ||||||
|  | import java.awt.Point; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | 
 | ||||||
|  | public interface OrthogonalMover extends ChessPiece { | ||||||
|  | 
 | ||||||
|  |     default Point[] getOrthogonalMoves() { | ||||||
|  |         var list = new ArrayList<Point>(); | ||||||
|  | 
 | ||||||
|  |         for (int i = getX()-1; i >= 0; i--) { | ||||||
|  |             var target = new Point(i, getY()); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = getX()+1; i < World.getWidth(); i++) { | ||||||
|  |             var target = new Point(i, getY()); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = getY()-1; i >= 0; i--) { | ||||||
|  |             var target = new Point(getX(), i); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = getY()+1; i < World.getHeight(); i++) { | ||||||
|  |             var target = new Point(getX(), i); | ||||||
|  |             var r = ChessUtils.getPieceAt(target); | ||||||
|  |             if (r == null || r.getTeam() != getTeam()) { | ||||||
|  |                 list.add(target); | ||||||
|  |             } | ||||||
|  |             if (r != null) break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return list.toArray(Point[]::new); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								H04/src/main/java/h04/movement/TeleportingMoveStrategy.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								H04/src/main/java/h04/movement/TeleportingMoveStrategy.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | package h04.movement; | ||||||
|  | 
 | ||||||
|  | import fopbot.Robot; | ||||||
|  | 
 | ||||||
|  | public class TeleportingMoveStrategy implements MoveStrategy { | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void move(Robot robot, int dx, int dy) { | ||||||
|  |         robot.setField(robot.getX()+dx, robot.getY()+dy); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								H04/src/main/java/h04/movement/WalkingMoveStrategy.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								H04/src/main/java/h04/movement/WalkingMoveStrategy.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | package h04.movement; | ||||||
|  | 
 | ||||||
|  | import fopbot.Direction; | ||||||
|  | import fopbot.Robot; | ||||||
|  | 
 | ||||||
|  | public class WalkingMoveStrategy implements MoveStrategy { | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void move(Robot robot, int dx, int dy) { | ||||||
|  |         if (dx < 0) { | ||||||
|  |             turnFacing(robot, Direction.LEFT); | ||||||
|  |         } | ||||||
|  |         if (dx > 0) { | ||||||
|  |             turnFacing(robot, Direction.RIGHT); | ||||||
|  |         } | ||||||
|  |         dx = Math.abs(dx); | ||||||
|  |         while (dx --> 0) { | ||||||
|  |             robot.move(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (dy < 0) { | ||||||
|  |             turnFacing(robot, Direction.DOWN); | ||||||
|  |         } | ||||||
|  |         if (dy > 0) { | ||||||
|  |             turnFacing(robot, Direction.UP); | ||||||
|  |         } | ||||||
|  |         dy = Math.abs(dy); | ||||||
|  |         while (dy --> 0) { | ||||||
|  |             robot.move(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         turnFacing(robot, Direction.UP); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void turnFacing(Robot robot, Direction dir) { | ||||||
|  |         while (robot.getDirection() != dir) { | ||||||
|  |             robot.turnLeft(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -13,12 +13,9 @@ import h04.chesspieces.Pawn; | ||||||
| import h04.chesspieces.Queen; | import h04.chesspieces.Queen; | ||||||
| import h04.chesspieces.Rook; | import h04.chesspieces.Rook; | ||||||
| import h04.chesspieces.Team; | import h04.chesspieces.Team; | ||||||
| //Wichtig für Implementation | import h04.movement.MoveStrategy; | ||||||
| //import h04.movement.MoveStrategy; | import h04.movement.TeleportingMoveStrategy; | ||||||
| //Wichtig für Implementation | import h04.movement.WalkingMoveStrategy; | ||||||
| //import h04.movement.TeleportingMoveStrategy; |  | ||||||
| //Wichtig für Implementation |  | ||||||
| //import h04.movement.WalkingMoveStrategy; |  | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
| import org.tudalgo.algoutils.student.io.PropertyUtils; | import org.tudalgo.algoutils.student.io.PropertyUtils; | ||||||
| 
 | 
 | ||||||
|  | @ -45,13 +42,10 @@ public abstract class GameControllerTemplate { | ||||||
| 
 | 
 | ||||||
|     protected @Nullable ChessPiece selectedPiece; |     protected @Nullable ChessPiece selectedPiece; | ||||||
| 
 | 
 | ||||||
|     //Wichtig für Implementation |  | ||||||
|     /* |  | ||||||
|     protected MoveStrategy moveStrategy = PropertyUtils.getBooleanProperty( |     protected MoveStrategy moveStrategy = PropertyUtils.getBooleanProperty( | ||||||
|         "h04.properties", |         "h04.properties", | ||||||
|         "USE_TELEPORT_MOVE_STRATEGY" |         "USE_TELEPORT_MOVE_STRATEGY" | ||||||
|     ) ? new TeleportingMoveStrategy() : new WalkingMoveStrategy(); |     ) ? new TeleportingMoveStrategy() : new WalkingMoveStrategy(); | ||||||
|     */ |  | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Starts the game loop. |      * Starts the game loop. | ||||||
|  | @ -62,8 +56,6 @@ public abstract class GameControllerTemplate { | ||||||
|         while (!gameOver) { |         while (!gameOver) { | ||||||
|             final var point = inputHandler.getNextInput(nextToMove); |             final var point = inputHandler.getNextInput(nextToMove); | ||||||
| 
 | 
 | ||||||
|             //Wichtig für Implementation |  | ||||||
|             /* |  | ||||||
|             if (ChessUtils.getTeamAt(point) == nextToMove) { |             if (ChessUtils.getTeamAt(point) == nextToMove) { | ||||||
|                 // select piece |                 // select piece | ||||||
|                 selectedPiece = ChessUtils.getPieceAt(point); |                 selectedPiece = ChessUtils.getPieceAt(point); | ||||||
|  | @ -107,7 +99,6 @@ public abstract class GameControllerTemplate { | ||||||
|                 nextToMove = nextToMove.getOpponent(); |                 nextToMove = nextToMove.getOpponent(); | ||||||
|                 selectedPiece = null; |                 selectedPiece = null; | ||||||
|             } |             } | ||||||
|             */ |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ public class Airspace { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO: H5.1.1 - Uncomment the following lines |     // TODO: H5.1.1 - Uncomment the following lines | ||||||
|     /* private final Set<Flying> flyingInAirspace = new HashSet<>(); |     private final Set<Flying> flyingInAirspace = new HashSet<>(); | ||||||
| 
 | 
 | ||||||
|     private Airspace(){ |     private Airspace(){ | ||||||
| 
 | 
 | ||||||
|  | @ -28,9 +28,27 @@ public class Airspace { | ||||||
| 
 | 
 | ||||||
|     void deregister(Flying flying){ |     void deregister(Flying flying){ | ||||||
|         flyingInAirspace.remove(flying); |         flyingInAirspace.remove(flying); | ||||||
|     } */ |     } | ||||||
| 
 | 
 | ||||||
|     void scanAirspace() { |     void scanAirspace() { | ||||||
|         // TODO: H5.5 |         // TODO: H5.5 | ||||||
|  |         System.out.println("Scanning..."); | ||||||
|  | 
 | ||||||
|  |         if (flyingInAirspace.isEmpty()) { | ||||||
|  |             System.out.println("Airspace is empty"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (var f : flyingInAirspace) { | ||||||
|  |             if (f instanceof CarriesPassengers cp) { | ||||||
|  |                 System.out.printf("%s is flying in airspace (%d PAX).\n", f.getIdentifier(), cp.getPassengerCount()); | ||||||
|  |             } else { | ||||||
|  |                 System.out.printf("%s is flying in airspace.\n", f.getIdentifier()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<Flying> getFlyingInAirspace() { | ||||||
|  |         return flyingInAirspace; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								H05/src/main/java/h05/CargoPlane.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								H05/src/main/java/h05/CargoPlane.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public class CargoPlane extends Plane implements CarriesCargo { | ||||||
|  | 
 | ||||||
|  |     private final CargoStack containers = new CargoStack(); | ||||||
|  | 
 | ||||||
|  |     public CargoPlane(String aircraftRegistration, int baseWeight, FuelType fuelType, double fuelCapacity) { | ||||||
|  |         super(aircraftRegistration, baseWeight, fuelType, fuelCapacity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void loadContainer(int cargoWeight) { | ||||||
|  |         containers.push(cargoWeight); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean hasFreightLoaded() { | ||||||
|  |         return !containers.empty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int unloadNextContainer() { | ||||||
|  |         return containers.pop(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected double mass() { | ||||||
|  |         return getBaseWeight() + containers.getSum(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								H05/src/main/java/h05/CarriesCargo.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								H05/src/main/java/h05/CarriesCargo.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public interface CarriesCargo { | ||||||
|  | 
 | ||||||
|  |     void loadContainer(int cargoWeight); | ||||||
|  | 
 | ||||||
|  |     boolean hasFreightLoaded(); | ||||||
|  | 
 | ||||||
|  |     int unloadNextContainer(); | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								H05/src/main/java/h05/CarriesPassengers.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								H05/src/main/java/h05/CarriesPassengers.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public interface CarriesPassengers { | ||||||
|  | 
 | ||||||
|  |     void board(int passengers); | ||||||
|  | 
 | ||||||
|  |     void disembark(); | ||||||
|  | 
 | ||||||
|  |     int getPassengerCount(); | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								H05/src/main/java/h05/CombinedPlane.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								H05/src/main/java/h05/CombinedPlane.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public class CombinedPlane extends Plane implements CarriesCargo, CarriesPassengers{ | ||||||
|  | 
 | ||||||
|  |     protected static final char AVERAGE_PEOPLE_WEIGHT = 100; | ||||||
|  |     protected static final char AVERAGE_LUGGAGE_WEIGHT = 15; | ||||||
|  | 
 | ||||||
|  |     private final int crewCount; | ||||||
|  | 
 | ||||||
|  |     private int passengerCount = 0; | ||||||
|  | 
 | ||||||
|  |     public CombinedPlane(String aircraftRegistration, int baseWeight, FuelType fuelType, double fuelCapacity, int crewCount) { | ||||||
|  |         super(aircraftRegistration, baseWeight, fuelType, fuelCapacity); | ||||||
|  |         this.crewCount = crewCount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected double mass() { | ||||||
|  |         return containers.getSum() + getBaseWeight() + passengerCount * AVERAGE_LUGGAGE_WEIGHT + passengerCount * AVERAGE_PEOPLE_WEIGHT + crewCount * AVERAGE_PEOPLE_WEIGHT; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void board(int passengers) { | ||||||
|  |         passengerCount += passengers; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void disembark() { | ||||||
|  |         passengerCount = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getPassengerCount() { | ||||||
|  |         return passengerCount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private final CargoStack containers = new CargoStack(); | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void loadContainer(int cargoWeight) { | ||||||
|  |         containers.push(cargoWeight); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean hasFreightLoaded() { | ||||||
|  |         return !containers.empty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int unloadNextContainer() { | ||||||
|  |         return containers.pop(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								H05/src/main/java/h05/Flying.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								H05/src/main/java/h05/Flying.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public interface Flying { | ||||||
|  | 
 | ||||||
|  |     String getIdentifier(); | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								H05/src/main/java/h05/FuelType.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								H05/src/main/java/h05/FuelType.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public enum FuelType { | ||||||
|  |     AvGas(0.99), | ||||||
|  |     Biokerosin(1.02), | ||||||
|  |     JetA(1.0), | ||||||
|  |     JetB(1.2); | ||||||
|  | 
 | ||||||
|  |     private final double consumptionMultiplicator; | ||||||
|  | 
 | ||||||
|  |     FuelType(double consumptionMultiplicator) { | ||||||
|  |         this.consumptionMultiplicator = consumptionMultiplicator; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public double getConsumptionMultiplicator() { | ||||||
|  |         return consumptionMultiplicator; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -11,5 +11,50 @@ public class Main { | ||||||
|      */ |      */ | ||||||
|     public static void main(String[] args) { |     public static void main(String[] args) { | ||||||
|         // TODO: H5.6 |         // TODO: H5.6 | ||||||
|  |         Airspace.get().scanAirspace(); | ||||||
|  | 
 | ||||||
|  |         var longRunway = new Runway(4000); | ||||||
|  | 
 | ||||||
|  |         var shortRunway = new Runway(2000); | ||||||
|  | 
 | ||||||
|  |         var balloon = new WeatherBalloon(99); | ||||||
|  |         balloon.start(); | ||||||
|  | 
 | ||||||
|  |         var tankA = new Tank(FuelType.JetA); | ||||||
|  | 
 | ||||||
|  |         var tankB = new Tank(FuelType.JetB); | ||||||
|  | 
 | ||||||
|  |         var tankerPlane = new TankerPlane("D-ABCD", 10000, FuelType.JetA, 1000); | ||||||
|  |         tankerPlane.loadFuel(FuelType.AvGas, 100000); | ||||||
|  |         tankerPlane.takeOff(); | ||||||
|  | 
 | ||||||
|  |         var passangerPlane = new PassengerPlane("GAG-67", 10000, FuelType.JetA, 1700, 5); | ||||||
|  |         tankA.refuelPlane(passangerPlane); | ||||||
|  |         passangerPlane.board(100); | ||||||
|  |         passangerPlane.takeOff(); | ||||||
|  | 
 | ||||||
|  |         Airspace.get().scanAirspace(); | ||||||
|  | 
 | ||||||
|  |         var cargoPlane = new CargoPlane("D-AFFF", 8000, FuelType.JetB, 1500); | ||||||
|  |         cargoPlane.loadContainer(1000); | ||||||
|  |         tankB.refuelPlane(cargoPlane); | ||||||
|  | 
 | ||||||
|  |         var combinedPlane = new CombinedPlane("D-ABBB", 9000, FuelType.AvGas, 10700, 5); | ||||||
|  |         tankerPlane.refuelPlane(combinedPlane); | ||||||
|  |         combinedPlane.board(30); | ||||||
|  |         combinedPlane.loadContainer(400); | ||||||
|  |         combinedPlane.takeOff(); | ||||||
|  |         combinedPlane.fly(3000); | ||||||
|  | 
 | ||||||
|  |         Airspace.get().scanAirspace(); | ||||||
|  | 
 | ||||||
|  |         shortRunway.land(combinedPlane); | ||||||
|  |         longRunway.land(cargoPlane); | ||||||
|  | 
 | ||||||
|  |         Airspace.get().scanAirspace(); | ||||||
|  | 
 | ||||||
|  |         balloon.pop(); | ||||||
|  | 
 | ||||||
|  |         Airspace.get().scanAirspace(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								H05/src/main/java/h05/PassengerPlane.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								H05/src/main/java/h05/PassengerPlane.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public class PassengerPlane extends Plane implements CarriesPassengers { | ||||||
|  | 
 | ||||||
|  |     protected static final char AVERAGE_PEOPLE_WEIGHT = 100; | ||||||
|  |     protected static final char AVERAGE_LUGGAGE_WEIGHT = 15; | ||||||
|  | 
 | ||||||
|  |     private final int crewCount; | ||||||
|  | 
 | ||||||
|  |     private int passengerCount = 0; | ||||||
|  | 
 | ||||||
|  |     public PassengerPlane(String aircraftRegistration, int baseWeight, FuelType fuelType, double fuelCapacity, int crewCount) { | ||||||
|  |         super(aircraftRegistration, baseWeight, fuelType, fuelCapacity); | ||||||
|  |         this.crewCount = crewCount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected double mass() { | ||||||
|  |         return getBaseWeight() + passengerCount * AVERAGE_LUGGAGE_WEIGHT + passengerCount * AVERAGE_PEOPLE_WEIGHT + crewCount * AVERAGE_PEOPLE_WEIGHT; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void board(int passengers) { | ||||||
|  |         passengerCount += passengers; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void disembark() { | ||||||
|  |         passengerCount = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getPassengerCount() { | ||||||
|  |         return passengerCount; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								H05/src/main/java/h05/Plane.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								H05/src/main/java/h05/Plane.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public abstract class Plane implements Flying { | ||||||
|  | 
 | ||||||
|  |     private static final double CONSUMPTION_PER_KM_KG = 1.1494e-4; | ||||||
|  | 
 | ||||||
|  |     private final String aircraftRegistration; | ||||||
|  | 
 | ||||||
|  |     private final int baseWeight; | ||||||
|  | 
 | ||||||
|  |     private final FuelType fuelType; | ||||||
|  | 
 | ||||||
|  |     private final double fuelCapacity; | ||||||
|  | 
 | ||||||
|  |     private double currentFuelLevel; | ||||||
|  | 
 | ||||||
|  |     public Plane(String aircraftRegistration, int baseWeight, FuelType fuelType, double fuelCapacity) { | ||||||
|  |         this.aircraftRegistration = aircraftRegistration; | ||||||
|  |         this.baseWeight = baseWeight; | ||||||
|  |         this.fuelType = fuelType; | ||||||
|  |         this.fuelCapacity = fuelCapacity; | ||||||
|  |         this.currentFuelLevel = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getIdentifier() { | ||||||
|  |         return aircraftRegistration; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public double getCurrentFuelLevel() { | ||||||
|  |         return currentFuelLevel; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public double getFuelCapacity() { | ||||||
|  |         return fuelCapacity; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public FuelType getFuelType() { | ||||||
|  |         return fuelType; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getBaseWeight() { | ||||||
|  |         return baseWeight; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void refuel(double amount) { | ||||||
|  |         if (currentFuelLevel + amount > fuelCapacity) { | ||||||
|  |             System.out.printf("The Tank of Plane %s has overflowed!\n", aircraftRegistration); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         currentFuelLevel += amount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected abstract double mass(); | ||||||
|  | 
 | ||||||
|  |     protected double getFuelConsumptionPerKilometer() { | ||||||
|  |         return CONSUMPTION_PER_KM_KG * fuelType.getConsumptionMultiplicator() * mass(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void fly(double distance) { | ||||||
|  |         var fuelNeeded = getFuelConsumptionPerKilometer() * distance; | ||||||
|  | 
 | ||||||
|  |         if (currentFuelLevel < fuelNeeded) { | ||||||
|  |             System.out.printf("Plane %s does not have enough fuel to fly %f km.", aircraftRegistration, distance / 100000); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         currentFuelLevel -= fuelNeeded; | ||||||
|  |         System.out.printf("Plane %s flew %s km and has %s liters of fuel left.", aircraftRegistration, distance, currentFuelLevel); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void takeOff() { | ||||||
|  |         Airspace.get().register(this); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void land() { | ||||||
|  |         Airspace.get().deregister(this); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								H05/src/main/java/h05/Refuelling.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								H05/src/main/java/h05/Refuelling.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public interface Refuelling { | ||||||
|  | 
 | ||||||
|  |     void refuelPlane(Plane plane); | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								H05/src/main/java/h05/Runway.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								H05/src/main/java/h05/Runway.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public class Runway { | ||||||
|  | 
 | ||||||
|  |     private final int runwayLength; | ||||||
|  | 
 | ||||||
|  |     public Runway(int runwayLength) { | ||||||
|  |         this.runwayLength = runwayLength; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getRunwayLength() { | ||||||
|  |         return runwayLength; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static double calculateLandingDistance(double mass) { | ||||||
|  |         return mass / 40; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean canLand(Plane plane) { | ||||||
|  |         return runwayLength >= calculateLandingDistance(plane.mass()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void land(Plane plane) { | ||||||
|  |         if (canLand(plane)) { | ||||||
|  |             plane.land(); | ||||||
|  |             System.out.printf("Plane %s has landed successfully.\n", plane.getIdentifier()); | ||||||
|  |         } else { | ||||||
|  |             System.out.printf("Plane %s could not land. The runway is too short.\n", plane.getIdentifier()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								H05/src/main/java/h05/Tank.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								H05/src/main/java/h05/Tank.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | public class Tank implements Refuelling { | ||||||
|  | 
 | ||||||
|  |     private final FuelType fuelType; | ||||||
|  | 
 | ||||||
|  |     public Tank(FuelType fuelType) { | ||||||
|  |         this.fuelType = fuelType; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void refuelPlane(Plane plane) { | ||||||
|  |         if (plane.getFuelType() != fuelType) { | ||||||
|  |             System.out.println("Hat nicht geklappt >:("); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         plane.refuel(plane.getFuelCapacity() - plane.getCurrentFuelLevel()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								H05/src/main/java/h05/TankerPlane.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								H05/src/main/java/h05/TankerPlane.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | import java.util.stream.DoubleStream; | ||||||
|  | 
 | ||||||
|  | public class TankerPlane extends Plane implements Refuelling { | ||||||
|  | 
 | ||||||
|  |     private final double[] availableAmount = new double[FuelType.values().length]; | ||||||
|  | 
 | ||||||
|  |     public TankerPlane(String aircraftRegistration, int baseWeight, FuelType fuelType, double fuelCapacity) { | ||||||
|  |         super(aircraftRegistration, baseWeight, fuelType, fuelCapacity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected double mass() { | ||||||
|  |         return getBaseWeight() + DoubleStream.of(availableAmount).sum(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void refuelPlane(Plane plane) { | ||||||
|  |         var diff = plane.getFuelCapacity() - plane.getCurrentFuelLevel(); | ||||||
|  |         var avail = availableAmount[plane.getFuelType().ordinal()]; | ||||||
|  | 
 | ||||||
|  |         if (diff > avail) { | ||||||
|  |             System.out.println("auawuduiwahduihdauwihdw"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         plane.refuel(diff); | ||||||
|  |         availableAmount[plane.getFuelType().ordinal()] -= diff; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void loadFuel(FuelType type, double amount) { | ||||||
|  |         availableAmount[type.ordinal()] = amount; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								H05/src/main/java/h05/WeatherBalloon.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								H05/src/main/java/h05/WeatherBalloon.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | package h05; | ||||||
|  | 
 | ||||||
|  | import kotlin.Pair; | ||||||
|  | 
 | ||||||
|  | public class WeatherBalloon implements Flying { | ||||||
|  | 
 | ||||||
|  |     private final int balloonNumber; | ||||||
|  | 
 | ||||||
|  |     public WeatherBalloon(int balloonNumber) { | ||||||
|  |         this.balloonNumber = balloonNumber; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getIdentifier() { | ||||||
|  |         return "WeatherBalloon " + balloonNumber; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void start() { | ||||||
|  |         Airspace.get().register(this); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void pop() { | ||||||
|  |         Airspace.get().deregister(this); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,66 +0,0 @@ | ||||||
| package h07; |  | ||||||
| 
 |  | ||||||
| import org.tudalgo.algoutils.student.annotation.DoNotTouch; |  | ||||||
| import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; |  | ||||||
| 
 |  | ||||||
| import h07.peano.NaturalNumber; |  | ||||||
| import h07.peano.Successor; |  | ||||||
| import h07.peano.Zero; |  | ||||||
| 
 |  | ||||||
| import static org.tudalgo.algoutils.student.Student.crash; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Main entry point in executing the program. |  | ||||||
|  */ |  | ||||||
| public class Main { |  | ||||||
|     /** |  | ||||||
|      * Main entry point in executing the program. |  | ||||||
|      * |  | ||||||
|      * @param args program arguments, currently ignored |  | ||||||
|      */ |  | ||||||
|     public static void main(String[] args) { |  | ||||||
|         testHeader("Multiplication Table"); |  | ||||||
|         numberExpressionMultiplicationTableTests(); |  | ||||||
| 
 |  | ||||||
|         testHeader("Peano Number Expressions"); |  | ||||||
|         peanoNumberExpressionTests(); |  | ||||||
| 
 |  | ||||||
|         testHeader("Filter, Fold, Map"); |  | ||||||
|         filterFoldMapTests(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @DoNotTouch |  | ||||||
|     private static void testHeader(String testName) { |  | ||||||
|         System.out.println("-----------------------------------"); |  | ||||||
|         System.out.println("Running test: " + testName); |  | ||||||
|         System.out.println("-----------------------------------"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @DoNotTouch |  | ||||||
|     private static void numberExpressionMultiplicationTableTests() { |  | ||||||
|         // TODO: H2.2 - uncomment to test |  | ||||||
| //        int lowerBound = 1; |  | ||||||
| //        int upperBound = 10; |  | ||||||
| //        NumberExpression[] multiplicationTable = NumberExpressionFactory.multiplicationTable(lowerBound, upperBound); |  | ||||||
| // |  | ||||||
| //        for (int i = lowerBound; i <= upperBound; i++) { |  | ||||||
| //            for (int j = lowerBound; j <= upperBound; j++) { |  | ||||||
| //                System.out.printf("| %4s ", multiplicationTable[(i - lowerBound) * (upperBound - lowerBound + 1) + (j - lowerBound)].evaluate()); |  | ||||||
| //            } |  | ||||||
| //            System.out.println("|"); |  | ||||||
| //        } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private static final NaturalNumber THREE = new Successor(new Successor(new Successor(new Zero()))); |  | ||||||
|     private static final NaturalNumber SEVEN = new Successor(new Successor(new Successor(new Successor(new Successor(new Successor(new Successor(new Zero()))))))); |  | ||||||
| 
 |  | ||||||
|     @StudentImplementationRequired |  | ||||||
|     private static void peanoNumberExpressionTests() { |  | ||||||
|         crash(); // TODO: H3.3 - remove if implemented |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @StudentImplementationRequired |  | ||||||
|     private static void filterFoldMapTests() { |  | ||||||
|         crash(); // TODO: H4.6 - remove if implemented |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,65 +0,0 @@ | ||||||
| package h07; |  | ||||||
| 
 |  | ||||||
| import java.util.function.IntPredicate; |  | ||||||
| 
 |  | ||||||
| import org.tudalgo.algoutils.student.annotation.DoNotTouch; |  | ||||||
| import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; |  | ||||||
| 
 |  | ||||||
| import static org.tudalgo.algoutils.student.Student.crash; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * A factory class for creating number expressions. |  | ||||||
|  */ |  | ||||||
| public class NumberExpressionFactory { |  | ||||||
|     /** |  | ||||||
|      * Calculates the product of all possible pairs of numbers in the given array. |  | ||||||
|      * |  | ||||||
|      * @param numbers the array of number expressions to calculate the multiplication table |  | ||||||
|      * @return An array of number expressions representing the result of the |  | ||||||
|      *         multiplication table of the given numbers. |  | ||||||
|      */ |  | ||||||
| //    @StudentImplementationRequired |  | ||||||
| //    public static NumberExpression[] multiplicationTable(NumberExpression[] numbers) { |  | ||||||
| //        return crash(); // TODO: H2.1 - remove if implemented |  | ||||||
| //    } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     // TODO: H2.2 - uncomment for testing |  | ||||||
|     /** |  | ||||||
|      * Calculates the product of all possible pairs of numbers in the given range. |  | ||||||
|      * |  | ||||||
|      * @param lowerBound the lower bound of the multiplication table, inclusive |  | ||||||
|      * @param upperBound the upper bound of the multiplication table, inclusive |  | ||||||
|      * @return An array of number expressions representing the result of the |  | ||||||
|      *         multiplication table of the numbers from lowerBound to upperBound. |  | ||||||
|      */ |  | ||||||
| //    @DoNotTouch |  | ||||||
| //    public static NumberExpression[] multiplicationTable(int lowerBound, int upperBound) { |  | ||||||
| //        int numberOfNumbers = upperBound - lowerBound + 1; |  | ||||||
| //        NumberExpression[] baseNumbers = new NumberExpression[numberOfNumbers]; |  | ||||||
| // |  | ||||||
| //        for (int i = lowerBound; i <= upperBound; i++) { |  | ||||||
| //            // Copy to local variable to make it effectively final, so it can be used in |  | ||||||
| //            // lambda |  | ||||||
| //            int finalI = i; |  | ||||||
| //            baseNumbers[i - lowerBound] = () -> finalI; |  | ||||||
| //        } |  | ||||||
| // |  | ||||||
| //        return multiplicationTable(baseNumbers); |  | ||||||
| //    } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Filters the given array of number expressions based on the given predicate. |  | ||||||
|      * The returned array should contain only the number expressions that satisfy |  | ||||||
|      * the predicate in the same order as they appear in the input array. |  | ||||||
|      * This means there should be no null values in the returned array. |  | ||||||
|      * |  | ||||||
|      * @param numbers   the array of number expressions to filter |  | ||||||
|      * @param predicate the predicate to filter the number expressions |  | ||||||
|      * @return An array of number expressions that satisfy the predicate. |  | ||||||
|      */ |  | ||||||
| //    @StudentImplementationRequired |  | ||||||
| //    public static NumberExpression[] filter(NumberExpression[] numbers, IntPredicate predicate) { |  | ||||||
| //        return crash(); // TODO: H4.4 - remove if implemented |  | ||||||
| //    } |  | ||||||
| } |  | ||||||
|  | @ -1,17 +0,0 @@ | ||||||
| package h07.peano; |  | ||||||
| 
 |  | ||||||
| import org.tudalgo.algoutils.student.annotation.DoNotTouch; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Represents a natural number. |  | ||||||
|  */ |  | ||||||
| @DoNotTouch |  | ||||||
| public abstract class NaturalNumber { |  | ||||||
|     /** |  | ||||||
|      * Returns the string representation of the natural number. |  | ||||||
|      * |  | ||||||
|      * @return the string representation of the natural number |  | ||||||
|      */ |  | ||||||
|     @Override |  | ||||||
|     public abstract String toString(); |  | ||||||
| } |  | ||||||
|  | @ -1,35 +0,0 @@ | ||||||
| package h07.peano; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; |  | ||||||
| 
 |  | ||||||
| import static org.tudalgo.algoutils.student.Student.crash; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Represents a factory for Peano number expressions. |  | ||||||
|  */ |  | ||||||
| public class PeanoNumberExpressionFactory { |  | ||||||
|     /** |  | ||||||
|      * Converts an array of number expressions to an array of Peano number expressions. |  | ||||||
|      * |  | ||||||
|      * @param numberExpressions the number expressions to convert |  | ||||||
|      * @return the converted Peano number expressions |  | ||||||
|      */ |  | ||||||
| //    @StudentImplementationRequired |  | ||||||
| //    public static PeanoNumberExpression[] fromNumberExpressions(NumberExpression[] numberExpressions) { |  | ||||||
| //        return crash(); // TODO: H4.3 - remove if implemented |  | ||||||
| //    } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Folds an array of Peano number expressions into a single Peano number expression. |  | ||||||
|      * |  | ||||||
|      * @param peanoNumberExpressions the Peano number expressions to fold |  | ||||||
|      * @param initial the initial Peano number expression |  | ||||||
|      * @param operation the operation to apply |  | ||||||
|      * @return the folded Peano number expression |  | ||||||
|      */ |  | ||||||
| //    @StudentImplementationRequired |  | ||||||
| //    public static PeanoNumberExpression fold(PeanoNumberExpression[] peanoNumberExpressions, PeanoNumberExpression initial, PeanoArithmeticExpression operation) { |  | ||||||
| //        return crash(); // TODO: H4.5 - remove if implemented |  | ||||||
| //    } |  | ||||||
| } |  | ||||||
|  | @ -1,20 +0,0 @@ | ||||||
| package h07.peano; |  | ||||||
| 
 |  | ||||||
| import org.tudalgo.algoutils.student.annotation.DoNotTouch; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Represents a successor of a natural number in Peano arithmetic. |  | ||||||
|  */ |  | ||||||
| @DoNotTouch |  | ||||||
| public class Successor extends NaturalNumber { |  | ||||||
|     public final NaturalNumber predecessor; |  | ||||||
| 
 |  | ||||||
|     public Successor(NaturalNumber predecessor) { |  | ||||||
|         this.predecessor = predecessor; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public String toString() { |  | ||||||
|         return "S(" + predecessor.toString() + ")"; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,14 +0,0 @@ | ||||||
| package h07.peano; |  | ||||||
| 
 |  | ||||||
| import org.tudalgo.algoutils.student.annotation.DoNotTouch; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Represents the number zero in Peano arithmetic. |  | ||||||
|  */ |  | ||||||
| @DoNotTouch |  | ||||||
| public class Zero extends NaturalNumber { |  | ||||||
|     @Override |  | ||||||
|     public String toString() { |  | ||||||
|         return "Z"; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										0
									
								
								H07/.gitignore → H08/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								H07/.gitignore → H08/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,4 +1,4 @@ | ||||||
| # Vorlage zu Hausübung 07 | # Vorlage zu Hausübung 08 | ||||||
| 
 | 
 | ||||||
| Beachten Sie die Hinweise zum Herunterladen, Importieren, Bearbeitern, Exportieren und Hochladen in unserem | Beachten Sie die Hinweise zum Herunterladen, Importieren, Bearbeitern, Exportieren und Hochladen in unserem | ||||||
| [Studierenden-Guide](https://wiki.tudalgo.org/) | [Studierenden-Guide](https://wiki.tudalgo.org/) | ||||||
|  | @ -5,7 +5,7 @@ plugins { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| exercise { | exercise { | ||||||
|     assignmentId.set("h07") |     assignmentId.set("h08") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| submission { | submission { | ||||||
|  | @ -31,3 +31,7 @@ tasks { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | application { | ||||||
|  |     applicationDefaultJvmArgs += "-ea" | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								H07/gradlew → H08/gradlew
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								H07/gradlew → H08/gradlew
									
										
									
									
										vendored
									
									
								
							
							
								
								
									
										0
									
								
								H07/gradlew.bat → H08/gradlew.bat
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								H07/gradlew.bat → H08/gradlew.bat
									
										
									
									
										vendored
									
									
								
							|  | @ -8,4 +8,4 @@ dependencyResolutionManagement { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| rootProject.name = "H07-Student" | rootProject.name = "H08-Student" | ||||||
							
								
								
									
										114
									
								
								H08/src/main/java/h08/Airport.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								H08/src/main/java/h08/Airport.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,114 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import java.util.Arrays; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents an airport. An airport manages departing and arriving flights, allowing for their addition, removal, and retrieval based on the airport code. | ||||||
|  |  */ | ||||||
|  | public class Airport { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The code of the airport. | ||||||
|  |      */ | ||||||
|  |     private String airportCode; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The departing flights of the airport. | ||||||
|  |      */ | ||||||
|  |     private Flight[] departingFlights; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The arriving flights to the airport. | ||||||
|  |      */ | ||||||
|  |     private Flight[] arrivingFlights; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The number of departing flights of the airport. | ||||||
|  |      */ | ||||||
|  |     private int departingSize; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The number of arriving flights to the airport. | ||||||
|  |      */ | ||||||
|  |     private int arrivingSize; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new airport with the specified airport code and initial capacity. | ||||||
|  |      * | ||||||
|  |      * @param airportCode     the code of the airport | ||||||
|  |      * @param initialCapacity the initial capacity of the airport | ||||||
|  |      */ | ||||||
|  |     public Airport(String airportCode, int initialCapacity) { | ||||||
|  |         this.airportCode = airportCode; | ||||||
|  |         this.departingFlights = new Flight[initialCapacity]; | ||||||
|  |         this.arrivingFlights = new Flight[initialCapacity]; | ||||||
|  |         this.departingSize = 0; | ||||||
|  |         this.arrivingSize = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds a flight. | ||||||
|  |      * | ||||||
|  |      * @param flight      the flight to add | ||||||
|  |      * @param isDeparting if true, adds to departing flights, otherwise to arriving flights | ||||||
|  |      * @throws IllegalArgumentException if the flight's airport code doesn't match the airport's code | ||||||
|  |      */ | ||||||
|  |     public void addFlight(Flight flight, boolean isDeparting) { | ||||||
|  |         //TODO H8.4.1 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.4.1 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes a flight by flight number. | ||||||
|  |      * | ||||||
|  |      * @param flightNumber the flight number | ||||||
|  |      * @param isDeparting  if true, removes from departing flights, otherwise from arriving flights | ||||||
|  |      * @throws FlightNotFoundException if the flight is not found | ||||||
|  |      */ | ||||||
|  |     public void removeFlight(String flightNumber, boolean isDeparting) { | ||||||
|  |         //TODO H8.4.2 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.4.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a flight by flight number. | ||||||
|  |      * | ||||||
|  |      * @param flightNumber the flight number | ||||||
|  |      * @param isDeparting  if true, searches in departing flights, otherwise in arriving flights | ||||||
|  |      * @return the flight with the specified flight number | ||||||
|  |      * @throws FlightNotFoundException if the flight is not found | ||||||
|  |      */ | ||||||
|  |     public Flight getFlight(String flightNumber, boolean isDeparting) { | ||||||
|  |         //TODO H8.4.3 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.4.3 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the departing flights of the airport. | ||||||
|  |      * | ||||||
|  |      * @return the departing flights of the airport | ||||||
|  |      */ | ||||||
|  |     public Flight[] getAllDepartingFlights() { | ||||||
|  |         return Arrays.copyOf(departingFlights, departingSize); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the arriving flights to the airport. | ||||||
|  |      * | ||||||
|  |      * @return the arriving flights to the airport | ||||||
|  |      */ | ||||||
|  |     public Flight[] getAllArrivingFlights() { | ||||||
|  |         return Arrays.copyOf(arrivingFlights, arrivingSize); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the airport code. | ||||||
|  |      * | ||||||
|  |      * @return the airport code | ||||||
|  |      */ | ||||||
|  |     public String getAirportCode() { | ||||||
|  |         return airportCode; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										97
									
								
								H08/src/main/java/h08/Booking.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								H08/src/main/java/h08/Booking.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,97 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents a flight booking. A booking allows the reservation of a flight as long as managing its identification and its relevant information. | ||||||
|  |  */ | ||||||
|  | public class Booking { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The booking ID of a booking. | ||||||
|  |      */ | ||||||
|  |     private String bookingId; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The flight number of a booking. | ||||||
|  |      */ | ||||||
|  |     private String flightNumber; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The passenger ID of a booking. | ||||||
|  |      */ | ||||||
|  |     private String passengerId; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The cancellations status of a booking. | ||||||
|  |      */ | ||||||
|  |     private boolean isCancelled; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new booking with the specified booking ID, flight number and passenger ID. | ||||||
|  |      * | ||||||
|  |      * @param bookingId    the booking ID of the booking | ||||||
|  |      * @param flightNumber the flight number of the booking | ||||||
|  |      * @param passengerId  the passenger ID of the booking | ||||||
|  |      */ | ||||||
|  |     public Booking(String bookingId, String flightNumber, String passengerId) { | ||||||
|  |         this.bookingId = bookingId; | ||||||
|  |         this.flightNumber = flightNumber; | ||||||
|  |         this.passengerId = passengerId; | ||||||
|  |         this.isCancelled = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the booking ID of the booking. | ||||||
|  |      * | ||||||
|  |      * @return the booking ID of the booking | ||||||
|  |      */ | ||||||
|  |     public String getBookingId() { | ||||||
|  |         return bookingId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the flight number of the booking. | ||||||
|  |      * | ||||||
|  |      * @return the flight number of the booking | ||||||
|  |      */ | ||||||
|  |     public String getFlightNumber() { | ||||||
|  |         return flightNumber; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the passenger ID of the booking. | ||||||
|  |      * | ||||||
|  |      * @return the passenger ID of the booking | ||||||
|  |      */ | ||||||
|  |     public String getPassengerId() { | ||||||
|  |         return passengerId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the cancellation status of the booking. | ||||||
|  |      * | ||||||
|  |      * @return the cancellation status of the booking | ||||||
|  |      */ | ||||||
|  |     public boolean isCancelled() { | ||||||
|  |         return isCancelled; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Cancels the booking. | ||||||
|  |      * | ||||||
|  |      * @throws BookingAlreadyCancelledException if the booking is already cancelled | ||||||
|  |      */ | ||||||
|  |     public void cancelBooking() { | ||||||
|  |         //TODO H8.4.4 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.4.4 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the booking details. | ||||||
|  |      * | ||||||
|  |      * @return the booking details | ||||||
|  |      */ | ||||||
|  |     public String viewBooking() { | ||||||
|  |         return String.format("Booking ID: %s, Flight Number: %s, Passenger ID: %s, Is Cancelled: %b", | ||||||
|  |             bookingId, flightNumber, passengerId, isCancelled); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										93
									
								
								H08/src/main/java/h08/BookingManagement.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								H08/src/main/java/h08/BookingManagement.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,93 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents a booking management. A booking management oversees booking operations, ensuring validity and handling duplicates. | ||||||
|  |  */ | ||||||
|  | public class BookingManagement { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The bookings to be managed. | ||||||
|  |      */ | ||||||
|  |     private Booking[] bookings; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The current number of bookings. | ||||||
|  |      */ | ||||||
|  |     private int size; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The flight management for the bookings. | ||||||
|  |      */ | ||||||
|  |     private FlightManagement flightManagement; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new booking management with the specified initial capacity and flight management. | ||||||
|  |      * | ||||||
|  |      * @param initialCapacity  the initial number of bookings that can be managed | ||||||
|  |      * @param flightManagement the flight management for the bookings | ||||||
|  |      */ | ||||||
|  |     public BookingManagement(int initialCapacity, FlightManagement flightManagement) { | ||||||
|  |         this.bookings = new Booking[initialCapacity]; | ||||||
|  |         this.size = 0; | ||||||
|  |         this.flightManagement = flightManagement; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a booking. | ||||||
|  |      * | ||||||
|  |      * @param bookingId    the booking ID of the booking | ||||||
|  |      * @param flightNumber the flight number of the booking | ||||||
|  |      * @param passengerId  the passenger ID of the booking | ||||||
|  |      */ | ||||||
|  |     public void createBooking(String bookingId, String flightNumber, String passengerId) { | ||||||
|  |         //TODO H8.5.5 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.5.5 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Validates the booking details and checks for duplicates. | ||||||
|  |      * | ||||||
|  |      * @param bookingId    the booking ID of the booking | ||||||
|  |      * @param flightNumber the flight number of the booking | ||||||
|  |      * @param passengerId  the passenger ID of the booking | ||||||
|  |      * @throws InvalidBookingException if the booking details are invalid | ||||||
|  |      * @throws DuplicateBookingException if the booking ID is already in use | ||||||
|  |      */ | ||||||
|  |     private void validateAndCheckBooking(String bookingId, String flightNumber, String passengerId){ | ||||||
|  |         //TODO H8.5.2 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.5.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Searches for a booking by booking ID. | ||||||
|  |      * | ||||||
|  |      * @param bookingId the booking ID of the booking | ||||||
|  |      * @return the booking with the specified booking ID | ||||||
|  |      * @throws BookingNotFoundException if the booking ist not found | ||||||
|  |      */ | ||||||
|  |     private Booking searchBooking(String bookingId){ | ||||||
|  |         //TODO H8.5.3 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.5.3 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a booking by booking ID. | ||||||
|  |      * | ||||||
|  |      * @param bookingId the booking ID of the booking | ||||||
|  |      * @return the booking with the specified booking ID | ||||||
|  |      */ | ||||||
|  |     public Booking getBooking(String bookingId) { | ||||||
|  |         //TODO H8.5.3 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.5.3 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Cancels a booking by booking ID. | ||||||
|  |      * | ||||||
|  |      * @param bookingId the booking ID of the booking | ||||||
|  |      */ | ||||||
|  |     public void cancelBooking(String bookingId) { | ||||||
|  |         //TODO H8.5.4 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.5.4 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										146
									
								
								H08/src/main/java/h08/Flight.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								H08/src/main/java/h08/Flight.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,146 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents a flight. A flight offers information such as the flight details and seat management. | ||||||
|  |  */ | ||||||
|  | public class Flight { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The flight number of the flight. | ||||||
|  |      */ | ||||||
|  |     private String flightNumber; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The departure airport of the flight. | ||||||
|  |      */ | ||||||
|  |     private String departure; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The destination airport of the flight. | ||||||
|  |      */ | ||||||
|  |     private String destination; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The departure time of the flight. | ||||||
|  |      */ | ||||||
|  |     private LocalDateTime departureTime; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The initial number of seats of the flight. | ||||||
|  |      */ | ||||||
|  |     private final int initialSeats; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The number of available seats. | ||||||
|  |      */ | ||||||
|  |     private int availableSeats; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new flight with the specified flight number, departure airport, destination airport, departure time and initial number of seats. | ||||||
|  |      * | ||||||
|  |      * @param flightNumber  the flight number of the flight | ||||||
|  |      * @param departure     the departure airport of the flight | ||||||
|  |      * @param destination   the destination airport of the flight | ||||||
|  |      * @param departureTime the departure time of the flight | ||||||
|  |      * @param initialSeats  the initial number of seats of the flight | ||||||
|  |      */ | ||||||
|  |     public Flight(String flightNumber, String departure, String destination, LocalDateTime departureTime, int initialSeats) { | ||||||
|  |         //TODO H8.2.1 | ||||||
|  |         this.flightNumber = flightNumber; | ||||||
|  |         this.departure = departure; | ||||||
|  |         this.destination = destination; | ||||||
|  |         this.departureTime = departureTime; | ||||||
|  |         this.initialSeats = initialSeats; | ||||||
|  |         this.availableSeats = initialSeats; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Validates the flight number. | ||||||
|  |      * | ||||||
|  |      * @param flightNumber the flight number of the flight | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H8.2.1") | ||||||
|  |     public void validateFlightNumber(String flightNumber) { | ||||||
|  |         //TODO H8.2.1 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.2.1 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the flight number of the flight. | ||||||
|  |      * | ||||||
|  |      * @return the flight number of the flight | ||||||
|  |      */ | ||||||
|  |     public String getFlightNumber() { | ||||||
|  |         return flightNumber; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the departure airport of the flight. | ||||||
|  |      * | ||||||
|  |      * @return the departure airport of the flight | ||||||
|  |      */ | ||||||
|  |     public String getDeparture() { | ||||||
|  |         return departure; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the destination airport of the flight. | ||||||
|  |      * | ||||||
|  |      * @return the destination airport of the flight | ||||||
|  |      */ | ||||||
|  |     public String getDestination() { | ||||||
|  |         return destination; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the departure time of the flight. | ||||||
|  |      * | ||||||
|  |      * @return the departure time of the flight | ||||||
|  |      */ | ||||||
|  |     public String getDepartureTime() { | ||||||
|  |         return departureTime.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the number of available seats of the flight. | ||||||
|  |      * | ||||||
|  |      * @return the number of available seats of the flight | ||||||
|  |      */ | ||||||
|  |     public int getAvailableSeats() { | ||||||
|  |         return availableSeats; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @StudentImplementationRequired("H8.2.2") | ||||||
|  |     public void bookSeat() { | ||||||
|  |         //TODO H8.2.2 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.2.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |    public void cancelSeat() { | ||||||
|  |         if (availableSeats < initialSeats) { | ||||||
|  |             availableSeats++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a string representation of the flight. | ||||||
|  |      * | ||||||
|  |      * @return a string representation of the flight | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "Flight{" + | ||||||
|  |             "flightNumber='" + flightNumber + '\'' + | ||||||
|  |             ", departure='" + departure + '\'' + | ||||||
|  |             ", destination='" + destination + '\'' + | ||||||
|  |             ", departureTime=" + departureTime + | ||||||
|  |             ", initialSeats=" + initialSeats + | ||||||
|  |             ", availableSeats=" + availableSeats + | ||||||
|  |             '}'; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										106
									
								
								H08/src/main/java/h08/FlightManagement.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								H08/src/main/java/h08/FlightManagement.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | import java.util.Arrays; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents a flight management. A flight management oversees the management of flights and airports. | ||||||
|  |  */ | ||||||
|  | public class FlightManagement { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The airports whose flights are managed. | ||||||
|  |      */ | ||||||
|  |     private Airport[] airports; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The current number of airports whose flights are managed. | ||||||
|  |      */ | ||||||
|  |     private int size; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new flight management with the specified initial capacity. | ||||||
|  |      * | ||||||
|  |      * @param initialCapacity the initial capacity | ||||||
|  |      */ | ||||||
|  |     public FlightManagement(int initialCapacity) { | ||||||
|  |         this.airports = new Airport[initialCapacity]; | ||||||
|  |         this.size = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds an airport to the flight management. | ||||||
|  |      * | ||||||
|  |      * @param airport the airport to be added | ||||||
|  |      */ | ||||||
|  |     public void addAirport(Airport airport) { | ||||||
|  |         if (size >= airports.length) { | ||||||
|  |             airports = Arrays.copyOf(airports, airports.length * 2); | ||||||
|  |         } | ||||||
|  |         airports[size++] = airport; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Manages the addition or removal of a flight for a specific airport. | ||||||
|  |      * | ||||||
|  |      * @param airportCode the airport code where the flight should be managed | ||||||
|  |      * @param flight      the flight to be added or removed | ||||||
|  |      * @param isAddOperation if true, the flight will be added; if false, the flight will be removed | ||||||
|  |      */ | ||||||
|  |     public void manageFlight(String airportCode, Flight flight, boolean isAddOperation) { | ||||||
|  |         //TODO H8.5.2 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H8.5.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a flight from a specific airport. | ||||||
|  |      * | ||||||
|  |      * @param airportCode  the airport code from which the flight should be returned | ||||||
|  |      * @param flightNumber the flight number of the flight | ||||||
|  |      * @return a flight from a specific airport | ||||||
|  |      */ | ||||||
|  |     public Flight getFlight(String airportCode, String flightNumber){ | ||||||
|  |         //TODO H8.5.1 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.5.1 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a flight with a specified flight number. | ||||||
|  |      * | ||||||
|  |      * @param flightNumber the flight number of the flight | ||||||
|  |      * @return a flight with a specified flight number | ||||||
|  |      */ | ||||||
|  |     public Flight getFlight(String flightNumber){ | ||||||
|  |         for (int i = 0; i < size; i++) { | ||||||
|  |             Flight flight = searchFlight(airports[i], flightNumber); | ||||||
|  |             if (flight != null) { | ||||||
|  |                 return flight; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         System.out.println("Error retrieving flight: Flight not found: " + flightNumber); | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Searches for an airport by airport code. | ||||||
|  |      * | ||||||
|  |      * @param airportCode the airport code | ||||||
|  |      * @return an airport by airport code | ||||||
|  |      * @throws Exception if the airport ist not found | ||||||
|  |      */ | ||||||
|  |     private Airport searchAirport(String airportCode) { | ||||||
|  |         //TODO H8.5.1 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.5.1 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Searches for a flight in departing or arriving flights. | ||||||
|  |      * | ||||||
|  |      * @param airport      the airport in which the flight should be searched | ||||||
|  |      * @param flightNumber the flight number of the flight | ||||||
|  |      * @return a flight in departing or arriving flights | ||||||
|  |      */ | ||||||
|  |     private Flight searchFlight(Airport airport, String flightNumber) { | ||||||
|  |         //TODO H8.5.1 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.5.1 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								H08/src/main/java/h08/Main.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								H08/src/main/java/h08/Main.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Main entry point in executing the program. | ||||||
|  |  */ | ||||||
|  | public class Main { | ||||||
|  |     /** | ||||||
|  |      * Main entry point in executing the program. | ||||||
|  |      * | ||||||
|  |      * @param args program arguments, currently ignored | ||||||
|  |      */ | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         System.out.println("Hello World!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										111
									
								
								H08/src/main/java/h08/Passenger.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								H08/src/main/java/h08/Passenger.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | ||||||
|  | package h08; | ||||||
|  | 
 | ||||||
|  | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDate; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents a passenger. A Passenger represents an individual with personal details and a unique identifier. | ||||||
|  |  */ | ||||||
|  | public class Passenger { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The ID of the passenger. | ||||||
|  |      */ | ||||||
|  |     private String passengerID; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The first name of the passenger. | ||||||
|  |      */ | ||||||
|  |     private String firstName; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The last name of the passenger. | ||||||
|  |      */ | ||||||
|  |     private String lastName; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The date of birth of the passenger. | ||||||
|  |      */ | ||||||
|  |     private LocalDate dateOfBirth; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new passenger with the specified first name, last name and date of birth. | ||||||
|  |      * | ||||||
|  |      * @param firstName   the first name of the passenger | ||||||
|  |      * @param lastName    the last name of the passenger | ||||||
|  |      * @param dateOfBirth the date of birth of the passenger | ||||||
|  |      */ | ||||||
|  |     public Passenger(String firstName, String lastName, LocalDate dateOfBirth) { | ||||||
|  |         this.firstName = firstName; | ||||||
|  |         this.lastName = lastName; | ||||||
|  |         this.dateOfBirth = dateOfBirth; | ||||||
|  |         this.passengerID = generatePassengerID(firstName, lastName, dateOfBirth); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the generated ID of the passenger. | ||||||
|  |      * | ||||||
|  |      * @param firstName   the first name of the passenger | ||||||
|  |      * @param lastName    the last name of the passenger | ||||||
|  |      * @param dateOfBirth the date of birth of the passenger | ||||||
|  |      * @return the generated ID of the passenger | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H8.1") | ||||||
|  |     private String generatePassengerID(String firstName, String lastName, LocalDate dateOfBirth) { | ||||||
|  |         //TODO H8.1 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H8.1 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the ID of the passenger. | ||||||
|  |      * | ||||||
|  |      * @return the ID of the passenger | ||||||
|  |      */ | ||||||
|  |     public String getPassengerID() { | ||||||
|  |         return passengerID; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the first name of the passenger. | ||||||
|  |      * | ||||||
|  |      * @return the first name of the passenger | ||||||
|  |      */ | ||||||
|  |     public String getFirstName() { | ||||||
|  |         return firstName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the last name of the passenger. | ||||||
|  |      * | ||||||
|  |      * @return the last name of the passenger | ||||||
|  |      */ | ||||||
|  |     public String getLastName() { | ||||||
|  |         return lastName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the date of birth of the passenger. | ||||||
|  |      * | ||||||
|  |      * @return the date of birth of the passenger | ||||||
|  |      */ | ||||||
|  |     public LocalDate getDateOfBirth() { | ||||||
|  |         return dateOfBirth; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a string representation of the passenger. | ||||||
|  |      * | ||||||
|  |      * @return a string representation of the passenger | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "Passenger{" + | ||||||
|  |                 "passengerID='" + passengerID + '\'' + | ||||||
|  |                 ", firstName='" + firstName + '\'' + | ||||||
|  |                 ", lastName='" + lastName + '\'' + | ||||||
|  |                 ", dateOfBirth=" + dateOfBirth + | ||||||
|  |                 '}'; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| package h07; | package h08; | ||||||
| 
 | 
 | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
							
								
								
									
										88
									
								
								H09/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								H09/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | ||||||
|  | ### Intellij ### | ||||||
|  | .idea/ | ||||||
|  | *.iws | ||||||
|  | /out/ | ||||||
|  | *.iml | ||||||
|  | .idea_modules/ | ||||||
|  | atlassian-ide-plugin.xml | ||||||
|  | 
 | ||||||
|  | ### VS-Code ### | ||||||
|  | .vscode/ | ||||||
|  | .VSCodeCounter/ | ||||||
|  | 
 | ||||||
|  | ### Eclipse ### | ||||||
|  | .metadata | ||||||
|  | bin/ | ||||||
|  | tmp/ | ||||||
|  | *.tmp | ||||||
|  | *.bak | ||||||
|  | *.swp | ||||||
|  | *~.nib | ||||||
|  | local.properties | ||||||
|  | .settings/ | ||||||
|  | .loadpath | ||||||
|  | .recommenders | ||||||
|  | .externalToolBuilders/ | ||||||
|  | *.launch | ||||||
|  | .factorypath | ||||||
|  | .recommenders/ | ||||||
|  | .apt_generated/ | ||||||
|  | .project | ||||||
|  | .classpath | ||||||
|  | 
 | ||||||
|  | ### Linux ### | ||||||
|  | *~ | ||||||
|  | .fuse_hidden* | ||||||
|  | .directory | ||||||
|  | .Trash-* | ||||||
|  | .nfs* | ||||||
|  | 
 | ||||||
|  | ### macOS ### | ||||||
|  | .DS_Store | ||||||
|  | .AppleDouble | ||||||
|  | .LSOverride | ||||||
|  | Icon | ||||||
|  | ._* | ||||||
|  | .DocumentRevisions-V100 | ||||||
|  | .fseventsd | ||||||
|  | .Spotlight-V100 | ||||||
|  | .TemporaryItems | ||||||
|  | .Trashes | ||||||
|  | .VolumeIcon.icns | ||||||
|  | .com.apple.timemachine.donotpresent | ||||||
|  | .AppleDB | ||||||
|  | .AppleDesktop | ||||||
|  | Network Trash Folder | ||||||
|  | Temporary Items | ||||||
|  | .apdisk | ||||||
|  | 
 | ||||||
|  | ### NetBeans ### | ||||||
|  | nbproject/private/ | ||||||
|  | build/ | ||||||
|  | nbbuild/ | ||||||
|  | dist/ | ||||||
|  | nbdist/ | ||||||
|  | .nb-gradle/ | ||||||
|  | 
 | ||||||
|  | ### Windows ### | ||||||
|  | # Windows thumbnail cache files | ||||||
|  | Thumbs.db | ||||||
|  | ehthumbs.db | ||||||
|  | ehthumbs_vista.db | ||||||
|  | *.stackdump | ||||||
|  | [Dd]esktop.ini | ||||||
|  | $RECYCLE.BIN/ | ||||||
|  | *.lnk | ||||||
|  | 
 | ||||||
|  | ### Gradle ### | ||||||
|  | .gradle | ||||||
|  | /build/ | ||||||
|  | out/ | ||||||
|  | gradle-app.setting | ||||||
|  | !gradle-wrapper.jar | ||||||
|  | .gradletasknamecache | ||||||
|  | 
 | ||||||
|  | *.hprof | ||||||
|  | screenshots | ||||||
|  | 
 | ||||||
|  | jagr.conf | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| # Musterlösung zu Hausübung 07 | # Vorlage zu Hausübung 09 | ||||||
| 
 | 
 | ||||||
| Beachten Sie die Hinweise zum Herunterladen, Importieren, Bearbeitern, Exportieren und Hochladen in unserem | Beachten Sie die Hinweise zum Herunterladen, Importieren, Bearbeitern, Exportieren und Hochladen in unserem | ||||||
| [Studierenden-Guide](https://wiki.tudalgo.org/) | [Studierenden-Guide](https://wiki.tudalgo.org/) | ||||||
							
								
								
									
										33
									
								
								H09/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								H09/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | import org.sourcegrade.jagr.gradle.task.grader.GraderRunTask | ||||||
|  | 
 | ||||||
|  | plugins { | ||||||
|  |     alias(libs.plugins.algomate) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | exercise { | ||||||
|  |     assignmentId.set("h09") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | submission { | ||||||
|  |     // ACHTUNG! | ||||||
|  |     // Setzen Sie im folgenden Bereich Ihre TU-ID (NICHT Ihre Matrikelnummer!), Ihren Nachnamen und Ihren Vornamen | ||||||
|  |     // in Anführungszeichen (z.B. "ab12cdef" für Ihre TU-ID) ein! | ||||||
|  |     // BEISPIEL: | ||||||
|  |     // studentId = "ab12cdef" | ||||||
|  |     // firstName = "sol_first" | ||||||
|  |     // lastName = "sol_last" | ||||||
|  |     studentId = "" | ||||||
|  |     firstName = "" | ||||||
|  |     lastName = "" | ||||||
|  | 
 | ||||||
|  |     // Optionally require own tests for mainBuildSubmission task. Default is false | ||||||
|  |     requireTests = false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | jagr { | ||||||
|  |     graders { | ||||||
|  |         val graderPublic by getting { | ||||||
|  |             rubricProviderName.set("h09.H09_RubricProviderPublic") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								H09/gradle/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								H09/gradle/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | [plugins] | ||||||
|  | algomate = { id = "org.tudalgo.algomate", version = "0.7.1" } | ||||||
							
								
								
									
										
											BIN
										
									
								
								H09/gradle/wrapper/gradle-wrapper.jar
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								H09/gradle/wrapper/gradle-wrapper.jar
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										7
									
								
								H09/gradle/wrapper/gradle-wrapper.properties
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								H09/gradle/wrapper/gradle-wrapper.properties
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | distributionBase=GRADLE_USER_HOME | ||||||
|  | distributionPath=wrapper/dists | ||||||
|  | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip | ||||||
|  | networkTimeout=10000 | ||||||
|  | validateDistributionUrl=true | ||||||
|  | zipStoreBase=GRADLE_USER_HOME | ||||||
|  | zipStorePath=wrapper/dists | ||||||
							
								
								
									
										249
									
								
								H09/gradlew
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										249
									
								
								H09/gradlew
									
										
									
									
										vendored
									
									
										Executable file
									
								
							|  | @ -0,0 +1,249 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # Copyright © 2015-2021 the original authors. | ||||||
|  | # | ||||||
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | # you may not use this file except in compliance with the License. | ||||||
|  | # You may obtain a copy of the License at | ||||||
|  | # | ||||||
|  | #      https://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | # Unless required by applicable law or agreed to in writing, software | ||||||
|  | # distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | # See the License for the specific language governing permissions and | ||||||
|  | # limitations under the License. | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | ############################################################################## | ||||||
|  | # | ||||||
|  | #   Gradle start up script for POSIX generated by Gradle. | ||||||
|  | # | ||||||
|  | #   Important for running: | ||||||
|  | # | ||||||
|  | #   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is | ||||||
|  | #       noncompliant, but you have some other compliant shell such as ksh or | ||||||
|  | #       bash, then to run this script, type that shell name before the whole | ||||||
|  | #       command line, like: | ||||||
|  | # | ||||||
|  | #           ksh Gradle | ||||||
|  | # | ||||||
|  | #       Busybox and similar reduced shells will NOT work, because this script | ||||||
|  | #       requires all of these POSIX shell features: | ||||||
|  | #         * functions; | ||||||
|  | #         * expansions «$var», «${var}», «${var:-default}», «${var+SET}», | ||||||
|  | #           «${var#prefix}», «${var%suffix}», and «$( cmd )»; | ||||||
|  | #         * compound commands having a testable exit status, especially «case»; | ||||||
|  | #         * various built-in commands including «command», «set», and «ulimit». | ||||||
|  | # | ||||||
|  | #   Important for patching: | ||||||
|  | # | ||||||
|  | #   (2) This script targets any POSIX shell, so it avoids extensions provided | ||||||
|  | #       by Bash, Ksh, etc; in particular arrays are avoided. | ||||||
|  | # | ||||||
|  | #       The "traditional" practice of packing multiple parameters into a | ||||||
|  | #       space-separated string is a well documented source of bugs and security | ||||||
|  | #       problems, so this is (mostly) avoided, by progressively accumulating | ||||||
|  | #       options in "$@", and eventually passing that to Java. | ||||||
|  | # | ||||||
|  | #       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, | ||||||
|  | #       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; | ||||||
|  | #       see the in-line comments for details. | ||||||
|  | # | ||||||
|  | #       There are tweaks for specific operating systems such as AIX, CygWin, | ||||||
|  | #       Darwin, MinGW, and NonStop. | ||||||
|  | # | ||||||
|  | #   (3) This script is generated from the Groovy template | ||||||
|  | #       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt | ||||||
|  | #       within the Gradle project. | ||||||
|  | # | ||||||
|  | #       You can find Gradle at https://github.com/gradle/gradle/. | ||||||
|  | # | ||||||
|  | ############################################################################## | ||||||
|  | 
 | ||||||
|  | # Attempt to set APP_HOME | ||||||
|  | 
 | ||||||
|  | # Resolve links: $0 may be a link | ||||||
|  | app_path=$0 | ||||||
|  | 
 | ||||||
|  | # Need this for daisy-chained symlinks. | ||||||
|  | while | ||||||
|  |     APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path | ||||||
|  |     [ -h "$app_path" ] | ||||||
|  | do | ||||||
|  |     ls=$( ls -ld "$app_path" ) | ||||||
|  |     link=${ls#*' -> '} | ||||||
|  |     case $link in             #( | ||||||
|  |       /*)   app_path=$link ;; #( | ||||||
|  |       *)    app_path=$APP_HOME$link ;; | ||||||
|  |     esac | ||||||
|  | done | ||||||
|  | 
 | ||||||
|  | # This is normally unused | ||||||
|  | # shellcheck disable=SC2034 | ||||||
|  | APP_BASE_NAME=${0##*/} | ||||||
|  | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | ||||||
|  | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit | ||||||
|  | 
 | ||||||
|  | # Use the maximum available, or set MAX_FD != -1 to use that value. | ||||||
|  | MAX_FD=maximum | ||||||
|  | 
 | ||||||
|  | warn () { | ||||||
|  |     echo "$*" | ||||||
|  | } >&2 | ||||||
|  | 
 | ||||||
|  | die () { | ||||||
|  |     echo | ||||||
|  |     echo "$*" | ||||||
|  |     echo | ||||||
|  |     exit 1 | ||||||
|  | } >&2 | ||||||
|  | 
 | ||||||
|  | # OS specific support (must be 'true' or 'false'). | ||||||
|  | cygwin=false | ||||||
|  | msys=false | ||||||
|  | darwin=false | ||||||
|  | nonstop=false | ||||||
|  | case "$( uname )" in                #( | ||||||
|  |   CYGWIN* )         cygwin=true  ;; #( | ||||||
|  |   Darwin* )         darwin=true  ;; #( | ||||||
|  |   MSYS* | MINGW* )  msys=true    ;; #( | ||||||
|  |   NONSTOP* )        nonstop=true ;; | ||||||
|  | esac | ||||||
|  | 
 | ||||||
|  | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Determine the Java command to use to start the JVM. | ||||||
|  | if [ -n "$JAVA_HOME" ] ; then | ||||||
|  |     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | ||||||
|  |         # IBM's JDK on AIX uses strange locations for the executables | ||||||
|  |         JAVACMD=$JAVA_HOME/jre/sh/java | ||||||
|  |     else | ||||||
|  |         JAVACMD=$JAVA_HOME/bin/java | ||||||
|  |     fi | ||||||
|  |     if [ ! -x "$JAVACMD" ] ; then | ||||||
|  |         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | ||||||
|  | 
 | ||||||
|  | Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | location of your Java installation." | ||||||
|  |     fi | ||||||
|  | else | ||||||
|  |     JAVACMD=java | ||||||
|  |     if ! command -v java >/dev/null 2>&1 | ||||||
|  |     then | ||||||
|  |         die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||||
|  | 
 | ||||||
|  | Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | location of your Java installation." | ||||||
|  |     fi | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Increase the maximum file descriptors if we can. | ||||||
|  | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||||
|  |     case $MAX_FD in #( | ||||||
|  |       max*) | ||||||
|  |         # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. | ||||||
|  |         # shellcheck disable=SC2039,SC3045 | ||||||
|  |         MAX_FD=$( ulimit -H -n ) || | ||||||
|  |             warn "Could not query maximum file descriptor limit" | ||||||
|  |     esac | ||||||
|  |     case $MAX_FD in  #( | ||||||
|  |       '' | soft) :;; #( | ||||||
|  |       *) | ||||||
|  |         # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. | ||||||
|  |         # shellcheck disable=SC2039,SC3045 | ||||||
|  |         ulimit -n "$MAX_FD" || | ||||||
|  |             warn "Could not set maximum file descriptor limit to $MAX_FD" | ||||||
|  |     esac | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Collect all arguments for the java command, stacking in reverse order: | ||||||
|  | #   * args from the command line | ||||||
|  | #   * the main class name | ||||||
|  | #   * -classpath | ||||||
|  | #   * -D...appname settings | ||||||
|  | #   * --module-path (only if needed) | ||||||
|  | #   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. | ||||||
|  | 
 | ||||||
|  | # For Cygwin or MSYS, switch paths to Windows format before running java | ||||||
|  | if "$cygwin" || "$msys" ; then | ||||||
|  |     APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) | ||||||
|  |     CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) | ||||||
|  | 
 | ||||||
|  |     JAVACMD=$( cygpath --unix "$JAVACMD" ) | ||||||
|  | 
 | ||||||
|  |     # Now convert the arguments - kludge to limit ourselves to /bin/sh | ||||||
|  |     for arg do | ||||||
|  |         if | ||||||
|  |             case $arg in                                #( | ||||||
|  |               -*)   false ;;                            # don't mess with options #( | ||||||
|  |               /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath | ||||||
|  |                     [ -e "$t" ] ;;                      #( | ||||||
|  |               *)    false ;; | ||||||
|  |             esac | ||||||
|  |         then | ||||||
|  |             arg=$( cygpath --path --ignore --mixed "$arg" ) | ||||||
|  |         fi | ||||||
|  |         # Roll the args list around exactly as many times as the number of | ||||||
|  |         # args, so each arg winds up back in the position where it started, but | ||||||
|  |         # possibly modified. | ||||||
|  |         # | ||||||
|  |         # NB: a `for` loop captures its iteration list before it begins, so | ||||||
|  |         # changing the positional parameters here affects neither the number of | ||||||
|  |         # iterations, nor the values presented in `arg`. | ||||||
|  |         shift                   # remove old arg | ||||||
|  |         set -- "$@" "$arg"      # push replacement arg | ||||||
|  |     done | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
|  | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | ||||||
|  | 
 | ||||||
|  | # Collect all arguments for the java command: | ||||||
|  | #   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | ||||||
|  | #     and any embedded shellness will be escaped. | ||||||
|  | #   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be | ||||||
|  | #     treated as '${Hostname}' itself on the command line. | ||||||
|  | 
 | ||||||
|  | set -- \ | ||||||
|  |         "-Dorg.gradle.appname=$APP_BASE_NAME" \ | ||||||
|  |         -classpath "$CLASSPATH" \ | ||||||
|  |         org.gradle.wrapper.GradleWrapperMain \ | ||||||
|  |         "$@" | ||||||
|  | 
 | ||||||
|  | # Stop when "xargs" is not available. | ||||||
|  | if ! command -v xargs >/dev/null 2>&1 | ||||||
|  | then | ||||||
|  |     die "xargs is not available" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Use "xargs" to parse quoted args. | ||||||
|  | # | ||||||
|  | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. | ||||||
|  | # | ||||||
|  | # In Bash we could simply go: | ||||||
|  | # | ||||||
|  | #   readarray ARGS < <( xargs -n1 <<<"$var" ) && | ||||||
|  | #   set -- "${ARGS[@]}" "$@" | ||||||
|  | # | ||||||
|  | # but POSIX shell has neither arrays nor command substitution, so instead we | ||||||
|  | # post-process each arg (as a line of input to sed) to backslash-escape any | ||||||
|  | # character that might be a shell metacharacter, then use eval to reverse | ||||||
|  | # that process (while maintaining the separation between arguments), and wrap | ||||||
|  | # the whole thing up as a single "set" statement. | ||||||
|  | # | ||||||
|  | # This will of course break if any of these variables contains a newline or | ||||||
|  | # an unmatched quote. | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | eval "set -- $( | ||||||
|  |         printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | | ||||||
|  |         xargs -n1 | | ||||||
|  |         sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | | ||||||
|  |         tr '\n' ' ' | ||||||
|  |     )" '"$@"' | ||||||
|  | 
 | ||||||
|  | exec "$JAVACMD" "$@" | ||||||
							
								
								
									
										92
									
								
								H09/gradlew.bat
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								H09/gradlew.bat
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | ||||||
|  | @rem | ||||||
|  | @rem Copyright 2015 the original author or authors. | ||||||
|  | @rem | ||||||
|  | @rem Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | @rem you may not use this file except in compliance with the License. | ||||||
|  | @rem You may obtain a copy of the License at | ||||||
|  | @rem | ||||||
|  | @rem      https://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | @rem | ||||||
|  | @rem Unless required by applicable law or agreed to in writing, software | ||||||
|  | @rem distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | @rem See the License for the specific language governing permissions and | ||||||
|  | @rem limitations under the License. | ||||||
|  | @rem | ||||||
|  | 
 | ||||||
|  | @if "%DEBUG%"=="" @echo off | ||||||
|  | @rem ########################################################################## | ||||||
|  | @rem | ||||||
|  | @rem  Gradle startup script for Windows | ||||||
|  | @rem | ||||||
|  | @rem ########################################################################## | ||||||
|  | 
 | ||||||
|  | @rem Set local scope for the variables with windows NT shell | ||||||
|  | if "%OS%"=="Windows_NT" setlocal | ||||||
|  | 
 | ||||||
|  | set DIRNAME=%~dp0 | ||||||
|  | if "%DIRNAME%"=="" set DIRNAME=. | ||||||
|  | @rem This is normally unused | ||||||
|  | set APP_BASE_NAME=%~n0 | ||||||
|  | set APP_HOME=%DIRNAME% | ||||||
|  | 
 | ||||||
|  | @rem Resolve any "." and ".." in APP_HOME to make it shorter. | ||||||
|  | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi | ||||||
|  | 
 | ||||||
|  | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
|  | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" | ||||||
|  | 
 | ||||||
|  | @rem Find java.exe | ||||||
|  | if defined JAVA_HOME goto findJavaFromJavaHome | ||||||
|  | 
 | ||||||
|  | set JAVA_EXE=java.exe | ||||||
|  | %JAVA_EXE% -version >NUL 2>&1 | ||||||
|  | if %ERRORLEVEL% equ 0 goto execute | ||||||
|  | 
 | ||||||
|  | echo. 1>&2 | ||||||
|  | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | ||||||
|  | echo. 1>&2 | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||||
|  | echo location of your Java installation. 1>&2 | ||||||
|  | 
 | ||||||
|  | goto fail | ||||||
|  | 
 | ||||||
|  | :findJavaFromJavaHome | ||||||
|  | set JAVA_HOME=%JAVA_HOME:"=% | ||||||
|  | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||||
|  | 
 | ||||||
|  | if exist "%JAVA_EXE%" goto execute | ||||||
|  | 
 | ||||||
|  | echo. 1>&2 | ||||||
|  | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | ||||||
|  | echo. 1>&2 | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||||
|  | echo location of your Java installation. 1>&2 | ||||||
|  | 
 | ||||||
|  | goto fail | ||||||
|  | 
 | ||||||
|  | :execute | ||||||
|  | @rem Setup the command line | ||||||
|  | 
 | ||||||
|  | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @rem Execute Gradle | ||||||
|  | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* | ||||||
|  | 
 | ||||||
|  | :end | ||||||
|  | @rem End local scope for the variables with windows NT shell | ||||||
|  | if %ERRORLEVEL% equ 0 goto mainEnd | ||||||
|  | 
 | ||||||
|  | :fail | ||||||
|  | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | ||||||
|  | rem the _cmd.exe /c_ return code! | ||||||
|  | set EXIT_CODE=%ERRORLEVEL% | ||||||
|  | if %EXIT_CODE% equ 0 set EXIT_CODE=1 | ||||||
|  | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% | ||||||
|  | exit /b %EXIT_CODE% | ||||||
|  | 
 | ||||||
|  | :mainEnd | ||||||
|  | if "%OS%"=="Windows_NT" endlocal | ||||||
|  | 
 | ||||||
|  | :omega | ||||||
							
								
								
									
										11
									
								
								H09/settings.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								H09/settings.gradle.kts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | dependencyResolutionManagement { | ||||||
|  |     repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) | ||||||
|  |     repositories { | ||||||
|  | //        mavenLocal() | ||||||
|  |         maven("https://s01.oss.sonatype.org/content/repositories/snapshots") | ||||||
|  |         maven("https://jitpack.io") | ||||||
|  |         mavenCentral() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | rootProject.name = "H09-Student" | ||||||
							
								
								
									
										149
									
								
								H09/src/graderPublic/java/h09/EnclosureTestPublic.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								H09/src/graderPublic/java/h09/EnclosureTestPublic.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,149 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import h09.abilities.Swims; | ||||||
|  | import h09.animals.Animal; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.CsvSource; | ||||||
|  | import org.sourcegrade.jagr.api.rubric.TestForSubmission; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.assertions.Context; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.reflections.BasicTypeLink; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.lang.reflect.Type; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  | import java.util.function.Consumer; | ||||||
|  | import java.util.function.Predicate; | ||||||
|  | 
 | ||||||
|  | import static h09.H09_TestUtils.assertDefinedParameters; | ||||||
|  | import static h09.H09_TestUtils.assertParameters; | ||||||
|  | import static h09.H09_TestUtils.assertReturnParameter; | ||||||
|  | import static h09.H09_TestUtils.assertType; | ||||||
|  | import static h09.H09_TestUtils.getDefinedTypes; | ||||||
|  | import static h09.H09_TestUtils.match; | ||||||
|  | import static h09.H09_TestUtils.matchNested; | ||||||
|  | import static h09.H09_TestUtils.matchUpperBounds; | ||||||
|  | import static h09.H09_TestUtils.matchWildcard; | ||||||
|  | import static org.mockito.Mockito.atLeastOnce; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
|  | import static org.mockito.Mockito.verify; | ||||||
|  | import static org.mockito.Mockito.when; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertEquals; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertNotNull; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.contextBuilder; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.emptyContext; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.fail; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.match.BasicStringMatchers.identical; | ||||||
|  | 
 | ||||||
|  | @TestForSubmission | ||||||
|  | public class EnclosureTestPublic { | ||||||
|  | 
 | ||||||
|  |     BasicTypeLink enclosureLink; | ||||||
|  |     Method getStack; | ||||||
|  |     Method forEach; | ||||||
|  |     Method filterObj; | ||||||
|  |     Method filterFunc; | ||||||
|  |     Method eatAndSink; | ||||||
|  |     Field swimsAtLowElevation; | ||||||
|  |     Field feedAndSleep; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     @SuppressWarnings("unchecked") | ||||||
|  |     public void setUp() { | ||||||
|  |         enclosureLink = BasicTypeLink.of(Enclosure.class); | ||||||
|  | 
 | ||||||
|  |         getStack = enclosureLink.getMethod(identical("getStack")).reflection(); | ||||||
|  |         forEach = enclosureLink.getMethod(identical("forEach")).reflection(); | ||||||
|  |         filterObj = enclosureLink.getMethod(identical("filterObj")).reflection(); | ||||||
|  |         filterFunc = enclosureLink.getMethod(identical("filterFunc")).reflection(); | ||||||
|  |         eatAndSink = enclosureLink.getMethod(identical("EAT_AND_SINK")).reflection(); | ||||||
|  | 
 | ||||||
|  |         swimsAtLowElevation = enclosureLink.getField(identical("SWIMS_AT_LOW_ELEVATION")).reflection(); | ||||||
|  |         feedAndSleep = enclosureLink.getField(identical("FEED_AND_SLEEP")).reflection(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testClassParameter() { | ||||||
|  |         assertDefinedParameters(Enclosure.class, Set.of(matchUpperBounds("A", Animal.class))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testGetStack_ReturnType() { | ||||||
|  |         Predicate<Type> typeMatcher = getDefinedTypes(Enclosure.class, ".*").stream() | ||||||
|  |             .map(H09_TestUtils::match) | ||||||
|  |             .reduce(Predicate::or) | ||||||
|  |             .orElse(new H09_TestUtils.GenericPredicate(i -> false, "Expected type is not defined")); | ||||||
|  | 
 | ||||||
|  |         assertReturnParameter(getStack, matchNested(StackOfObjects.class, typeMatcher)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testForEach_Parameter() { | ||||||
|  |         Predicate<Type> typeMatcher = getDefinedTypes(Enclosure.class, ".*").stream() | ||||||
|  |             .map(type -> matchWildcard(false, type)) | ||||||
|  |             .reduce(Predicate::or) | ||||||
|  |             .orElse(new H09_TestUtils.GenericPredicate(i -> false, "Expected type is not defined")); | ||||||
|  | 
 | ||||||
|  |         assertParameters(forEach, List.of(matchNested(Consumer.class, typeMatcher))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testSWIMS_AT_LOW_ELEVATION_Type() { | ||||||
|  |         assertType(swimsAtLowElevation, matchNested(Predicate.class, match(Swims.class))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @CsvSource({"5,false", "-3,false", "-5,true", "-5,true"}) | ||||||
|  |     public void testSWIMS_AT_LOW_ELEVATION_Implementation(float elevation, boolean predicateResult) { | ||||||
|  |         assertNotNull(Enclosure.SWIMS_AT_LOW_ELEVATION, emptyContext(), r -> "SWIMS_AT_LOW_ELEVATION is not implemented"); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             Swims mock = mock(Swims.class); | ||||||
|  |             when(mock.getElevation()).thenReturn(elevation); | ||||||
|  | 
 | ||||||
|  |             Context context = contextBuilder().add("elevation", elevation).build(); | ||||||
|  | 
 | ||||||
|  |             assertEquals( | ||||||
|  |                 predicateResult, | ||||||
|  |                 Enclosure.SWIMS_AT_LOW_ELEVATION.test(mock), | ||||||
|  |                 context, | ||||||
|  |                 r -> "SWIMS_AT_LOW_ELEVATION is not implemented correctly" | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |         } catch (ClassCastException exception) { | ||||||
|  |             fail( | ||||||
|  |                 emptyContext(), | ||||||
|  |                 r -> "SWIMS_AT_LOW_ELEVATION does not accept correct type of objects. Message of thrown Exception: %s".formatted( | ||||||
|  |                     exception.getMessage()) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testFEED_AND_SLEEP_Type() { | ||||||
|  |         assertType(feedAndSleep, matchNested(Consumer.class, match(Animal.class))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testFEED_AND_SLEEP_Implementation() { | ||||||
|  |         assertNotNull(Enclosure.FEED_AND_SLEEP, emptyContext(), r -> "FEED_AND_SLEEP is not implemented"); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             Animal mock = mock(Animal.class); | ||||||
|  | 
 | ||||||
|  |             Enclosure.FEED_AND_SLEEP.accept(mock); | ||||||
|  | 
 | ||||||
|  |             verify(mock, atLeastOnce()).eat(); | ||||||
|  |             verify(mock, atLeastOnce()).sleep(); | ||||||
|  | 
 | ||||||
|  |         } catch (ClassCastException exception) { | ||||||
|  |             fail( | ||||||
|  |                 emptyContext(), | ||||||
|  |                 r -> "FEED_AND_SLEEP does not accept correct type of objects. Message of thrown Exception: %s".formatted(exception.getMessage()) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										152
									
								
								H09/src/graderPublic/java/h09/H09_RubricProviderPublic.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								H09/src/graderPublic/java/h09/H09_RubricProviderPublic.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,152 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import org.sourcegrade.jagr.api.rubric.Criterion; | ||||||
|  | import org.sourcegrade.jagr.api.rubric.JUnitTestRef; | ||||||
|  | import org.sourcegrade.jagr.api.rubric.Rubric; | ||||||
|  | import org.sourcegrade.jagr.api.rubric.RubricProvider; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.jagr.RubricUtils.criterion; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.jagr.RubricUtils.graderPrivateOnly; | ||||||
|  | 
 | ||||||
|  | public class H09_RubricProviderPublic implements RubricProvider { | ||||||
|  | 
 | ||||||
|  |     public static final Rubric RUBRIC = Rubric.builder() | ||||||
|  |         .title("H09") | ||||||
|  |         .addChildCriteria( | ||||||
|  |             Criterion.builder() | ||||||
|  |                 .shortDescription("H9.1 | StackOfObjects") | ||||||
|  |                 .addChildCriteria( | ||||||
|  |                     criterion( | ||||||
|  |                         "Der generische Typparameter O wird korrekt deklariert und das Attribut objs wird korrekt initialisiert.", | ||||||
|  |                         JUnitTestRef.and( | ||||||
|  |                             JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testClassParameter")), | ||||||
|  |                             JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testObjsType")) | ||||||
|  |                         ) | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "push wird korrekt mit generischem Typparameter angepasst.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testPushParameter")) | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "remove wird korrekt mit generischem Typparameter angepasst.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testRemoveParameter")) | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "get und pop werden korrekt mit generischem Typparameter angepasst.", | ||||||
|  |                         JUnitTestRef.and( | ||||||
|  |                             JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testGetParameter")), | ||||||
|  |                             JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testPopParameter")) | ||||||
|  |                         ) | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "of wird korrekt mit generischem Typparameter angepasst.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> StackOfObjectsTestPublic.class.getMethod("testOfParameter")) | ||||||
|  |                         , 2 | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |                 .build(), | ||||||
|  |             Criterion.builder() | ||||||
|  |                 .shortDescription("H9.2 | Generische Typen beschränken") | ||||||
|  |                 .addChildCriteria( | ||||||
|  |                     criterion( | ||||||
|  |                         "Der generische Typparameter von Enclosure wird korrekt deklariert und beschränkt.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod("testClassParameter")) | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "Enclosure::getStack von Enclosure wird korrekt mit generischem Typparameter angepasst.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod("testGetStack_ReturnType")) | ||||||
|  |                     ), | ||||||
|  |                     privateCriterion( | ||||||
|  |                         "Waterenclosure besitzt einen korrekt beschränkten Typparameter und implementiert Enclosure korrekt.", | ||||||
|  |                         0, | ||||||
|  |                         1 | ||||||
|  |                     ), | ||||||
|  |                     privateCriterion("Waterenclosure::getStack funktioniert korrekt.", 0, 1), | ||||||
|  |                     criterion( | ||||||
|  |                         "Waterenclosure::feed funktioniert korrekt.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> WaterEnclosureTestPublic.class.getMethod("testFeed")) | ||||||
|  |                         , 2 | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "Waterenclosure::getMeanElevation funktioniert korrekt.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> WaterEnclosureTestPublic.class.getMethod( | ||||||
|  |                             "testGetMeanElevation", | ||||||
|  |                             List.class, | ||||||
|  |                             double.class | ||||||
|  |                         )) | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |                 .build(), | ||||||
|  |             Criterion.builder() | ||||||
|  |                 .shortDescription("H9.3 | Bearbeitung von Enclosures mit funktionalen Interfaces") | ||||||
|  |                 .addChildCriteria( | ||||||
|  |                     criterion( | ||||||
|  |                         "forEach hat korrekt beschränkte Typparameter.", | ||||||
|  |                         JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod("testForEach_Parameter")), | ||||||
|  |                         3 | ||||||
|  |                     ), | ||||||
|  |                     privateCriterion("filterObj hat korrekt beschränkte Typparameter.", 0, 3), | ||||||
|  |                     privateCriterion("filterFunc hat korrekt beschränkte Typparameter.", 0, 4), | ||||||
|  |                     privateCriterion("filterFunc gibt korrekt ein neues Enclosure mit gefilterten Tieren zurück.", 0, 2) | ||||||
|  |                 ) | ||||||
|  |                 .build(), | ||||||
|  |             Criterion.builder() | ||||||
|  |                 .shortDescription("H9.4 | Predicates and Consumer mit Lambda") | ||||||
|  |                 .addChildCriteria( | ||||||
|  |                     criterion( | ||||||
|  |                         "SWIMS_AT_LOW_ELEVATION funktioniert korrekt und wurde korrekt beschränkt.", | ||||||
|  |                         JUnitTestRef.and( | ||||||
|  |                             JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod("testSWIMS_AT_LOW_ELEVATION_Type")), | ||||||
|  |                             JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod( | ||||||
|  |                                 "testSWIMS_AT_LOW_ELEVATION_Implementation", | ||||||
|  |                                 float.class, | ||||||
|  |                                 boolean.class | ||||||
|  |                             )) | ||||||
|  |                         ) | ||||||
|  |                     ), | ||||||
|  |                     criterion( | ||||||
|  |                         "FEED_AND_SLEEP funktioniert korrekt und wurde korrekt beschränkt.", | ||||||
|  |                         JUnitTestRef.and( | ||||||
|  |                             JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod("testFEED_AND_SLEEP_Type")), | ||||||
|  |                             JUnitTestRef.ofMethod(() -> EnclosureTestPublic.class.getMethod("testFEED_AND_SLEEP_Implementation")) | ||||||
|  |                         ) | ||||||
|  |                     ), | ||||||
|  |                     privateCriterion("EAT_AND_SINK() gibt einen korrekten Consumer zurück, welcher korrekt beschränkt ist.", 0, 2) | ||||||
|  |                 ) | ||||||
|  |                 .build(), | ||||||
|  |             Criterion.builder() | ||||||
|  |                 .shortDescription("H9.5 | Enclosure::forEach") | ||||||
|  |                 .addChildCriteria( | ||||||
|  |                     privateCriterion( | ||||||
|  |                         "Drei Lion Objekte werden erstellt sowie gefüttert. Die Methode forEach wird grundlegend getestet.", | ||||||
|  |                         0, | ||||||
|  |                         1 | ||||||
|  |                     ), | ||||||
|  |                     privateCriterion("Zwei Penguin Objekte werden korrekt erstellt, bewegt und gefüttert.", 0, 1), | ||||||
|  |                     privateCriterion("Einfache Fehlfunktionen der Methode filterFunc werden erkannt.", 0, 1) | ||||||
|  |                 ) | ||||||
|  |                 .build() | ||||||
|  |         ) | ||||||
|  |         .build(); | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Rubric getRubric() { | ||||||
|  |         return RUBRIC; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Criterion privateCriterion(String message, int min, int max) { | ||||||
|  |         return Criterion.builder() | ||||||
|  |             .shortDescription(message) | ||||||
|  |             .grader(graderPrivateOnly(max)) | ||||||
|  |             .minPoints(min) | ||||||
|  |             .maxPoints(max) | ||||||
|  |             .build(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | //    @Override | ||||||
|  | //    public void configure(final RubricConfiguration configuration) { | ||||||
|  | //        configuration.addTransformer(new AccessTransformer()); | ||||||
|  | //    } | ||||||
|  | } | ||||||
							
								
								
									
										689
									
								
								H09/src/graderPublic/java/h09/H09_TestUtils.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										689
									
								
								H09/src/graderPublic/java/h09/H09_TestUtils.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,689 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import org.apache.commons.lang3.tuple.ImmutablePair; | ||||||
|  | import org.apache.commons.lang3.tuple.Pair; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.assertions.Context; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.reflections.BasicMethodLink; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.reflections.BasicTypeLink; | ||||||
|  | import spoon.reflect.declaration.CtField; | ||||||
|  | import spoon.reflect.declaration.CtMethod; | ||||||
|  | import spoon.reflect.declaration.CtParameter; | ||||||
|  | import spoon.reflect.declaration.CtType; | ||||||
|  | import spoon.reflect.declaration.CtTypeParameter; | ||||||
|  | import spoon.reflect.reference.CtTypeReference; | ||||||
|  | import spoon.reflect.visitor.filter.TypeFilter; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.lang.reflect.GenericArrayType; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.lang.reflect.ParameterizedType; | ||||||
|  | import java.lang.reflect.Type; | ||||||
|  | import java.lang.reflect.TypeVariable; | ||||||
|  | import java.lang.reflect.WildcardType; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  | import java.util.function.Predicate; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | import java.util.stream.Stream; | ||||||
|  | 
 | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertEquals; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertTrue; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.contextBuilder; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.emptyContext; | ||||||
|  | 
 | ||||||
|  | public class H09_TestUtils { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it has the given name and no bounds. | ||||||
|  |      * | ||||||
|  |      * @param name the name of the Type that should be matched. Also accepts a regex for the name. | ||||||
|  |      * @return a Predicate that matches a Type with the given name. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchNoBounds(String name) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!type.getTypeName().matches(name)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 if (bounds.getLeft() != null) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 return bounds.getRight().size() == 1 && bounds.getRight().get(0) == Object.class; | ||||||
|  |             }, | ||||||
|  |             String.format("Name: %s; Bounds: No Bounds", name) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it has the given name and bounds. | ||||||
|  |      * | ||||||
|  |      * @param name           the name of the Type that should be matched. Also accepts a regex for the name. | ||||||
|  |      * @param expectedBounds the lower Bounds that a type should have to be matched by this Predicate. | ||||||
|  |      * @return a Predicate that matches a Type with the given name and bounds. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchLowerBounds(String name, Type... expectedBounds) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!type.getTypeName().matches(name)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 return bounds.getLeft().size() == expectedBounds.length | ||||||
|  |                     && new HashSet<>(bounds.getLeft()).containsAll(List.of(expectedBounds)); | ||||||
|  |             }, | ||||||
|  |             String.format( | ||||||
|  |                 "Name: %s; Bounds: %s", | ||||||
|  |                 name, | ||||||
|  |                 Arrays.stream(expectedBounds).map(Type::getTypeName).collect(Collectors.joining(", ")) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it has the given name and bounds. | ||||||
|  |      * | ||||||
|  |      * @param name           the name of the Type that should be matched. Also accepts a regex for the name. | ||||||
|  |      * @param expectedBounds the upper Bounds that a type should have to be matched by this Predicate. | ||||||
|  |      * @return a Predicate that matches a Type with the given name and bounds. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchLowerBounds(String name, Predicate<Type>... expectedBounds) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!type.getTypeName().matches(name)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 return bounds.getLeft().size() == expectedBounds.length | ||||||
|  |                     && bounds.getLeft() | ||||||
|  |                     .stream() | ||||||
|  |                     .allMatch(actual -> Stream.of(expectedBounds).anyMatch(expected -> expected.test(actual))) | ||||||
|  |                     && Stream.of(expectedBounds).allMatch(expected -> bounds.getLeft().stream().anyMatch(expected)); | ||||||
|  |             }, | ||||||
|  |             String.format( | ||||||
|  |                 "Name: %s; Bounds: %s", | ||||||
|  |                 name, | ||||||
|  |                 Arrays.stream(expectedBounds).map(Object::toString).collect(Collectors.joining(", ")) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it has the given name and bounds. | ||||||
|  |      * | ||||||
|  |      * @param name           the name of the Type that should be matched. Also accepts a regex for the name. | ||||||
|  |      * @param expectedBounds the upper Bounds that a type should have to be matched by this Predicate. | ||||||
|  |      * @return a Predicate that matches a Type with the given name and bounds. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchUpperBounds(String name, Type... expectedBounds) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!type.getTypeName().matches(name)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 return bounds.getRight().size() == expectedBounds.length | ||||||
|  |                     && new HashSet<>(bounds.getRight()).containsAll(List.of(expectedBounds)); | ||||||
|  |             }, | ||||||
|  |             String.format( | ||||||
|  |                 "Name: %s; Bounds: %s", | ||||||
|  |                 name, | ||||||
|  |                 Arrays.stream(expectedBounds).map(Type::getTypeName).collect(Collectors.joining(", ")) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it has the given name and bounds. | ||||||
|  |      * | ||||||
|  |      * @param name           the name of the Type that should be matched. Also accepts a regex for the name. | ||||||
|  |      * @param expectedBounds the upper Bounds that a type should have to be matched by this Predicate. | ||||||
|  |      * @return a Predicate that matches a Type with the given name and bounds. | ||||||
|  |      */ | ||||||
|  |     @SafeVarargs | ||||||
|  |     public static Predicate<Type> matchUpperBounds(String name, Predicate<Type>... expectedBounds) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!type.getTypeName().matches(name)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 return bounds.getRight().size() == expectedBounds.length | ||||||
|  |                     && bounds.getRight() | ||||||
|  |                     .stream() | ||||||
|  |                     .allMatch(actual -> Stream.of(expectedBounds).anyMatch(expected -> expected.test(actual))) | ||||||
|  |                     && Stream.of(expectedBounds).allMatch(expected -> bounds.getRight().stream().anyMatch(expected)); | ||||||
|  |             }, | ||||||
|  |             String.format( | ||||||
|  |                 "Name: %s; Bounds: %s", | ||||||
|  |                 name, | ||||||
|  |                 Arrays.stream(expectedBounds).map(Object::toString).collect(Collectors.joining(", ")) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it is a wildcard type and has the given bounds. | ||||||
|  |      * | ||||||
|  |      * @param isUpperBound   indicates if the given Bounds should be the upper or lower bounds of the type | ||||||
|  |      * @param expectedBounds the expected Bounds that a type should have to be matched by this Predicate. | ||||||
|  |      * @return a Predicate that matches a wildcard type with the given bounds. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchWildcard(boolean isUpperBound, Type... expectedBounds) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!(type instanceof WildcardType wildcardType)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 if (isUpperBound) { | ||||||
|  |                     return bounds.getRight().size() == expectedBounds.length && | ||||||
|  |                         new HashSet<>(bounds.getRight()).containsAll(List.of(expectedBounds)); | ||||||
|  |                 } | ||||||
|  |                 return bounds.getLeft().size() == expectedBounds.length && | ||||||
|  |                     new HashSet<>(bounds.getLeft()).containsAll(List.of(expectedBounds)); | ||||||
|  |             }, | ||||||
|  |             String.format( | ||||||
|  |                 "Wildcard: ? %s %s", | ||||||
|  |                 isUpperBound ? "extends" : "super", | ||||||
|  |                 Arrays.stream(expectedBounds).map(Type::getTypeName).collect(Collectors.joining(" & ")) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it is a wildcard type and has the given bounds. | ||||||
|  |      * | ||||||
|  |      * @param isUpperBound   indicates if the given Bounds should be the upper or lower bounds of the type | ||||||
|  |      * @param expectedBounds the expected Bounds that a type should have to be matched by this Predicate. | ||||||
|  |      * @return a Predicate that matches a wildcard type with the given bounds. | ||||||
|  |      */ | ||||||
|  |     @SafeVarargs | ||||||
|  |     public static Predicate<Type> matchWildcard(boolean isUpperBound, Predicate<Type>... expectedBounds) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |                 if (!(type instanceof WildcardType wildcardType)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 if (isUpperBound) { | ||||||
|  |                     return bounds.getRight().size() == expectedBounds.length | ||||||
|  |                         && bounds.getRight() | ||||||
|  |                         .stream() | ||||||
|  |                         .allMatch(actual -> Stream.of(expectedBounds).anyMatch(expected -> expected.test(actual))) | ||||||
|  |                         && Stream.of(expectedBounds).allMatch(expected -> bounds.getRight().stream().anyMatch(expected)); | ||||||
|  |                 } | ||||||
|  |                 return bounds.getLeft().size() == expectedBounds.length | ||||||
|  |                     && bounds.getLeft() | ||||||
|  |                     .stream() | ||||||
|  |                     .allMatch(actual -> Stream.of(expectedBounds).anyMatch(expected -> expected.test(actual))) | ||||||
|  |                     && Stream.of(expectedBounds).allMatch(expected -> bounds.getLeft().stream().anyMatch(expected)); | ||||||
|  |             }, | ||||||
|  |             String.format( | ||||||
|  |                 "Wildcard: ? %s %s", | ||||||
|  |                 isUpperBound ? "extends" : "super", | ||||||
|  |                 Arrays.stream(expectedBounds).map(Object::toString).collect(Collectors.joining(" & ")) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it is an exact match with the given Type. | ||||||
|  |      * | ||||||
|  |      * @param expected the type that is expected. | ||||||
|  |      * @return the Predicate matching the expected type. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> match(Type expected) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> type.equals(expected), | ||||||
|  |             String.format("Type: %s", expected.getTypeName()) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it is a match with an array of the given Type. | ||||||
|  |      * | ||||||
|  |      * @param expected the type that is expected. | ||||||
|  |      * @return the Predicate matching the expected type. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchArray(Type expected) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 if (type instanceof GenericArrayType arrayType) { | ||||||
|  |                     return arrayType.getGenericComponentType().equals(expected); | ||||||
|  |                 } | ||||||
|  |                 return false; | ||||||
|  |             }, | ||||||
|  |             String.format("Type: %s", expected.getTypeName()) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it is a match with an array of the given Type. | ||||||
|  |      * | ||||||
|  |      * @param expected the type that is expected. | ||||||
|  |      * @return the Predicate matching the expected type. | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchArray(Predicate<Type> expected) { | ||||||
|  |         return new GenericPredicate( | ||||||
|  |             (type) -> { | ||||||
|  |                 if (type instanceof GenericArrayType arrayType) { | ||||||
|  |                     return expected.test(arrayType.getGenericComponentType()); | ||||||
|  |                 } | ||||||
|  |                 return false; | ||||||
|  |             }, | ||||||
|  |             String.format("Type: %s", expected.toString()) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new Predicate that matches a Type if it has the expected outer Type and the inner Types all match the | ||||||
|  |      * expectedNested types | ||||||
|  |      * | ||||||
|  |      * @param outerType      the Type of the outer type. | ||||||
|  |      * @param expectedNested an array of predicates for all inner types that should be matched. | ||||||
|  |      * @return a predicate that checks the outer and inner types of a ParameterizedType. | ||||||
|  |      */ | ||||||
|  |     @SafeVarargs | ||||||
|  |     public static Predicate<Type> matchNested(Type outerType, Predicate<Type>... expectedNested) { | ||||||
|  |         return new Predicate<>() { | ||||||
|  |             @Override | ||||||
|  |             public boolean test(Type type) { | ||||||
|  |                 if (!(type instanceof ParameterizedType parameterizedType)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 if (!parameterizedType.getRawType().equals(outerType)) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 Type[] actualType = parameterizedType.getActualTypeArguments(); | ||||||
|  |                 for (int i = 0; i < expectedNested.length; i++) { | ||||||
|  |                     if (!expectedNested[i].test(actualType[i])) { | ||||||
|  |                         return false; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             public String toString() { | ||||||
|  |                 return String.format("Type: %s; Inner Type: %s", outerType.getTypeName(), List.of(expectedNested)); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Matches if any of the supplied Types is passed to the predicate | ||||||
|  |      * | ||||||
|  |      * @param typesToMatch the types to match | ||||||
|  |      * @return a Predicate that checks if one of the supplied Types is tested | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchAny(Type... typesToMatch) { | ||||||
|  |         return Arrays.stream(typesToMatch) | ||||||
|  |             .map(H09_TestUtils::match) | ||||||
|  |             .reduce(Predicate::or) | ||||||
|  |             .orElse(new H09_TestUtils.GenericPredicate(i -> false, "Expected type is not defined")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Matches if any of the supplied Types is passed to the predicate | ||||||
|  |      * | ||||||
|  |      * @param typesToMatch the types to match | ||||||
|  |      * @return a Predicate that checks if one of the supplied Types is tested | ||||||
|  |      */ | ||||||
|  |     public static Predicate<Type> matchAny(List<Type> typesToMatch) { | ||||||
|  |         return typesToMatch.stream() | ||||||
|  |             .map(H09_TestUtils::match) | ||||||
|  |             .reduce(Predicate::or) | ||||||
|  |             .orElse(new H09_TestUtils.GenericPredicate(i -> false, "Expected type is not defined")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * This method returns the upper and lower bounds of the given type. | ||||||
|  |      * | ||||||
|  |      * <p>The returned Pair contains a list of lower bounds in the left Parameter and a list of upper bounds in the right | ||||||
|  |      * Parameter. | ||||||
|  |      * | ||||||
|  |      * <p>If the given Type does not have any lower bounds the left element of the Pair will be null. | ||||||
|  |      * | ||||||
|  |      * <p>If the given Type is not generic this method will return null. | ||||||
|  |      * | ||||||
|  |      * @param type the type to getrieve the Bounds from | ||||||
|  |      * @return a Pair containing both the upper and the lower bounds of the given Type | ||||||
|  |      */ | ||||||
|  |     public static Pair<List<Type>, List<Type>> getBounds(Type type) { | ||||||
|  |         if (type instanceof WildcardType wildcardType) { | ||||||
|  |             return ImmutablePair.of(Arrays.asList(wildcardType.getLowerBounds()), Arrays.asList(wildcardType.getUpperBounds())); | ||||||
|  |         } | ||||||
|  |         if (type instanceof ParameterizedType parameterizedType) { | ||||||
|  |             return ImmutablePair.of(null, Arrays.asList(parameterizedType.getActualTypeArguments())); | ||||||
|  |         } | ||||||
|  |         if (type instanceof TypeVariable<?> typeVariable) { | ||||||
|  |             return ImmutablePair.of(null, Arrays.asList(typeVariable.getBounds())); | ||||||
|  |         } | ||||||
|  |         if (type instanceof GenericArrayType) { | ||||||
|  |             return ImmutablePair.of(null, List.of(Object[].class)); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieves the inner type of the given Type. | ||||||
|  |      * | ||||||
|  |      * @param type the type to get the inner type from. | ||||||
|  |      * @return the inner type of the given type. Returns empty list if no inner type is present. | ||||||
|  |      */ | ||||||
|  |     public static List<Type> getInnerTypes(Type type) { | ||||||
|  |         if (!(type instanceof ParameterizedType parameterizedType)) { | ||||||
|  |             return List.of(); | ||||||
|  |         } | ||||||
|  |         return Arrays.asList(parameterizedType.getActualTypeArguments()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieves the super Types of the given Type if it is a class. Returns upper bounds otherwise. | ||||||
|  |      * | ||||||
|  |      * @param type the type to get the super types from. | ||||||
|  |      * @return the super types or upper bounds of the given type. Returns a list containing only Object if no supertype can be | ||||||
|  |      * determined. | ||||||
|  |      */ | ||||||
|  |     public static List<Type> getGenericSuperTypes(Type type) { | ||||||
|  |         if (type instanceof Class<?> clazz) { | ||||||
|  |             List<Type> superTypes = new ArrayList<>(); | ||||||
|  |             if (clazz.getGenericSuperclass() != null) { | ||||||
|  |                 superTypes.add(clazz.getGenericSuperclass()); | ||||||
|  |             } | ||||||
|  |             if (clazz.getGenericInterfaces().length > 0) { | ||||||
|  |                 superTypes.addAll(List.of(clazz.getGenericInterfaces())); | ||||||
|  |             } | ||||||
|  |             return superTypes; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Pair<List<Type>, List<Type>> bounds = getBounds(type); | ||||||
|  |         if (bounds != null) { | ||||||
|  |             return bounds.getRight(); | ||||||
|  |         } | ||||||
|  |         return List.of(Object.class); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieves the return type of the given Method. | ||||||
|  |      * | ||||||
|  |      * @param method the method to get the return type from. | ||||||
|  |      * @return the return type of the given method. | ||||||
|  |      */ | ||||||
|  |     public static Type getReturnType(Method method) { | ||||||
|  |         return method.getGenericReturnType(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieves all parameters of the given method. Returned parameters may not generic. | ||||||
|  |      * | ||||||
|  |      * @param method the method that the generic types should be retrieved from. | ||||||
|  |      * @param regex  a regex that is used to filter all generic type names. | ||||||
|  |      * @return a List containing all types of the parameters from the method whose type names match the given regex. | ||||||
|  |      */ | ||||||
|  |     public static List<Type> getTypeParameters(Method method, String regex) { | ||||||
|  |         return Arrays.stream(method.getGenericParameterTypes()).filter(t -> t.getTypeName().matches(regex)).toList(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieves all generic types that are defined by the given method. | ||||||
|  |      * | ||||||
|  |      * @param method the method that the generic types should be retrieved from. | ||||||
|  |      * @param regex  a regex that is used to filter all generic type names. | ||||||
|  |      * @return a List containing all defined types that match the given regex. | ||||||
|  |      */ | ||||||
|  |     public static List<Type> getDefinedTypes(Method method, String regex) { | ||||||
|  |         return Arrays.stream(method.getTypeParameters()).filter(t -> t.getTypeName().matches(regex)).map(t -> (Type) t).toList(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieves all generic types that are defined by the given class. | ||||||
|  |      * | ||||||
|  |      * @param clazz the class that the generic types should be retrieved from. | ||||||
|  |      * @param regex a regex that is used to filter all generic type names. | ||||||
|  |      * @return a List containing all defined types that match the given regex. | ||||||
|  |      */ | ||||||
|  |     public static List<Type> getDefinedTypes(Class clazz, String regex) { | ||||||
|  |         return Arrays.stream(clazz.getTypeParameters()).filter(t -> t.getTypeName().matches(regex)).map(t -> (Type) t).toList(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Asserts that the given {@link Class} defines a certain set a generic Parameters. | ||||||
|  |      * | ||||||
|  |      * @param clazz    the Class that should be tested. | ||||||
|  |      * @param expected a set of predicates that is used to check if all defined generic Types match an expected Type. | ||||||
|  |      */ | ||||||
|  |     public static void assertDefinedParameters(Class<?> clazz, Set<Predicate<Type>> expected) { | ||||||
|  | 
 | ||||||
|  |         List<TypeVariable<?>> typeVariable = Arrays.asList(clazz.getTypeParameters()); | ||||||
|  |         CtType<?> ctClass = (CtType<?>) BasicTypeLink.of(clazz).getCtElement(); | ||||||
|  |         var actualNames = | ||||||
|  |             ctClass.getFormalCtTypeParameters().stream().map(CtType::toStringDebug).map(s -> s.replace("\n", "")).toList(); | ||||||
|  |         Context context = contextBuilder() | ||||||
|  |             .add("expected", expected) | ||||||
|  |             .add("actual", actualNames) | ||||||
|  |             .build(); | ||||||
|  | 
 | ||||||
|  |         assertTrue( | ||||||
|  |             !typeVariable.isEmpty(), | ||||||
|  |             emptyContext(), | ||||||
|  |             r -> clazz.getSimpleName() + " does not have any generic parameters." | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         assertEquals( | ||||||
|  |             expected.size(), | ||||||
|  |             typeVariable.size(), | ||||||
|  |             context, | ||||||
|  |             r -> clazz.getSimpleName() + " does not have the expected number of generic parameters." | ||||||
|  |         ); | ||||||
|  |         typeVariable.forEach(a -> | ||||||
|  |             assertTrue( | ||||||
|  |                 expected.stream().anyMatch(e -> e.test(a)), | ||||||
|  |                 context, | ||||||
|  |                 r -> String.format("The type parameter %s of %s do not match any expected types.", a, clazz.getSimpleName()) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Asserts that the given {@link Method} defines a specific set of generic types. | ||||||
|  |      * | ||||||
|  |      * @param method   the method that is checked for type definitions. | ||||||
|  |      * @param expected a set of predicates that is used to check if all defined generic Types match an expected Type. | ||||||
|  |      */ | ||||||
|  |     public static void assertDefinedParameters(Method method, Set<Predicate<Type>> expected) { | ||||||
|  | 
 | ||||||
|  |         List<TypeVariable<?>> typeVariable = Arrays.asList(method.getTypeParameters()); | ||||||
|  |         CtMethod<?> ctMethod = BasicMethodLink.of(method).getCtElement(); | ||||||
|  |         var actualNames = ctMethod.getFormalCtTypeParameters() | ||||||
|  |             .stream() | ||||||
|  |             .map(CtTypeParameter::toStringDebug) | ||||||
|  |             .map(s -> s.replace("\n", "")) | ||||||
|  |             .toList(); | ||||||
|  |         Context context = contextBuilder() | ||||||
|  |             .add("expected", expected) | ||||||
|  |             .add("actual", actualNames) | ||||||
|  |             .build(); | ||||||
|  | 
 | ||||||
|  |         assertTrue(!typeVariable.isEmpty(), emptyContext(), r -> method.getName() + " does not have any generic parameters."); | ||||||
|  | 
 | ||||||
|  |         assertEquals( | ||||||
|  |             expected.size(), | ||||||
|  |             typeVariable.size(), | ||||||
|  |             context, | ||||||
|  |             r -> method.getName() + " does not have the expected number of generic parameters." | ||||||
|  |         ); | ||||||
|  |         typeVariable.forEach(a -> | ||||||
|  |             assertTrue( | ||||||
|  |                 expected.stream().anyMatch(e -> e.test(a)), | ||||||
|  |                 context, | ||||||
|  |                 r -> String.format("The type parameter %s of %s do not match any expected types.", a, method.getName()) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Asserts that the given {@link Method} has a return type that matches the given {@link Predicate}. | ||||||
|  |      * | ||||||
|  |      * @param method   the method that should be tested. | ||||||
|  |      * @param expected the {@link Predicate} that shoul be used to check the return type. | ||||||
|  |      */ | ||||||
|  |     public static void assertReturnParameter(Method method, Predicate<Type> expected) { | ||||||
|  |         Type type = method.getGenericReturnType(); | ||||||
|  | 
 | ||||||
|  |         CtMethod<?> ctMethod = BasicMethodLink.of(method).getCtElement(); | ||||||
|  |         var actualNames = ctMethod.getType().toStringDebug().replace("\n", ""); | ||||||
|  |         Context context = contextBuilder() | ||||||
|  |             .add("actual type", actualNames) | ||||||
|  |             .add("expected", expected) | ||||||
|  |             .build(); | ||||||
|  | 
 | ||||||
|  |         assertTrue(expected.test(type), context, r -> String.format("%s has a wrong return type.", method.getName())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Asserts that the given {@link Method} has a correct list of parameters each parameter is checked with the given | ||||||
|  |      * {@link Predicate} for the index. | ||||||
|  |      * | ||||||
|  |      * @param method   the method that should be checked | ||||||
|  |      * @param expected a list containing a {@link Predicate} for each Parameter of the method. | ||||||
|  |      */ | ||||||
|  |     public static void assertParameters(Method method, List<Predicate<Type>> expected) { | ||||||
|  |         Type[] type = method.getGenericParameterTypes(); | ||||||
|  | 
 | ||||||
|  |         assertEquals( | ||||||
|  |             expected.size(), | ||||||
|  |             type.length, | ||||||
|  |             emptyContext(), r -> String.format("The method %s() does not have the correct amount of parameters", method.getName()) | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         CtMethod<?> ctMethod = BasicMethodLink.of(method).getCtElement(); | ||||||
|  |         var actualNames = | ||||||
|  |             ctMethod.getParameters() | ||||||
|  |                 .stream() | ||||||
|  |                 .map(CtParameter::getType) | ||||||
|  |                 .map(CtTypeReference::toStringDebug) | ||||||
|  |                 .map(s -> s.replace("\n", "")) | ||||||
|  |                 .toList(); | ||||||
|  | 
 | ||||||
|  |         for (int i = 0; i < type.length; i++) { | ||||||
|  |             int finalI = i; | ||||||
|  | 
 | ||||||
|  |             Context context = contextBuilder() | ||||||
|  |                 .add("actual type", actualNames.get(i)) | ||||||
|  |                 .add("expected", expected.get(i)) | ||||||
|  |                 .build(); | ||||||
|  | 
 | ||||||
|  |             assertTrue( | ||||||
|  |                 expected.get(i).test(type[i]), | ||||||
|  |                 context, | ||||||
|  |                 r -> String.format("%s has a wrong parameter at index %d.", method.getName(), finalI) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Asserts that the given field has a {@link Type} that matches the given {@link Predicate}. | ||||||
|  |      * | ||||||
|  |      * @param field    the field that should be checked. | ||||||
|  |      * @param expected the {@link Predicate} that is used to check if the Field has a correct Type. | ||||||
|  |      */ | ||||||
|  |     public static void assertType(Field field, Predicate<Type> expected) { | ||||||
|  |         Type type = field.getGenericType(); | ||||||
|  | 
 | ||||||
|  |         CtField<?> ctField = | ||||||
|  |             BasicTypeLink.of(field.getDeclaringClass()).getCtElement().filterChildren(new TypeFilter<>(CtField.class) { | ||||||
|  |                 @Override | ||||||
|  |                 public boolean matches(CtField element) { | ||||||
|  |                     return super.matches(element) && element.getSimpleName().equals(field.getName()); | ||||||
|  |                 } | ||||||
|  |             }).first(); | ||||||
|  |         var actualNames = ctField.getType().toStringDebug(); | ||||||
|  | 
 | ||||||
|  |         Context context = contextBuilder() | ||||||
|  |             .add("actual type", actualNames) | ||||||
|  |             .add("expected", expected) | ||||||
|  |             .build(); | ||||||
|  | 
 | ||||||
|  |         assertTrue(expected.test(type), context, r -> String.format("%s has a wrong type.", field.getName())); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Asserts that the given method is generic. | ||||||
|  |      * | ||||||
|  |      * @param toTest a method reference to the method that should be checked. | ||||||
|  |      */ | ||||||
|  |     public static void assertGeneric(Method toTest) { | ||||||
|  | 
 | ||||||
|  |         Predicate<Method> isGeneric = (method) -> !getTypeParameters(method, ".*").isEmpty(); | ||||||
|  |         isGeneric = isGeneric.or((method) -> getBounds(getReturnType(method)) != null); | ||||||
|  | 
 | ||||||
|  |         assertTrue( | ||||||
|  |             isGeneric.test(toTest), | ||||||
|  |             emptyContext(), | ||||||
|  |             r -> String.format("The method %s() is not Generic.", toTest.getName()) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A simple Predicate that can store a custom toString() method for better readability. | ||||||
|  |      */ | ||||||
|  |     public static class GenericPredicate implements Predicate<Type> { | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * The description that should be displayed if toString() is called. | ||||||
|  |          */ | ||||||
|  |         private final String description; | ||||||
|  |         /** | ||||||
|  |          * The underlying predicate. | ||||||
|  |          */ | ||||||
|  |         private final Predicate<Type> predicate; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Creates a new {@link GenericPredicate} from a {@link Predicate} and a short description that describes what the | ||||||
|  |          * predicate matches. | ||||||
|  |          * | ||||||
|  |          * @param predicate   the predicate that should be used to match any object. | ||||||
|  |          * @param description the description of what the predicate matches. | ||||||
|  |          */ | ||||||
|  |         GenericPredicate(Predicate<Type> predicate, String description) { | ||||||
|  |             this.predicate = predicate; | ||||||
|  |             this.description = description; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean test(Type type) { | ||||||
|  |             return predicate.test(type); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @NotNull | ||||||
|  |         @Override | ||||||
|  |         public Predicate<Type> and(@NotNull Predicate<? super Type> other) { | ||||||
|  |             return new GenericPredicate(predicate.and(other), "(" + this.description + " and " + other + ")"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @NotNull | ||||||
|  |         @Override | ||||||
|  |         public Predicate<Type> negate() { | ||||||
|  |             return new GenericPredicate(predicate.negate(), "(not " + description + ")"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @NotNull | ||||||
|  |         @Override | ||||||
|  |         public Predicate<Type> or(@NotNull Predicate<? super Type> other) { | ||||||
|  |             return new GenericPredicate(predicate.or(other), "(" + this.description + " or " + other + ")"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public String toString() { | ||||||
|  |             return description; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										191
									
								
								H09/src/graderPublic/java/h09/ReflectionUtils.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								H09/src/graderPublic/java/h09/ReflectionUtils.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,191 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import com.google.common.primitives.Primitives; | ||||||
|  | import sun.misc.Unsafe; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.lang.reflect.Modifier; | ||||||
|  | import java.util.ArrayDeque; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.Deque; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Optional; | ||||||
|  | 
 | ||||||
|  | public class ReflectionUtils { | ||||||
|  | 
 | ||||||
|  |     public static void setFieldValue(Object instance, String fieldName, Object value) { | ||||||
|  |         try { | ||||||
|  |             Class<?> objectClass = instance.getClass(); | ||||||
|  |             Field declaredField; | ||||||
|  |             try { | ||||||
|  |                 declaredField = objectClass.getDeclaredField(fieldName); | ||||||
|  |             } catch (NoSuchFieldException e) { | ||||||
|  |                 declaredField = getSuperClassesIncludingSelf(objectClass).stream() | ||||||
|  |                     .filter((c) -> List.of(c.getDeclaredFields()).stream() | ||||||
|  |                         .map(Field::getName) | ||||||
|  |                         .anyMatch(name -> name.equals(fieldName)) | ||||||
|  |                     ) | ||||||
|  |                     .map((c) -> { | ||||||
|  |                         try { | ||||||
|  |                             return c.getDeclaredField(fieldName); | ||||||
|  |                         } catch (NoSuchFieldException ex) { | ||||||
|  |                             throw new RuntimeException(ex); | ||||||
|  |                         } | ||||||
|  |                     }) | ||||||
|  |                     .findFirst() | ||||||
|  |                     .orElseThrow(() -> new NoSuchFieldException(e.getMessage())); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //best case field in non Final | ||||||
|  |             if (!Modifier.isFinal(declaredField.getModifiers())) { | ||||||
|  |                 try { | ||||||
|  |                     declaredField.setAccessible(true); | ||||||
|  |                     declaredField.set(instance, value); | ||||||
|  |                     return; | ||||||
|  |                 } catch (Exception ignored) { | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //field has setter | ||||||
|  |             Optional<Method> setter = Arrays | ||||||
|  |                 .stream(objectClass.getDeclaredMethods()) | ||||||
|  |                 .filter( | ||||||
|  |                     m -> m.getName().equalsIgnoreCase("set" + fieldName) | ||||||
|  |                 ).findFirst(); | ||||||
|  |             if (setter.isPresent()) { | ||||||
|  |                 setter.get().invoke(instance, value); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //rely on Unsafe to set value | ||||||
|  |             Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); | ||||||
|  |             unsafeField.setAccessible(true); | ||||||
|  |             Unsafe unsafe = (Unsafe) unsafeField.get(null); | ||||||
|  | 
 | ||||||
|  |             Field theInternalUnsafeField = Unsafe.class.getDeclaredField("theInternalUnsafe"); | ||||||
|  |             theInternalUnsafeField.setAccessible(true); | ||||||
|  |             Object theInternalUnsafe = theInternalUnsafeField.get(null); | ||||||
|  | 
 | ||||||
|  |             Method offset = Class.forName("jdk.internal.misc.Unsafe").getMethod("objectFieldOffset", Field.class); | ||||||
|  |             unsafe.putBoolean(offset, 12, true); | ||||||
|  | 
 | ||||||
|  |             switch (value) { | ||||||
|  |                 case Boolean val -> unsafe.putBoolean(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 case Character val -> unsafe.putChar(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 case Short val -> unsafe.putShort(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 case Integer val -> unsafe.putInt(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 case Long val -> unsafe.putLong(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 case Double val -> unsafe.putDouble(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 case Float val -> unsafe.putFloat(instance, (long) offset.invoke(theInternalUnsafe, declaredField), val); | ||||||
|  |                 default -> unsafe.putObject(instance, (long) offset.invoke(theInternalUnsafe, declaredField), value); | ||||||
|  |             } | ||||||
|  |         } catch (IllegalAccessException | NoSuchFieldException | ClassNotFoundException | NoSuchMethodException | | ||||||
|  |                  InvocationTargetException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static <T> T getFieldValue(Object instance, String fieldName) { | ||||||
|  |         Field f; | ||||||
|  |         Class<?> fieldType = null; | ||||||
|  |         try { | ||||||
|  |             f = instance.getClass().getDeclaredField(fieldName); | ||||||
|  | 
 | ||||||
|  |             try { | ||||||
|  |                 f.setAccessible(true); | ||||||
|  |                 return (T) f.get(instance); | ||||||
|  |             } catch (Exception ignored) { | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             fieldType = f.getType(); | ||||||
|  |             if (Primitives.isWrapperType(fieldType)) { | ||||||
|  |                 fieldType = Primitives.unwrap(fieldType); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); | ||||||
|  |             unsafeField.setAccessible(true); | ||||||
|  |             Unsafe unsafe = (Unsafe) unsafeField.get(null); | ||||||
|  | 
 | ||||||
|  |             Field theInternalUnsafeField = Unsafe.class.getDeclaredField("theInternalUnsafe"); | ||||||
|  |             theInternalUnsafeField.setAccessible(true); | ||||||
|  |             Object theInternalUnsafe = theInternalUnsafeField.get(null); | ||||||
|  | 
 | ||||||
|  |             Method offset = Class.forName("jdk.internal.misc.Unsafe").getMethod("objectFieldOffset", Field.class); | ||||||
|  |             unsafe.putBoolean(offset, 12, true); | ||||||
|  | 
 | ||||||
|  |             Object fieldValue; | ||||||
|  |             if (boolean.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getBoolean(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (byte.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getByte(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (short.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getShort(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (int.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getInt(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (long.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getLong(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (float.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getFloat(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (double.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getDouble(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else if (char.class == fieldType) { | ||||||
|  |                 fieldValue = unsafe.getChar(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } else { | ||||||
|  |                 fieldValue = unsafe.getObject(instance, (long) offset.invoke(theInternalUnsafe, f)); | ||||||
|  |             } | ||||||
|  |             return (T) fieldValue; | ||||||
|  |         } catch (NoSuchFieldException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | | ||||||
|  |                  IllegalAccessException e) { | ||||||
|  |             throw new RuntimeException( | ||||||
|  |                 "Could not set value for Field %s(%s) in %s. Please do not access this field.".formatted( | ||||||
|  |                     fieldName, | ||||||
|  |                     fieldType, | ||||||
|  |                     instance.getClass() | ||||||
|  |                 ), e | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void copyFields(Object source, Object dest) { | ||||||
|  |         for (Field f : source.getClass().getDeclaredFields()) { | ||||||
|  |             setFieldValue(dest, f.getName(), getFieldValue(source, f.getName())); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static boolean actsLikePrimitive(Class<?> type) { | ||||||
|  |         return type.isPrimitive() || | ||||||
|  |             Enum.class.isAssignableFrom(type) || | ||||||
|  |             Primitives.isWrapperType(type) || | ||||||
|  |             type == String.class; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static List<Class<?>> getSuperClassesIncludingSelf(Class<?> clazz) { | ||||||
|  |         List<Class<?>> classes = new ArrayList<>(); | ||||||
|  |         Deque<Class<?>> classDeque = new ArrayDeque<>(); | ||||||
|  | 
 | ||||||
|  |         classDeque.add(clazz); | ||||||
|  | 
 | ||||||
|  |         while ((clazz = classDeque.peekFirst()) != null) { | ||||||
|  |             classDeque.pop(); | ||||||
|  | 
 | ||||||
|  |             classes.add(clazz); | ||||||
|  |             if (clazz.getSuperclass() != null) { | ||||||
|  |                 classDeque.add(clazz.getSuperclass()); | ||||||
|  |             } | ||||||
|  |             if (clazz.getInterfaces().length > 0) { | ||||||
|  |                 classDeque.addAll(List.of(clazz.getInterfaces())); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         return classes; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static boolean isObjectMethod(Method methodToCheck) { | ||||||
|  |         List<String> objectMethods = | ||||||
|  |             List.of("getClass", "hashCode", "equals", "clone", "toString", "notify", "notifyAll", "wait", "finalize"); | ||||||
|  |         return objectMethods.contains(methodToCheck.getName()); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										101
									
								
								H09/src/graderPublic/java/h09/StackOfObjectsTestPublic.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								H09/src/graderPublic/java/h09/StackOfObjectsTestPublic.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,101 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.sourcegrade.jagr.api.rubric.TestForSubmission; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.reflections.BasicTypeLink; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.lang.reflect.GenericArrayType; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.lang.reflect.Type; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | import static h09.H09_TestUtils.assertDefinedParameters; | ||||||
|  | import static h09.H09_TestUtils.assertParameters; | ||||||
|  | import static h09.H09_TestUtils.assertReturnParameter; | ||||||
|  | import static h09.H09_TestUtils.assertType; | ||||||
|  | import static h09.H09_TestUtils.getTypeParameters; | ||||||
|  | import static h09.H09_TestUtils.match; | ||||||
|  | import static h09.H09_TestUtils.matchArray; | ||||||
|  | import static h09.H09_TestUtils.matchNested; | ||||||
|  | import static h09.H09_TestUtils.matchNoBounds; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertNotNull; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.emptyContext; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.match.BasicStringMatchers.identical; | ||||||
|  | 
 | ||||||
|  | @TestForSubmission | ||||||
|  | public class StackOfObjectsTestPublic { | ||||||
|  | 
 | ||||||
|  |     BasicTypeLink stackLink; | ||||||
|  |     Class<?> ctClassStack; | ||||||
|  |     Method get; | ||||||
|  |     Method pop; | ||||||
|  |     Method push; | ||||||
|  |     Method remove; | ||||||
|  |     Method of; | ||||||
|  |     Field objs; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     public void setUp() { | ||||||
|  |         stackLink = BasicTypeLink.of(StackOfObjects.class); | ||||||
|  |         ctClassStack = stackLink.reflection(); | ||||||
|  |         get = stackLink.getMethod(identical("get")).reflection(); | ||||||
|  |         pop = stackLink.getMethod(identical("pop")).reflection(); | ||||||
|  |         push = stackLink.getMethod(identical("push")).reflection(); | ||||||
|  |         remove = stackLink.getMethod(identical("remove")).reflection(); | ||||||
|  |         of = stackLink.getMethod(identical("of")).reflection(); | ||||||
|  |         objs = stackLink.getField(identical("objs")).reflection(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testClassParameter() { | ||||||
|  |         assertDefinedParameters(ctClassStack, Set.of(matchNoBounds("O"))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testObjsType() { | ||||||
|  |         assertType(objs, matchArray(matchNoBounds("O"))); | ||||||
|  |         assertNotNull( | ||||||
|  |             ReflectionUtils.getFieldValue(new StackOfObjects<>(), "objs"), | ||||||
|  |             emptyContext(), | ||||||
|  |             r -> "Field objs is not correctly initialized" | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testPushParameter() { | ||||||
|  |         assertParameters(push, List.of(matchNoBounds("O"))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testRemoveParameter() { | ||||||
|  |         assertParameters(remove, List.of(matchNoBounds("O"))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testPopParameter() { | ||||||
|  |         assertReturnParameter(pop, matchNoBounds("O")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testGetParameter() { | ||||||
|  |         assertReturnParameter(get, matchNoBounds("O")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testOfParameter() { | ||||||
|  |         assertDefinedParameters(of, Set.of(matchNoBounds("O"))); | ||||||
|  | 
 | ||||||
|  |         List<Type> types = getTypeParameters(of, ".*"); | ||||||
|  | 
 | ||||||
|  |         assertReturnParameter( | ||||||
|  |             of, | ||||||
|  |             matchNested(StackOfObjects.class, match(((GenericArrayType) types.get(0)).getGenericComponentType())) | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         assertParameters(of, List.of(match(types.get(0)))); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										140
									
								
								H09/src/graderPublic/java/h09/WaterEnclosureTestPublic.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								H09/src/graderPublic/java/h09/WaterEnclosureTestPublic.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import h09.abilities.Swims; | ||||||
|  | import h09.animals.Penguin; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.Arguments; | ||||||
|  | import org.junit.jupiter.params.provider.MethodSource; | ||||||
|  | import org.sourcegrade.jagr.api.rubric.TestForSubmission; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.assertions.Context; | ||||||
|  | import org.tudalgo.algoutils.tutor.general.reflections.BasicTypeLink; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Stream; | ||||||
|  | 
 | ||||||
|  | import static org.mockito.Mockito.CALLS_REAL_METHODS; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
|  | import static org.mockito.Mockito.never; | ||||||
|  | import static org.mockito.Mockito.verify; | ||||||
|  | import static org.mockito.Mockito.when; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertTrue; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.contextBuilder; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.fail; | ||||||
|  | import static org.tudalgo.algoutils.tutor.general.match.BasicStringMatchers.identical; | ||||||
|  | 
 | ||||||
|  | @TestForSubmission | ||||||
|  | public class WaterEnclosureTestPublic { | ||||||
|  | 
 | ||||||
|  |     BasicTypeLink waterEnclosureLink; | ||||||
|  |     Class<?> waterEnclosureClass; | ||||||
|  |     Method getStack; | ||||||
|  |     Method feed; | ||||||
|  |     Method getMeanElevation; | ||||||
|  |     Field animals; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     public void setUp() { | ||||||
|  |         waterEnclosureLink = BasicTypeLink.of(WaterEnclosure.class); | ||||||
|  |         waterEnclosureClass = waterEnclosureLink.reflection(); | ||||||
|  |         getStack = waterEnclosureLink.getMethod(identical("getStack")).reflection(); | ||||||
|  |         feed = waterEnclosureLink.getMethod(identical("feed")).reflection(); | ||||||
|  |         getMeanElevation = waterEnclosureLink.getMethod(identical("getMeanElevation")).reflection(); | ||||||
|  |         animals = waterEnclosureLink.getField(identical("animals")).reflection(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testFeed() { | ||||||
|  | 
 | ||||||
|  |         WaterEnclosure enclosure = new WaterEnclosure(); | ||||||
|  |         List<Penguin> animals = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|  |         for (int i = 0; i < 10; i++) { | ||||||
|  |             Penguin mock = mock(Penguin.class, CALLS_REAL_METHODS); | ||||||
|  |             ReflectionUtils.setFieldValue(mock, "isHungry", false); | ||||||
|  |             ReflectionUtils.setFieldValue(mock, "elevation", Swims.MAX_ELEVATION); | ||||||
|  |             if (i % 2 == 0) { | ||||||
|  |                 ReflectionUtils.setFieldValue(mock, "isHungry", true); | ||||||
|  |             } | ||||||
|  |             if (i % 3 == 0) { | ||||||
|  |                 ReflectionUtils.setFieldValue(mock, "elevation", Swims.MIN_ELEVATION); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             enclosure.getStack().push(mock); | ||||||
|  |             animals.add(mock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Context context = contextBuilder() | ||||||
|  |             .add("Animals", animals) | ||||||
|  |             .build(); | ||||||
|  | 
 | ||||||
|  |         enclosure.feed(); | ||||||
|  | 
 | ||||||
|  |         for (int i = 0; i < 10; i++) { | ||||||
|  |             if (enclosure.getStack().size() <= 0) { | ||||||
|  |                 fail(context, r -> "WaterEnclosure does not have correct number of Animals after feeding."); | ||||||
|  |             } | ||||||
|  |             Penguin mock = (Penguin) enclosure.getStack().pop(); | ||||||
|  | 
 | ||||||
|  |             int id = animals.indexOf(mock); | ||||||
|  | 
 | ||||||
|  |             if (id % 2 == 0) { | ||||||
|  |                 verify(mock).eat(); | ||||||
|  |                 verify(mock).swimDown(); | ||||||
|  |                 if (i % 3 == 0) { | ||||||
|  |                     verify(mock).swimUp(); | ||||||
|  |                 } else { | ||||||
|  |                     verify(mock, never()).swimUp(); | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 verify(mock, never()).eat(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @MethodSource("provide_testGetMeanElevation") | ||||||
|  |     public void testGetMeanElevation(List<Double> elevations, double expected) { | ||||||
|  | 
 | ||||||
|  |         WaterEnclosure enclosure = new WaterEnclosure<>(); | ||||||
|  | 
 | ||||||
|  |         for (double elevation : elevations) { | ||||||
|  |             Penguin mock = mock(Penguin.class); | ||||||
|  |             when(mock.getElevation()).thenReturn((float) elevation); | ||||||
|  | 
 | ||||||
|  |             enclosure.getStack().push(mock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         float actual = enclosure.getMeanElevation(); | ||||||
|  | 
 | ||||||
|  |         Context context = contextBuilder() | ||||||
|  |             .add("Elevations", elevations) | ||||||
|  |             .build(); | ||||||
|  | 
 | ||||||
|  |         double error = 0.00001; | ||||||
|  | 
 | ||||||
|  |         assertTrue( | ||||||
|  |             Math.abs(Math.abs(expected) - Math.abs(actual)) < error, | ||||||
|  |             context, | ||||||
|  |             r -> "Average Elevation is not calculated correctly." | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Stream<Arguments> provide_testGetMeanElevation() { | ||||||
|  |         return Stream.of( | ||||||
|  |             Arguments.of(List.of(0d, 0d, 0d, 0d, 0d, 0d), 0.0), | ||||||
|  |             Arguments.of(List.of(0d, -1d, -2d, -3d, -4d, -5d), -2.5), | ||||||
|  |             Arguments.of(List.of(-1d, -2d, -3d, -4d, -5d, -6d), -3.5), | ||||||
|  |             Arguments.of(List.of(-6d, -5d, -4d, -3d, -2d, -1d), -3.5), | ||||||
|  |             Arguments.of(List.of(-3d, -5d, 0d, -3d, -10d, -1d), -3.6666667), | ||||||
|  |             Arguments.of(List.of(-3d, -2d, 0d, -3d, -2d, -3d), -2.1666667), | ||||||
|  |             Arguments.of(List.of(-2d, -2d, -2d, -2d, -2d, -2d), -2.0), | ||||||
|  |             Arguments.of(List.of(-1d, -2d, -2d), -1.6666666) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										119
									
								
								H09/src/main/java/h09/Enclosure.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								H09/src/main/java/h09/Enclosure.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import h09.animals.Animal; | ||||||
|  | import org.tudalgo.algoutils.student.annotation.DoNotTouch; | ||||||
|  | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
|  | 
 | ||||||
|  | import java.util.function.Consumer; | ||||||
|  | import java.util.function.Predicate; | ||||||
|  | import java.util.function.Supplier; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class implementing {@link Enclosure} has the ability to contain and manage a stack of {@link Animal}s. | ||||||
|  |  */ | ||||||
|  | // TODO: H9.2.1 | ||||||
|  | public interface Enclosure<TODO_REPLACE> { | ||||||
|  |     /** | ||||||
|  |      * @return the stack of animals which is used manage the contained {@link Animal}s | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.2.1") | ||||||
|  |     // TODO: H9.2.1 | ||||||
|  |     StackOfObjects getStack(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Feeds all contained animals. | ||||||
|  |      */ | ||||||
|  |     @DoNotTouch | ||||||
|  |     void feed(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Counts the number of hungry {@link Animal}s in the enclosure. | ||||||
|  |      * | ||||||
|  |      * @return number of hungry {@link Animal}s in the enclosure | ||||||
|  |      */ | ||||||
|  |     @DoNotTouch | ||||||
|  |     @SuppressWarnings("RedundantCast") | ||||||
|  |     default int countHungry() { | ||||||
|  |         int count = 0; | ||||||
|  |         for (int i = 0; i < this.getStack().size(); i++) | ||||||
|  |             if (((Animal) this.getStack().get(i)).isHungry()) count++; | ||||||
|  |         return count; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Applies a {@link Consumer} operation on each {@link Animal} in the enclosure. | ||||||
|  |      * | ||||||
|  |      * @param func operation to be applied to each {@link Animal} in the enclosure | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.3.1") // TODO: H9.3.1 | ||||||
|  |     default void forEach(Consumer func) { | ||||||
|  |         for (int i = 0; i < this.getStack().size(); i++) | ||||||
|  |             func.accept(this.getStack().get(i)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Tests a {@link Predicate} operation on each {@link Animal} in the enclosure and removes every {@link Animal} | ||||||
|  |      * which does not satisfy the predicate. That means only {@link Animal}s for which the predicate returns 'true' | ||||||
|  |      * remain in the enclosure. | ||||||
|  |      * | ||||||
|  |      * @param filter operation to test to each {@link Animal} in the enclosure | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.3.2") // TODO: H9.3.2 | ||||||
|  |     default void filterObj(Predicate filter) { | ||||||
|  |         for (int i = 0; i < this.getStack().size(); i++) { | ||||||
|  |             Object a = this.getStack().get(i); | ||||||
|  |             if (!filter.test(a)) { | ||||||
|  |                 this.getStack().remove(a); | ||||||
|  |                 i--; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a new {@link Enclosure} that contains only the {@link Animal}s of the previous {@link Enclosure} which | ||||||
|  |      * satisfied the predicate. That means only {@link Animal}s for which the predicate returns 'true' are included | ||||||
|  |      * in the new enclosure. | ||||||
|  |      * | ||||||
|  |      * @param supp   {@link Supplier} which is used to create the new {@link Enclosure} to be returned | ||||||
|  |      * @param filter operation to test to each {@link Animal} in the enclosure | ||||||
|  |      * @param <E>    Type of the new {@link Enclosure} which is returned | ||||||
|  |      * @return a new {@link Enclosure} that contains only the {@link Animal}s of the previous {@link Enclosure} which | ||||||
|  |      * satisfied the predicate | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.3.3") | ||||||
|  |     default Enclosure filterFunc(Supplier<Enclosure> supp, Predicate<Object> filter) { | ||||||
|  |         // TODO: H9.3.3 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H9.3.3 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@link Predicate} which returns true if an {@link Animal} is old (that means older than 10). | ||||||
|  |      */ | ||||||
|  |     @DoNotTouch | ||||||
|  |     Predicate<Animal> IS_OLD = animal -> animal.getAge() > 10; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@link Predicate} which returns true if a swimming {@link Animal} swims at a low elevation. | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.4.1") // TODO: H9.4.1 | ||||||
|  |     Predicate SWIMS_AT_LOW_ELEVATION = null; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@link Consumer} which lets the consumed {@link Animal} eat and sleep. | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.4.2") // TODO: H9.4.2 | ||||||
|  |     Consumer FEED_AND_SLEEP = null; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a {@link Consumer} which lets the consumed swimming {@link Animal} eat and swim down. | ||||||
|  |      * | ||||||
|  |      * @param <T> Type of the swimming {@link Animal} to eat and swim down | ||||||
|  |      * @return a {@link Consumer} which lets the consumed swimming {@link Animal} eat and swim down | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.4.3") | ||||||
|  |     static Consumer EAT_AND_SINK() { | ||||||
|  |         // TODO: H9.4.3 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H9.4.3 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								H09/src/main/java/h09/GroundEnclosure.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								H09/src/main/java/h09/GroundEnclosure.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import h09.abilities.Walks; | ||||||
|  | import h09.animals.Animal; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class implementing {@link GroundEnclosure} has the ability to contain and manage a stack of | ||||||
|  |  * {@link Animal}s which have the ability to {@link Walks}. | ||||||
|  |  */ | ||||||
|  | public class GroundEnclosure<A extends Animal & Walks> implements Enclosure<A> { | ||||||
|  |     /** | ||||||
|  |      * The stack of animals which is used manage the contained Animals. | ||||||
|  |      */ | ||||||
|  |     final StackOfObjects<A> animals = new StackOfObjects<>(); | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public StackOfObjects<A> getStack() { | ||||||
|  |         return animals; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void feed() { | ||||||
|  |         for (int i = 0; i < this.getStack().size(); i++) { | ||||||
|  |             A a = (A) this.getStack().get(i); | ||||||
|  |             a.eat(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Counts the total number of legs of all {@link Animal}s in the enclosure. | ||||||
|  |      * | ||||||
|  |      * @return the total number of legs of all {@link Animal}s in the enclosure | ||||||
|  |      */ | ||||||
|  |     public int countLegs() { | ||||||
|  |         int sum = 0; | ||||||
|  |         for (int i = 0; i < this.getStack().size(); i++) | ||||||
|  |             sum += ((A) this.getStack().get(i)).getNumberOfLegs(); | ||||||
|  |         return sum; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								H09/src/main/java/h09/Main.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								H09/src/main/java/h09/Main.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Main entry point in executing the program. | ||||||
|  |  */ | ||||||
|  | public class Main { | ||||||
|  |     /** | ||||||
|  |      * Main entry point in executing the program. | ||||||
|  |      * | ||||||
|  |      * @param args program arguments, currently ignored | ||||||
|  |      */ | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         System.out.println("Hello World!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										90
									
								
								H09/src/main/java/h09/StackOfObjects.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								H09/src/main/java/h09/StackOfObjects.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import org.tudalgo.algoutils.student.annotation.DoNotTouch; | ||||||
|  | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of class {@link StackOfObjects} represents a data structure of type stack. | ||||||
|  |  */ | ||||||
|  | @SuppressWarnings({"ManualArrayCopy"}) | ||||||
|  | public class StackOfObjects<TODO_REPLACE> { | ||||||
|  |     @StudentImplementationRequired("H9.1.1") // TODO: H9.1.1 | ||||||
|  |     private Object[] objs = new Object[0]; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Pushes the given object on this stack. | ||||||
|  |      * | ||||||
|  |      * @param obj the object | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.1.2") // TODO: H9.1.2 | ||||||
|  |     public void push(Object obj) { | ||||||
|  |         Object[] newArray = new Object[objs.length + 1]; | ||||||
|  |         for (int i = 0; i < objs.length; i++) newArray[i] = objs[i]; | ||||||
|  |         newArray[objs.length] = obj; | ||||||
|  |         objs = newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes the given object from this stack. | ||||||
|  |      * | ||||||
|  |      * @param obj the object | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.1.3") // TODO: H9.1.3 | ||||||
|  |     public void remove(Object obj) { | ||||||
|  |         Object[] newArray = new Object[objs.length - 1]; | ||||||
|  |         int n = 0; | ||||||
|  |         for (Object currObj : objs) { | ||||||
|  |             if (currObj == obj) continue; | ||||||
|  |             newArray[n++] = currObj; | ||||||
|  |         } | ||||||
|  |         objs = newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the number of objects in this stack. | ||||||
|  |      * | ||||||
|  |      * @return the number of objects | ||||||
|  |      */ | ||||||
|  |     @DoNotTouch | ||||||
|  |     public int size() { | ||||||
|  |         return objs.length; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the object at the given index in this stack. | ||||||
|  |      * | ||||||
|  |      * @param index the index | ||||||
|  |      * @return the object | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.1.4") // TODO: H9.1.4 | ||||||
|  |     public Object get(int index) { | ||||||
|  |         return objs[index]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes and returns the top object of this stack. | ||||||
|  |      * | ||||||
|  |      * @return the top object | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.1.4") // TODO: H9.1.4 | ||||||
|  |     public Object pop() { | ||||||
|  |         Object o = get(objs.length - 1); | ||||||
|  |         remove(o); | ||||||
|  |         return o; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs and returns a stack with the given objects. | ||||||
|  |      * The last object is the top object. | ||||||
|  |      * | ||||||
|  |      * @param objs the objects | ||||||
|  |      * @return the stack | ||||||
|  |      */ | ||||||
|  |     @SafeVarargs | ||||||
|  |     @StudentImplementationRequired("H9.1.5") // TODO: H9.1.5 | ||||||
|  |     public static StackOfObjects of(Object... objs) { | ||||||
|  |         StackOfObjects stack = new StackOfObjects(); | ||||||
|  |         stack.objs = objs; | ||||||
|  |         return stack; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								H09/src/main/java/h09/WaterEnclosure.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								H09/src/main/java/h09/WaterEnclosure.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | ||||||
|  | package h09; | ||||||
|  | 
 | ||||||
|  | import h09.abilities.Swims; | ||||||
|  | import h09.animals.Animal; | ||||||
|  | import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class implementing {@link WaterEnclosure} has the ability to contain and manage a stack of | ||||||
|  |  * {@link Animal}s which have the ability to {@link Swims}. | ||||||
|  |  */ | ||||||
|  | // TODO: H9.2.2 | ||||||
|  | public class WaterEnclosure<TODO_REPLACE> { | ||||||
|  |     /** | ||||||
|  |      * The stack of animals which is used manage the contained Animals. | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.2.2") // TODO: H9.2.2 | ||||||
|  |     final StackOfObjects animals = null; | ||||||
|  | 
 | ||||||
|  |     @StudentImplementationRequired("H9.2.2") | ||||||
|  |     // @Override | ||||||
|  |     public StackOfObjects getStack() { | ||||||
|  |         // TODO: H9.2.2 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H9.2.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @StudentImplementationRequired("H9.2.2") | ||||||
|  |     // @Override | ||||||
|  |     public void feed() { | ||||||
|  |         // TODO: H9.2.2 | ||||||
|  |         org.tudalgo.algoutils.student.Student.crash("H9.2.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Compares the elevations of all {@link Animal}s in the enclosure and returns the mean. | ||||||
|  |      * | ||||||
|  |      * @return the mean elevation of all {@link Animal}s in the enclosure | ||||||
|  |      */ | ||||||
|  |     @StudentImplementationRequired("H9.2.2") | ||||||
|  |     public float getMeanElevation() { | ||||||
|  |         // TODO: H9.2.2 | ||||||
|  |         return org.tudalgo.algoutils.student.Student.crash("H9.2.2 - Remove if implemented"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								H09/src/main/java/h09/abilities/Flies.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								H09/src/main/java/h09/abilities/Flies.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | package h09.abilities; | ||||||
|  | 
 | ||||||
|  | public interface Flies { | ||||||
|  |     /** | ||||||
|  |      * Lets the animal land. | ||||||
|  |      */ | ||||||
|  |     void land(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Lets the animal fly. | ||||||
|  |      */ | ||||||
|  |     void takeOff(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return whether the animal is flying. | ||||||
|  |      */ | ||||||
|  |     boolean isFlying(); | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								H09/src/main/java/h09/abilities/Swims.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								H09/src/main/java/h09/abilities/Swims.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | package h09.abilities; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class implementing {@link Swims} has the ability to swim and live in an {@link h09.WaterEnclosure} | ||||||
|  |  */ | ||||||
|  | public interface Swims { | ||||||
|  |     /** | ||||||
|  |      * @return the elevation of the swimming animal | ||||||
|  |      */ | ||||||
|  |     float getElevation(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Lets the animal swim up and increase in elevation. | ||||||
|  |      */ | ||||||
|  |     void swimUp(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Lets the animal swim down and decrease in elevation. | ||||||
|  |      */ | ||||||
|  |     void swimDown(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The max elevation an animal can swim to. | ||||||
|  |      */ | ||||||
|  |     float MAX_ELEVATION = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The min elevation an animal can swim to. | ||||||
|  |      */ | ||||||
|  |     float MIN_ELEVATION = -10; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The elevation above which an animal is considered at a high elevation or at the surface. | ||||||
|  |      */ | ||||||
|  |     float HIGH_ELEVATION = -3; | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								H09/src/main/java/h09/abilities/Walks.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								H09/src/main/java/h09/abilities/Walks.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | package h09.abilities; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class implementing {@link Walks} has the ability to walk and live in an {@link h09.GroundEnclosure} | ||||||
|  |  */ | ||||||
|  | public interface Walks { | ||||||
|  |     /** | ||||||
|  |      * @return the number of legs of the animal | ||||||
|  |      */ | ||||||
|  |     int getNumberOfLegs(); | ||||||
|  | } | ||||||
							
								
								
									
										71
									
								
								H09/src/main/java/h09/animals/Animal.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								H09/src/main/java/h09/animals/Animal.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | ||||||
|  | package h09.animals; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class {@link Animal} represents an animal. | ||||||
|  |  */ | ||||||
|  | public class Animal { | ||||||
|  |     /** | ||||||
|  |      * Name of the animal. | ||||||
|  |      */ | ||||||
|  |     protected String name; | ||||||
|  |     /** | ||||||
|  |      * Age of the animal. | ||||||
|  |      */ | ||||||
|  |     private int age; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A 'true' value represents that the animal is hungry. | ||||||
|  |      */ | ||||||
|  |     private boolean isHungry = true; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs an Animal with the given name and age. | ||||||
|  |      * | ||||||
|  |      * @param name the name of the animal | ||||||
|  |      * @param age  the age of the animal | ||||||
|  |      */ | ||||||
|  |     public Animal(String name, int age) { | ||||||
|  |         this.name = name; | ||||||
|  |         this.age = age; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return the name of the animal | ||||||
|  |      */ | ||||||
|  |     public String getName() { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Lets the animal eat. This prints a message to the system output noting that the animal has eaten and sets the | ||||||
|  |      * animal to not hungry. | ||||||
|  |      */ | ||||||
|  |     public void eat() { | ||||||
|  |         System.out.println(name + " ate..."); | ||||||
|  |         isHungry = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Lets the animal sleep. This prints a message to the system output noting that the animal has eaten. It also | ||||||
|  |      * increases the age of the animal and sets the animal to hungry. | ||||||
|  |      */ | ||||||
|  |     public void sleep() { | ||||||
|  |         System.out.println(name + " slept..."); | ||||||
|  |         isHungry = true; | ||||||
|  |         age++; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return true if the animal is hungry; false otherwise | ||||||
|  |      */ | ||||||
|  |     public boolean isHungry() { | ||||||
|  |         return isHungry; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return the age of the animal | ||||||
|  |      */ | ||||||
|  |     public int getAge() { | ||||||
|  |         return age; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								H09/src/main/java/h09/animals/ClownFish.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								H09/src/main/java/h09/animals/ClownFish.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | package h09.animals; | ||||||
|  | 
 | ||||||
|  | public class ClownFish extends Fish { | ||||||
|  |     public ClownFish(String name, int age) { | ||||||
|  |         super(name, age); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Prints a joke about fish playing basketball. | ||||||
|  |      */ | ||||||
|  |     public void tellJoke() { | ||||||
|  |         System.out.println(getName() + " says: Why don't fish play basketball? Because they're afraid of the net!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								H09/src/main/java/h09/animals/Fish.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								H09/src/main/java/h09/animals/Fish.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | ||||||
|  | package h09.animals; | ||||||
|  | 
 | ||||||
|  | import h09.abilities.Swims; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An object of a class {@link Fish} represents a fish which can swim. | ||||||
|  |  */ | ||||||
|  | public class Fish extends Animal implements Swims { | ||||||
|  |     /** | ||||||
|  |      * Constructs a Fish with the given name and age. | ||||||
|  |      * | ||||||
|  |      * @param name the name of the animal | ||||||
|  |      * @param age  the age of the animal | ||||||
|  |      */ | ||||||
|  |     public Fish(String name, int age) { | ||||||
|  |         super(name, age); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public float getElevation() { | ||||||
|  |         return Swims.MAX_ELEVATION - (Swims.MAX_ELEVATION - Swims.MIN_ELEVATION) / (getName().length() + 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void swimUp() { | ||||||
|  |         name += "Blub"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void swimDown() { | ||||||
|  |         if (name.length() < 4) return; | ||||||
|  |         name = name.substring(0, name.length() - 4); | ||||||
|  |     } | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		
		Reference in a new issue