├── .gitignore ├── .gradle ├── 5.2.1 │ ├── executionHistory │ │ ├── executionHistory.bin │ │ └── executionHistory.lock │ ├── fileChanges │ │ └── last-build.bin │ ├── fileHashes │ │ ├── fileHashes.bin │ │ └── fileHashes.lock │ └── gc.properties ├── buildOutputCleanup │ ├── buildOutputCleanup.lock │ ├── cache.properties │ └── outputFiles.bin └── vcs-1 │ └── gc.properties ├── .idea ├── .gitignore ├── codeStyles │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── Readme.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main └── java └── com └── gb └── parkinglot ├── ParkinglotApplication.java ├── exceptions ├── InvalidParkingLotException.java └── InvlaidParkingFloorException.java ├── model ├── account │ ├── Account.java │ ├── Admin.java │ ├── Contact.java │ ├── Person.java │ ├── PersonalInfo.java │ └── common │ │ └── Address.java ├── parking │ ├── AbledCarParkingSpot.java │ ├── CarParkingSpot.java │ ├── ElectricBikeParkingSpot.java │ ├── ElectricCarParkingSpot.java │ ├── EntrancePanel.java │ ├── ExitPanel.java │ ├── HourlyCost.java │ ├── LargeVehicleParkingSpot.java │ ├── MotorBikeParkingSpot.java │ ├── ParkingFloor.java │ ├── ParkingLot.java │ ├── ParkingSpot.java │ ├── ParkingSpotType.java │ ├── ParkingTicket.java │ ├── Payment.java │ ├── PaymentPortal.java │ ├── PaymentStatus.java │ └── TicketStatus.java └── vehicle │ ├── Car.java │ ├── ElectircMotorBike.java │ ├── ElectricCar.java │ ├── MotorBike.java │ ├── Truck.java │ ├── Van.java │ ├── Vehicle.java │ └── VehicleType.java └── repository ├── AdminRepository.java └── ParkingLotRepository.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /.gradle/5.2.1/executionHistory/executionHistory.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/5.2.1/executionHistory/executionHistory.bin -------------------------------------------------------------------------------- /.gradle/5.2.1/executionHistory/executionHistory.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/5.2.1/executionHistory/executionHistory.lock -------------------------------------------------------------------------------- /.gradle/5.2.1/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/5.2.1/fileHashes/fileHashes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/5.2.1/fileHashes/fileHashes.bin -------------------------------------------------------------------------------- /.gradle/5.2.1/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/5.2.1/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /.gradle/5.2.1/gc.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/5.2.1/gc.properties -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/buildOutputCleanup.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/buildOutputCleanup/buildOutputCleanup.lock -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 06 23:29:44 IST 2020 2 | gradle.version=5.2.1 3 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/outputFiles.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/buildOutputCleanup/outputFiles.bin -------------------------------------------------------------------------------- /.gradle/vcs-1/gc.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/.gradle/vcs-1/gc.properties -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ## Design Parking lot 2 | 3 | ![Image of Parking lot](https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Subterranean_parking_lot.jpg/2880px-Subterranean_parking_lot.jpg) 4 | 5 | Parking lot has multiple floors, multiple entry and exit points. 6 | Entry is recorded at entry point and payment is done at the time of exit. 7 | Parking lot contains Multiple floors. 8 | Parking floor containts multiple parking slots which are of different types. 9 | 1. HANDICAPPED 10 | 2. CAR 11 | 3. LARGE 12 | 4. MOTORBIKE 13 | 5. ELECTRIC 14 | 6. EBIKE 15 | 16 | Parking is on first come first served basis. 17 | Time is recorded at the time of issuing the ticket in entry panel. 18 | Time is recorded at the exit panel and charges are calculated at that point of time. 19 | User should be able to pay for the ticket. 20 | Admin should be able to add floor to the lot. 21 | Admin shoul be able to add parking slots to the floor. 22 | Admin should be able to remove a slot. 23 | Admin should be able to add etrance and exit panels. 24 | User should not be issued a ticket if the slot is not available. 25 | As the user is allocated a slot the inventory of the slots gets reduced. 26 | Add user leaves the parking the inventory get updated. 27 | 28 | # Admin Test cases 29 | Admin Case 1 - should be able to add parking floor case 30 | Admin Case 2 - should be able to add parking floor case 31 | Admin Case 3 - should be able to add entrance panel 32 | Admin Case 4 - should be able to add exit panel 33 | Admin case 5 - should be able to add car parking spot 34 | Admin case 6 - should be able to add bike parking spot 35 | Admin case 7 - should be able to add car parking spot 36 | 37 | #User Test cases 38 | Test case 1 - check for availability of parking lot - TRUE 39 | Test case 2 - check for availability of parking lot - FALSE 40 | Test case 3 - check for availability of parking lot - FALSE 41 | TEST case 4 - Check if full 42 | Test case 5 - get parking spot 43 | Test case 6 - should not be able to get spot 44 | Test case 7 - Entrance Panel - 1 45 | Test case - 8 - Should be able to get parking ticket 46 | Test case - 9 - Should be able to get parking ticket 47 | Test case 10 - Should not be able to get ticket 48 | Test case 11 - Should be able to get ticket 49 | Test case 12 - vacate parking spot 50 | Test case 13 - park on vacated spot 51 | Test case 14 - park when spot is not available 52 | Test cast 15 - vacate car 53 | Test case 16 - Now should be able to park car 54 | Test case 17 - Should be able to vacate parked vehicle 55 | Test case 18 - check for slots count 56 | Test case 19 - Payment 57 | Test case 20 - vacate motorbike spot -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'com.gb.parkinglot' 6 | version '1.0-SNAPSHOT' 7 | 8 | sourceCompatibility = 11 9 | targetCompatibility = 11 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | compileOnly 'org.projectlombok:lombok:1.18.12' 17 | compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' 18 | annotationProcessor 'org.projectlombok:lombok:1.18.12' 19 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' 20 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' 21 | // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter 22 | testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '3.3.3' 23 | 24 | } 25 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/parkinglot/6559d1762bd005c44a9c7b54ac8930c684cb16d8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 06 23:30:11 IST 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'parkinglot' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/ParkinglotApplication.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot; 2 | 3 | import com.gb.parkinglot.exceptions.InvlaidParkingFloorException; 4 | import com.gb.parkinglot.model.account.Account; 5 | import com.gb.parkinglot.model.account.Admin; 6 | import com.gb.parkinglot.model.account.common.Address; 7 | import com.gb.parkinglot.model.parking.*; 8 | import com.gb.parkinglot.model.vehicle.*; 9 | 10 | import java.util.UUID; 11 | 12 | public class ParkinglotApplication { 13 | public static void main(String[] args) throws InvlaidParkingFloorException { 14 | ParkingLot parkingLot = ParkingLot.INSTANCE; 15 | 16 | Address address = new Address(); 17 | address.setAddressLine1("Ram parking Complex"); 18 | address.setStreet("BG Road"); 19 | address.setCity("Bangalore"); 20 | address.setState("Karnataka"); 21 | address.setCountry("India"); 22 | address.setPinCode("560075"); 23 | 24 | parkingLot.setAddress(address); 25 | //Admin tests 26 | Account adminAccount = new Admin(); 27 | //Admin Case 1 - should be able to add parking floor case 28 | ((Admin) adminAccount).addParkingFloor(new ParkingFloor("1")); 29 | //Admin Case 2 - should be able to add parking floor case 30 | ((Admin) adminAccount).addParkingFloor(new ParkingFloor("2")); 31 | 32 | //Admin Case 3 - should be able to add entrance panel 33 | EntrancePanel entrancePanel = new EntrancePanel("1"); 34 | ((Admin) adminAccount).addEntrancePanel(entrancePanel); 35 | 36 | //Admin Case 4 - should be able to add exit panel 37 | ExitPanel exitPanel = new ExitPanel("1"); 38 | ((Admin) adminAccount).addExitPanel(exitPanel); 39 | 40 | String floorId = parkingLot.getParkingFloors().get(0).getFloorId(); 41 | 42 | ///Admin case 5 - should be able to add car parking spot 43 | ParkingSpot carSpot1 = new CarParkingSpot("c1"); 44 | ((Admin) adminAccount).addParkingSpot(floorId, carSpot1); 45 | ///Admin case 6 - should be able to add bike parking spot 46 | ParkingSpot bikeSport = new MotorBikeParkingSpot("b1"); 47 | ((Admin) adminAccount).addParkingSpot(floorId, bikeSport); 48 | ///Admin case 7 - should be able to add car parking spot 49 | ParkingSpot carSpot2 = new CarParkingSpot("c2"); 50 | ((Admin) adminAccount).addParkingSpot(floorId, carSpot2); 51 | 52 | // Test case 1 - check for availability of parking lot - TRUE 53 | System.out.println(ParkingLot.INSTANCE.canPark(VehicleType.CAR)); 54 | 55 | // Test case 2 - check for availability of parking lot - FALSE 56 | System.out.println(ParkingLot.INSTANCE.canPark(VehicleType.EBIKE)); 57 | 58 | // Test case 3 - check for availability of parking lot - FALSE 59 | System.out.println(ParkingLot.INSTANCE.canPark(VehicleType.ELECTRIC)); 60 | 61 | // TEST case 4 - Check if full 62 | System.out.println(ParkingLot.INSTANCE.isFull()); 63 | 64 | // Test case 5 - get parking spot 65 | Vehicle vehicle = new Car("KA05MR2311"); 66 | ParkingSpot availableSpot = ParkingLot.INSTANCE.getParkingSpot(vehicle.getType()); 67 | System.out.println(availableSpot.getParkingSpotType()); 68 | System.out.println(availableSpot.getParkingSpotId()); 69 | 70 | // Test case 6 - should not be able to get spot 71 | Vehicle van = new Van("KA01MR7804"); 72 | ParkingSpot vanSpot = ParkingLot.INSTANCE.getParkingSpot(van.getType()); 73 | System.out.println(null == vanSpot); 74 | 75 | //Test case 7 - Entrance Panel - 1 76 | System.out.println(ParkingLot.INSTANCE.getEntrancePanels().size()); 77 | 78 | // Test case - 8 - Should be able to get parking ticket 79 | ParkingTicket parkingTicket = entrancePanel.getParkingTicket(vehicle); 80 | System.out.println(parkingTicket.getAllocatedSpotId()); 81 | 82 | ((Admin) adminAccount).addParkingSpot(floorId, carSpot1); 83 | // Test case - 9 - Should be able to get parking ticket 84 | Vehicle car = new Car("KA02MR6355"); 85 | ParkingTicket parkingTicket1 = entrancePanel.getParkingTicket(car); 86 | 87 | // Test case 10 - Should not be able to get ticket 88 | ParkingTicket tkt = entrancePanel.getParkingTicket(new Car("ka04rb8458")); 89 | System.out.println(null == tkt); 90 | 91 | // Test case 11 - Should be able to get ticket 92 | ParkingTicket mtrTkt = entrancePanel.getParkingTicket(new MotorBike("ka01ee4901")); 93 | System.out.println(mtrTkt.getAllocatedSpotId()); 94 | 95 | //Test case 12 - vacate parking spot 96 | mtrTkt = exitPanel.scanAndVacate(mtrTkt); 97 | System.out.println(mtrTkt.getCharges()); 98 | System.out.println(mtrTkt.getCharges() > 0); 99 | 100 | // Test case 13 - park on vacated spot 101 | ParkingTicket mtrTkt1 = entrancePanel.getParkingTicket(new MotorBike("ka01ee7791")); 102 | System.out.println(mtrTkt.getAllocatedSpotId()); 103 | 104 | // Test case 14 - park when spot is not available 105 | ParkingTicket unavaialbemTkt = 106 | entrancePanel.getParkingTicket(new MotorBike("ka01ee4455")); 107 | System.out.println(null == unavaialbemTkt); 108 | 109 | // Test cast 15 - vacate car 110 | parkingTicket = exitPanel.scanAndVacate(parkingTicket); 111 | System.out.println(parkingTicket.getCharges()); 112 | System.out.println(parkingTicket.getCharges() > 0); 113 | 114 | //Test case 16 - Now should be able to park car 115 | System.out.println(ParkingLot.INSTANCE.canPark(VehicleType.CAR)); 116 | 117 | //Test case 17 - Should be able to vacate parked vehicle 118 | parkingTicket1 = exitPanel.scanAndVacate(parkingTicket1); 119 | System.out.println(parkingTicket1.getCharges()); 120 | System.out.println(parkingTicket1.getCharges() > 0); 121 | 122 | //Test case 18 - check for slots count 123 | System.out.println(ParkingLot.INSTANCE.getParkingFloors() 124 | .get(0).getParkingSpots().get(ParkingSpotType.CAR).size()); 125 | 126 | //Test case 19 - Payment 127 | Payment payment = new Payment(UUID.randomUUID().toString(), 128 | parkingTicket1.getTicketNumber(), parkingTicket1.getCharges()); 129 | payment.makePayment(); 130 | System.out.println(payment.getPaymentStatus()); 131 | 132 | //Test case 20 - vacate motorbike spot 133 | mtrTkt = exitPanel.scanAndVacate(mtrTkt); 134 | System.out.println(ParkingLot.INSTANCE.getParkingFloors() 135 | .get(0).getParkingSpots().get(ParkingSpotType.MOTORBIKE).size()); 136 | System.out.println(mtrTkt.getCharges()); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/exceptions/InvalidParkingLotException.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.exceptions; 2 | 3 | public class InvalidParkingLotException extends Exception { 4 | public InvalidParkingLotException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/exceptions/InvlaidParkingFloorException.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.exceptions; 2 | 3 | public class InvlaidParkingFloorException extends Exception { 4 | public InvlaidParkingFloorException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/account/Account.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.account; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Getter 9 | @Setter 10 | public abstract class Account { 11 | private String id; 12 | private String email; 13 | private String userName; 14 | private String password; 15 | private LocalDateTime lastAccessed; 16 | private Contact contact; 17 | } -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/account/Admin.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.account; 2 | 3 | import com.gb.parkinglot.exceptions.InvlaidParkingFloorException; 4 | import com.gb.parkinglot.model.parking.*; 5 | import com.gb.parkinglot.repository.ParkingLotRepository; 6 | 7 | import java.util.Optional; 8 | 9 | public class Admin extends Account { 10 | ParkingLotRepository parkingLotRepository = new ParkingLotRepository(); 11 | 12 | public void addParkingFloor(ParkingFloor parkingFloor) { 13 | Optional floor = 14 | ParkingLot.INSTANCE.getParkingFloors().stream() 15 | .filter(pF -> pF.getFloorId().equalsIgnoreCase(parkingFloor.getFloorId())) 16 | .findFirst(); 17 | if (floor.isPresent()) 18 | return; 19 | ParkingLot.INSTANCE.getParkingFloors().add(parkingFloor); 20 | } 21 | 22 | public void addParkingSpot(String parkingFloorId, ParkingSpot parkingSpot) 23 | throws InvlaidParkingFloorException { 24 | Optional floor = 25 | ParkingLot.INSTANCE.getParkingFloors().stream() 26 | .filter(pF -> pF.getFloorId().equalsIgnoreCase(parkingFloorId)) 27 | .findFirst(); 28 | if (!floor.isPresent()) 29 | throw new InvlaidParkingFloorException("Invalid floor"); 30 | 31 | Optional spot = 32 | floor.get().getParkingSpots().get(parkingSpot.getParkingSpotType()) 33 | .stream() 34 | .filter(pS -> pS.getParkingSpotId().equalsIgnoreCase(parkingSpot.getParkingSpotId())) 35 | .findFirst(); 36 | if (spot.isPresent()) 37 | return; 38 | 39 | floor.get().getParkingSpots().get(parkingSpot.getParkingSpotType()) 40 | .addLast(parkingSpot); 41 | } 42 | 43 | public void addEntrancePanel(EntrancePanel entrancePanel) { 44 | Optional panel = 45 | ParkingLot.INSTANCE.getEntrancePanels().stream() 46 | .filter(eP -> eP.getId().equalsIgnoreCase(entrancePanel.getId())).findFirst(); 47 | if (panel.isPresent()) 48 | return; 49 | ParkingLot.INSTANCE.getEntrancePanels().add(entrancePanel); 50 | } 51 | 52 | public void addExitPanel(ExitPanel exitPanel) { 53 | Optional panel = 54 | ParkingLot.INSTANCE.getExitPanels().stream() 55 | .filter(eP -> eP.getId().equalsIgnoreCase(exitPanel.getId())).findFirst(); 56 | if (panel.isPresent()) 57 | return; 58 | ParkingLot.INSTANCE.getExitPanels().add(exitPanel); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/account/Contact.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.account; 2 | 3 | import com.gb.parkinglot.model.account.common.Address; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | public class Contact { 10 | private String phone; 11 | private String email; 12 | private Address address; 13 | private PersonalInfo personalInfo; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/account/Person.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.account; 2 | 3 | public class Person { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/account/PersonalInfo.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.account; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class PersonalInfo { 9 | private String firstName; 10 | private String lastName; 11 | private String middleName; 12 | private String initials; 13 | private String dob; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/account/common/Address.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.account.common; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class Address { 9 | private String addressLine1; 10 | private String addressLine2; 11 | private String addressLine3; 12 | private String street; 13 | private String city; 14 | private String state; 15 | private String country; 16 | private String pinCode; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/AbledCarParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class AbledCarParkingSpot extends ParkingSpot { 9 | public AbledCarParkingSpot(String id) { 10 | super(id, ParkingSpotType.ABLED); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/CarParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public class CarParkingSpot extends ParkingSpot { 4 | public CarParkingSpot(String id) { 5 | super(id, ParkingSpotType.CAR); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ElectricBikeParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public class ElectricBikeParkingSpot extends ParkingSpot { 4 | public ElectricBikeParkingSpot(String id) { 5 | super(id, ParkingSpotType.EBIKE); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ElectricCarParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public class ElectricCarParkingSpot extends ParkingSpot { 4 | public ElectricCarParkingSpot(String id) { 5 | super(id, ParkingSpotType.ELECTRIC); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/EntrancePanel.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import com.gb.parkinglot.model.vehicle.Vehicle; 4 | import lombok.Getter; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.UUID; 8 | 9 | @Getter 10 | public class EntrancePanel { 11 | private String id; 12 | 13 | public EntrancePanel(String id) { 14 | this.id = id; 15 | } 16 | 17 | public ParkingTicket getParkingTicket(Vehicle vehicle) { 18 | if (!ParkingLot.INSTANCE.canPark(vehicle.getType())) 19 | return null; 20 | ParkingSpot parkingSpot = ParkingLot.INSTANCE.getParkingSpot(vehicle.getType()); 21 | if (parkingSpot == null) 22 | return null; 23 | return buildTicket(vehicle.getLicenseNumber(), parkingSpot.getParkingSpotId()); 24 | } 25 | 26 | private ParkingTicket buildTicket(String vehicleLicenseNumber, String parkingSpotId) { 27 | ParkingTicket parkingTicket = new ParkingTicket(); 28 | parkingTicket.setIssuedAt(LocalDateTime.now()); 29 | parkingTicket.setAllocatedSpotId(parkingSpotId); 30 | parkingTicket.setLicensePlateNumber(vehicleLicenseNumber); 31 | parkingTicket.setTicketNumber(UUID.randomUUID().toString()); 32 | parkingTicket.setTicketStatus(TicketStatus.ACTIVE); 33 | return parkingTicket; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ExitPanel.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import java.time.Duration; 7 | import java.time.LocalDateTime; 8 | 9 | @Getter 10 | @AllArgsConstructor 11 | public class ExitPanel { 12 | private String id; 13 | 14 | public ParkingTicket scanAndVacate(ParkingTicket parkingTicket) { 15 | ParkingSpot parkingSpot = 16 | ParkingLot.INSTANCE.vacateParkingSpot(parkingTicket.getAllocatedSpotId()); 17 | parkingTicket.setCharges(calculateCost(parkingTicket, parkingSpot.getParkingSpotType())); 18 | return parkingTicket; 19 | } 20 | 21 | private double calculateCost(ParkingTicket parkingTicket, ParkingSpotType parkingSpotType) { 22 | Duration duration = Duration.between(parkingTicket.getIssuedAt(), LocalDateTime.now()); 23 | long hours = duration.toHours(); 24 | if (hours == 0) 25 | hours = 1; 26 | double amount = hours * new HourlyCost().getCost(parkingSpotType); 27 | return amount; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/HourlyCost.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | @Getter 9 | public class HourlyCost { 10 | private Map hourlyCosts = new HashMap<>(); 11 | 12 | public HourlyCost() { 13 | hourlyCosts.put(ParkingSpotType.CAR, 20.0); 14 | hourlyCosts.put(ParkingSpotType.LARGE, 30.0); 15 | hourlyCosts.put(ParkingSpotType.ELECTRIC, 25.0); 16 | hourlyCosts.put(ParkingSpotType.MOTORBIKE, 10.0); 17 | hourlyCosts.put(ParkingSpotType.ABLED, 25.0); 18 | } 19 | 20 | public double getCost(ParkingSpotType parkingSpotType) { 21 | return hourlyCosts.get(parkingSpotType); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/LargeVehicleParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public class LargeVehicleParkingSpot extends ParkingSpot { 4 | public LargeVehicleParkingSpot(String id) { 5 | super(id, ParkingSpotType.LARGE); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/MotorBikeParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public class MotorBikeParkingSpot extends ParkingSpot { 4 | public MotorBikeParkingSpot(String id) { 5 | super(id, ParkingSpotType.MOTORBIKE); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ParkingFloor.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import com.gb.parkinglot.model.vehicle.VehicleType; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.util.BitSet; 8 | import java.util.Deque; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentLinkedDeque; 12 | 13 | import static com.gb.parkinglot.model.parking.ParkingSpotType.*; 14 | 15 | 16 | public class ParkingFloor { 17 | @Getter 18 | @Setter 19 | private String floorId; 20 | @Getter 21 | private Map> parkingSpots = new HashMap<>(); 22 | private Map usedParkingSpots = new HashMap<>(); 23 | 24 | public ParkingFloor(String id) { 25 | this.floorId = id; 26 | parkingSpots.put(ABLED, new ConcurrentLinkedDeque()); 27 | parkingSpots.put(CAR, new ConcurrentLinkedDeque()); 28 | parkingSpots.put(LARGE, new ConcurrentLinkedDeque()); 29 | parkingSpots.put(MOTORBIKE, new ConcurrentLinkedDeque()); 30 | parkingSpots.put(ELECTRIC, new ConcurrentLinkedDeque()); 31 | } 32 | 33 | public boolean isFloorFull() { 34 | BitSet fullBitSet = new BitSet(); 35 | int bitIndex = 0; 36 | for (Map.Entry> entry : parkingSpots.entrySet()) { 37 | if (entry.getValue().size() == 0) { 38 | fullBitSet.set(bitIndex++); 39 | } else { 40 | break; 41 | } 42 | } 43 | return fullBitSet.cardinality() == fullBitSet.size(); 44 | } 45 | 46 | public static ParkingSpotType getSpotTypeForVehicle(VehicleType vehicleType) { 47 | switch (vehicleType) { 48 | case CAR: 49 | return CAR; 50 | case ELECTRIC: 51 | return ELECTRIC; 52 | case MOTORBIKE: 53 | return MOTORBIKE; 54 | default: 55 | return LARGE; 56 | } 57 | } 58 | 59 | public boolean canPark(VehicleType vehicleType) { 60 | return canPark(getSpotTypeForVehicle(vehicleType)); 61 | } 62 | 63 | public synchronized ParkingSpot getSpot(VehicleType vehicleType) { 64 | if (!canPark(getSpotTypeForVehicle(vehicleType))) 65 | return null; 66 | 67 | ParkingSpotType parkingSpotType = getSpotTypeForVehicle(vehicleType); 68 | ParkingSpot parkingSpot = parkingSpots.get(parkingSpotType) 69 | .poll(); 70 | 71 | usedParkingSpots.put(parkingSpot.getParkingSpotId(), parkingSpot); 72 | return parkingSpot; 73 | } 74 | 75 | public ParkingSpot vacateSpot(String parkingSpotId) { 76 | ParkingSpot parkingSpot = usedParkingSpots.remove(parkingSpotId); 77 | if (parkingSpot != null) { 78 | parkingSpot.freeSpot(); 79 | parkingSpots.get(parkingSpot.getParkingSpotType()) 80 | .addFirst(parkingSpot); 81 | return parkingSpot; 82 | } 83 | return null; 84 | } 85 | 86 | public boolean canPark(ParkingSpotType parkingSpotType) { 87 | return parkingSpots.get(parkingSpotType).size() > 0; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ParkingLot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import com.gb.parkinglot.model.account.common.Address; 4 | import com.gb.parkinglot.model.vehicle.VehicleType; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | import java.util.ArrayList; 9 | import java.util.BitSet; 10 | import java.util.List; 11 | import java.util.UUID; 12 | 13 | import static com.gb.parkinglot.model.parking.ParkingFloor.getSpotTypeForVehicle; 14 | 15 | @Getter 16 | @Setter 17 | public class ParkingLot { 18 | private String parkingLotId; 19 | private Address address; 20 | 21 | private List parkingFloors; 22 | private List entrancePanels; 23 | private List exitPanels; 24 | 25 | public static ParkingLot INSTANCE = new ParkingLot(); 26 | 27 | private ParkingLot() { 28 | this.parkingLotId = UUID.randomUUID().toString(); 29 | parkingFloors = new ArrayList<>(); 30 | entrancePanels = new ArrayList<>(); 31 | exitPanels = new ArrayList<>(); 32 | } 33 | 34 | public boolean isFull() { 35 | int index = 0; 36 | BitSet bitSet = new BitSet(); 37 | for (ParkingFloor parkingFloor : parkingFloors) { 38 | bitSet.set(index++, parkingFloor.isFloorFull()); 39 | } 40 | return bitSet.cardinality() == bitSet.size(); 41 | } 42 | 43 | public boolean canPark(VehicleType vehicleType) { 44 | for (ParkingFloor parkingFloor : parkingFloors) { 45 | if (parkingFloor.canPark(getSpotTypeForVehicle(vehicleType))) 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | public ParkingSpot getParkingSpot(VehicleType vehicleType) { 52 | for (ParkingFloor parkingFloor : ParkingLot.INSTANCE.getParkingFloors()) { 53 | ParkingSpot parkingSpot = parkingFloor.getSpot(vehicleType); 54 | if (parkingSpot != null) { 55 | return parkingSpot; 56 | } 57 | } 58 | return null; 59 | } 60 | 61 | public ParkingSpot vacateParkingSpot(String parkingSpotId) { 62 | for (ParkingFloor parkingFloor : ParkingLot.INSTANCE.getParkingFloors()) { 63 | ParkingSpot parkingSpot = parkingFloor.vacateSpot(parkingSpotId); 64 | if (parkingSpot != null) 65 | return parkingSpot; 66 | } 67 | return null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ParkingSpot.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public abstract class ParkingSpot { 9 | private String parkingSpotId; 10 | private boolean isFree; 11 | private ParkingSpotType parkingSpotType; 12 | private String assignedVehicleId; 13 | 14 | public ParkingSpot(String parkingSpotId, ParkingSpotType parkingSpotType) { 15 | this.parkingSpotId = parkingSpotId; 16 | this.parkingSpotType = parkingSpotType; 17 | } 18 | 19 | public void assignVehicleToSpot(String vehicleId) { 20 | this.assignedVehicleId = vehicleId; 21 | } 22 | 23 | public void freeSpot() { 24 | this.isFree = true; 25 | this.assignedVehicleId = null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ParkingSpotType.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public enum ParkingSpotType { 4 | ABLED, 5 | CAR, 6 | LARGE, 7 | MOTORBIKE, 8 | ELECTRIC, 9 | EBIKE 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/ParkingTicket.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Getter 9 | @Setter 10 | public class ParkingTicket { 11 | private String ticketNumber; 12 | private String licensePlateNumber; 13 | private String allocatedSpotId; 14 | private LocalDateTime issuedAt; 15 | private LocalDateTime vacatedAt; 16 | private double charges; 17 | private TicketStatus ticketStatus; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/Payment.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Getter 9 | public class Payment { 10 | private String id; 11 | private String ticketId; 12 | private double amount; 13 | 14 | @Setter 15 | private LocalDateTime initiatedDate; 16 | @Setter 17 | private LocalDateTime completedDate; 18 | @Setter 19 | private PaymentStatus paymentStatus; 20 | 21 | public Payment(String id, String ticketId, double amount) { 22 | this.id = id; 23 | this.ticketId = ticketId; 24 | this.amount = amount; 25 | } 26 | 27 | public void makePayment() { 28 | this.initiatedDate = LocalDateTime.now(); 29 | this.paymentStatus = PaymentStatus.SUCCESS; 30 | this.completedDate = LocalDateTime.now(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/PaymentPortal.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public class PaymentPortal { 9 | private String id; 10 | 11 | public void scanTicket(ParkingTicket parkingTicket) { 12 | 13 | } 14 | 15 | public void makePayment(ParkingTicket parkingTicket) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/PaymentStatus.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public enum PaymentStatus { 4 | SUCCESS, 5 | FAILED 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/parking/TicketStatus.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.parking; 2 | 3 | public enum TicketStatus { 4 | ACTIVE, 5 | LOST 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/Car.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public class Car extends Vehicle { 4 | public Car(String licenseNumber) { 5 | super(licenseNumber, VehicleType.CAR); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/ElectircMotorBike.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public class ElectircMotorBike extends Vehicle { 4 | public ElectircMotorBike(String licenseNumber) { 5 | super(licenseNumber, VehicleType.EBIKE); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/ElectricCar.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public class ElectricCar extends Vehicle { 4 | public ElectricCar(String licenseNumber, VehicleType type) { 5 | super(licenseNumber, VehicleType.ELECTRIC); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/MotorBike.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public class MotorBike extends Vehicle { 4 | public MotorBike(String licenseNumber) { 5 | super(licenseNumber, VehicleType.MOTORBIKE); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/Truck.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public class Truck extends Vehicle { 4 | public Truck(String licenseNumber) { 5 | super(licenseNumber, VehicleType.TRUCK); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/Van.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public class Van extends Vehicle { 4 | public Van(String licenseNumber) { 5 | super(licenseNumber, VehicleType.VAN); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/Vehicle.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | import com.gb.parkinglot.model.parking.ParkingTicket; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | public abstract class Vehicle { 10 | private String licenseNumber; 11 | private final VehicleType type; 12 | private ParkingTicket ticket; 13 | 14 | public Vehicle(String licenseNumber, VehicleType type) { 15 | this.licenseNumber = licenseNumber; 16 | this.type = type; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/model/vehicle/VehicleType.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.model.vehicle; 2 | 3 | public enum VehicleType { 4 | CAR, 5 | TRUCK, 6 | ELECTRIC, 7 | VAN, 8 | MOTORBIKE, 9 | EBIKE 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/repository/AdminRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.repository; 2 | 3 | import com.gb.parkinglot.model.account.Admin; 4 | 5 | import java.util.*; 6 | 7 | public class AdminRepository { 8 | public static Map adminMap = new HashMap<>(); 9 | public static List admins = new ArrayList<>(); 10 | 11 | public Admin addAdmin(Admin admin) { 12 | adminMap.putIfAbsent(admin.getId(), admin); 13 | admins.add(admin); 14 | return admin; 15 | } 16 | 17 | public Admin getAdminByEmail(String email) { 18 | Optional admin = 19 | admins.stream().filter(adm -> adm.getEmail().equalsIgnoreCase(email)).findFirst(); 20 | 21 | return admin.isPresent() ? admin.get() : null; 22 | } 23 | 24 | public Admin getAdminById(String id) { 25 | return adminMap.get(id); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/gb/parkinglot/repository/ParkingLotRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.parkinglot.repository; 2 | 3 | import com.gb.parkinglot.exceptions.InvalidParkingLotException; 4 | import com.gb.parkinglot.exceptions.InvlaidParkingFloorException; 5 | import com.gb.parkinglot.model.parking.*; 6 | 7 | import java.util.*; 8 | 9 | public class ParkingLotRepository { 10 | public static Map parkingLotMap = new HashMap<>(); 11 | public static List parkingLots = new ArrayList<>(); 12 | 13 | 14 | public ParkingLot addParkingLot(ParkingLot parkingLot) { 15 | parkingLotMap.putIfAbsent(parkingLot.getParkingLotId(), parkingLot); 16 | parkingLots.add(parkingLot); 17 | return parkingLot; 18 | } 19 | 20 | public ParkingLot getParkingLot(String parkingLotId) { 21 | return parkingLotMap.get(parkingLotId); 22 | } 23 | 24 | public ParkingFloor addParkingFloor(String parkingLotId, ParkingFloor parkingFloor) 25 | throws InvalidParkingLotException { 26 | ParkingLot parkingLot = parkingLotMap.get(parkingLotId); 27 | if (parkingLot == null) 28 | throw new InvalidParkingLotException("Invalid parking lot"); 29 | 30 | //Idempotency 31 | Optional floor = parkingLot.getParkingFloors().stream() 32 | .filter(pFloor -> pFloor.getFloorId() 33 | .equalsIgnoreCase(parkingFloor.getFloorId())).findFirst(); 34 | 35 | if (floor.isPresent()) 36 | return floor.get(); 37 | 38 | parkingLot.getParkingFloors().add(parkingFloor); 39 | return parkingFloor; 40 | } 41 | 42 | public ParkingSpot addParkingSpot(String parkingLotId, String parkingFloorId, ParkingSpot parkingSpot) 43 | throws InvalidParkingLotException, InvlaidParkingFloorException { 44 | ParkingLot parkingLot = parkingLotMap.get(parkingLotId); 45 | if (parkingLot == null) 46 | throw new InvalidParkingLotException("Invalid parking lot"); 47 | Optional floor = parkingLot.getParkingFloors().stream() 48 | .filter(pFloor -> pFloor.getFloorId() 49 | .equalsIgnoreCase(parkingFloorId)).findFirst(); 50 | if (!floor.isPresent()) { 51 | throw new InvlaidParkingFloorException("Invalid parking floor"); 52 | } 53 | Optional spot = 54 | floor.get().getParkingSpots().get(parkingSpot.getParkingSpotType()) 55 | .stream().filter(pSpot -> 56 | pSpot.getParkingSpotId() 57 | .equalsIgnoreCase(parkingSpot.getParkingSpotId())).findFirst(); 58 | if (spot.isPresent()) 59 | return spot.get(); 60 | 61 | floor.get().getParkingSpots().get(parkingSpot.getParkingSpotType()).add(parkingSpot); 62 | return parkingSpot; 63 | } 64 | 65 | public EntrancePanel addEntryPanel(String parkingLotId, EntrancePanel entrancePanel) 66 | throws InvalidParkingLotException { 67 | ParkingLot parkingLot = parkingLotMap.get(parkingLotId); 68 | if (parkingLot == null) 69 | throw new InvalidParkingLotException("Invalid parking lot"); 70 | Optional ePanel = 71 | parkingLotMap.get(parkingLotId) 72 | .getEntrancePanels().stream().filter(ep -> 73 | ep.getId().equalsIgnoreCase(entrancePanel.getId())).findFirst(); 74 | if (ePanel.isPresent()) 75 | return entrancePanel; 76 | parkingLotMap.get(parkingLotId) 77 | .getEntrancePanels().add(entrancePanel); 78 | return entrancePanel; 79 | } 80 | 81 | public ExitPanel addExitPanel(String parkingLotId, ExitPanel exitPanel) 82 | throws InvalidParkingLotException { 83 | ParkingLot parkingLot = parkingLotMap.get(parkingLotId); 84 | if (parkingLot == null) 85 | throw new InvalidParkingLotException("Invalid parking lot"); 86 | Optional ePanel = 87 | parkingLotMap.get(parkingLotId) 88 | .getEntrancePanels().stream().filter(ep -> 89 | ep.getId().equalsIgnoreCase(exitPanel.getId())).findFirst(); 90 | if (ePanel.isPresent()) 91 | return exitPanel; 92 | parkingLotMap.get(parkingLotId) 93 | .getExitPanels().add(exitPanel); 94 | return exitPanel; 95 | } 96 | 97 | } 98 | --------------------------------------------------------------------------------