Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .gradle/7.5.1/checksums/checksums.lock
Binary file not shown.
Binary file modified .gradle/7.5.1/checksums/md5-checksums.bin
Binary file not shown.
Binary file modified .gradle/7.5.1/checksums/sha1-checksums.bin
Binary file not shown.
Binary file modified .gradle/7.5.1/executionHistory/executionHistory.bin
Binary file not shown.
Binary file modified .gradle/7.5.1/executionHistory/executionHistory.lock
Binary file not shown.
Binary file modified .gradle/7.5.1/fileHashes/fileHashes.bin
Binary file not shown.
Binary file modified .gradle/7.5.1/fileHashes/fileHashes.lock
Binary file not shown.
Binary file added .gradle/7.5.1/fileHashes/resourceHashesCache.bin
Binary file not shown.
Binary file modified .gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
Binary file modified .gradle/buildOutputCleanup/outputFiles.bin
Binary file not shown.
Binary file modified .gradle/file-system.probe
Binary file not shown.
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Database Backup/steam_backUp
Binary file not shown.
189 changes: 22 additions & 167 deletions README.md

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# In the name of god
# Steam simulation
## Introduction
Steam is a digital distribution platform developed by Valve Corporation that allows users to purchase, download, and play video games on their computers.
In this code we have simulation of steam. We have database, server and client and request, response between them. Instead playing game, users can download pictures of game
## Desgin and implementation
- Code has 4 classes (database, serverMain, client handler and clientMain) and a folder with information and pictures of games.
`Database` is postgresql and makes tables are made in database class. Database contains the following data:
### Games
This table stores information about video games, including their attributes.

| Column name | Data type | Description |
|--------------------|------------------|-------------------------------------------------------------------------------------|
| id | text | A unique identifier for the game |
| title | text | Title of the video game |
| developer | text | Name of the studio that developed the game |
| genre | text | Genre of the video game |
| price | double precision | Current price of the video game |
| release_year | integer | The game's release year |
| controller_support | boolean | This parameter is True if the game supports controllers |
| reviews | integer | A value from 0 to 100 indicating the game's average user score on Steam (higher is better) |
| size | integer | Size of the game in kilobytes |
| file_path | text | Path of the game file stored in the `Resources` folder |


### Accounts
This table stores information about user accounts.

| Column name | Data type | Description |
|---------------|-----------|-------------------------------------|
| id | text | A unique identifier for the account |
| username | text | Username of the account |
| hash of password | text | Hashed password of the account |
| date_of_birth | date | The user's date of birth |


### Downloads
This table stores information about user downloads.

| Column name | Data type | Description |
|----------------|-----------|--------------------------------------------------|
| account_id | text | A unique identifier for an existing account |
| game_id | text | A unique identifier for an existing game |
| download_count | Integer | The number of times a user has downloaded a specific game |
- In code, I get connection of database and used it.

- `serverMain` has a while(true) and it listen for client. When client accept, it makes a thread and run it to client handler.
- `clientHandler` is a thread and and has menu and push clients into that. In menu it get order's client and recognized it in switch case and send it to its function.
- `clientMain` has a login menu contains signIn,signUp and exit. When user sginIn, the menu has list of games, game information, download game and exit.
- For download, serverHandler gets file path from database and breaks file into chunks and sends it to client. Then updates download_count in downloads table. Client saves file in download folder.
## Testing and evaluation
- In order to test my program, I tried diffrent inputs and tracked the program flow. I used breakpoints and other tools to achive my goal.
## Conclusion
- In conclusion, this project was a valuable learning experience that allowed me to gain a deeper understanding of Java programming and multi threading concepts and web sockets.

- Throughout the development process, I encountered several challenges, including design considerations, testing and debugging. However, I was able to overcome these obstacles through careful planning, research, and collaboration with my peers.

- Although this project was successful in achieving its objectives, there is still room for improvement. Future work could include expanding the functionality of the application, improving the user interface and adding GUI, and optimizing performance.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ dependencies {

// https://mvnrepository.com/artifact/org.postgresql/postgresql
implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
// https://mvnrepository.com/artifact/org.json/json
implementation group: 'org.json', name: 'json', version: '20230227'

}

test {
Expand Down
201 changes: 199 additions & 2 deletions src/main/java/Client/ClientMain.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,204 @@
package Client;
import java.net.*;
import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
import org.json.JSONObject;

public class ClientMain {
public static void main(String[] args) {
public class ClientMain
{
private static Socket socket = null;
private static BufferedReader input = null;
private static PrintWriter out = null;

public ClientMain(String address, int port)
{
try
{
socket = new Socket(address, port);
System.out.println("Connected to server");

input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
}
public static void ClientClose(){
try
{
input.close();
out.close();
socket.close();
}
catch(IOException i)
{
System.out.println(i);
}
}

public static void RunMenu(){
Scanner in = new Scanner(System.in);
while (true) {
System.out.print("1.Sign in\n2.Sign up\n3.Exit\n->");
String order = in.nextLine();

//sign in
if (order.equals("1")) {
System.out.print("Enter username\n->");
String username = in.nextLine();

try {
out.println("usernameExist");
out.println(username);
if (input.readLine().equals("false")) System.out.println("Username doesn't exist");
else{
System.out.print("Enter password\n->");
String password = in.nextLine();
out.println("checkPass");
out.println(username);
out.println(password);
if (input.readLine().equals("false")) System.out.println("password is not correct");
else signin(username);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//sign up
else if (order.equals("2")) {
System.out.print("Enter username\n->");
String username= in.nextLine();
System.out.println(username);
try {
out.println("usernameExist");
out.println(username);
String foo = input.readLine();
if (foo.equals("true")) System.out.println("Username existed");
else{
System.out.print("Enter password\n->");
String password= in.nextLine();
String date;
while (true){
System.out.print("Enter date of birthday(format : MM-dd-yyyy)\n->");
date= in.nextLine();
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
dateFormat.setLenient(false);
try {
dateFormat.parse(date);
break;
} catch (ParseException e){
System.out.println("Format is wrong!");
}
}

JSONObject jsonObj = new JSONObject();
out.println("signUp");
jsonObj.put("username", username);
jsonObj.put("password", password);
jsonObj.put("date",date);

out.println(jsonObj);
System.out.println("Account create");

}
} catch (IOException e) {
e.printStackTrace();
}
}
//exit
else if (order.equals("3")) {
out.println("exit");
break;
}else System.out.println("Wrong order!");
}

}
public static void signin(String username){
Scanner in = new Scanner(System.in);
while (true) {
System.out.print("1.List of games\n2.Game information\n3.Download game\n4.Exit\n->");
String order = in.nextLine();

//list of games
if (order.equals("1")) {
try {
out.println("listOfGames");
System.out.println(input.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

//game information
else if (order.equals("2")) {
try {
System.out.print("Enter name of game\n->");
String gameName = in.nextLine();
out.println("checkGameName");
out.println(gameName);

if (input.readLine().equals("false")) System.out.println("This game does not exist");
else {
out.println("gameInfo");
out.println(gameName);
String jsonString = input.readLine();
System.out.println(jsonString);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

//download game
else if (order.equals("3")) {
try {
System.out.println("Enter name of game");
String gameName = in.nextLine();
out.println("checkGameName");
out.println(gameName);
if (input.readLine().equals("false")) System.out.println("this game doesn't exist");
else {
out.println("Download");
out.println(gameName);
out.println(username);

DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
int bytes = 0;
FileOutputStream fileOutputStream = new FileOutputStream("/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Client/Downloads/"+gameName+".png");
long size = dataInputStream.readLong(); // read file size
byte[] buffer = new byte[4 * 1024];
while (size > 0 && (bytes = dataInputStream.read(buffer, 0, (int)Math.min(buffer.length, size))) != -1) {
// Here we write the file using write method
fileOutputStream.write(buffer, 0, bytes);
size -= bytes; // read upto file size
}
System.out.println("File is Received");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

//exit
else if (order.equals("4")) {
break;
}else System.out.println("wrong order!");
}
}
public static void main(String args[])
{
ClientMain client = new ClientMain("127.0.0.1", 1402);
RunMenu();
ClientClose();
System.out.println("Client closed");
}
}
Binary file added src/main/java/Client/Downloads/Frostpunk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 101 additions & 0 deletions src/main/java/Server/DataBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package Server;

import java.sql.*;

public class DataBase {
private String url = "jdbc:postgresql://localhost:5432/postgres";
private String user = "postgres";
private String pass = "12345";
private Connection connection;
private Statement statement;
public void connect() {
try {
connection = DriverManager.getConnection(url, user, pass);
statement = connection.createStatement();
ResultSet resultSet = null;

resultSet = statement.executeQuery("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'games')");
resultSet.next();
if (!resultSet.getBoolean(1)) {
statement.executeUpdate("CREATE table games(\n" +
"id text not null primary key,\n" +
"title text not null,\n" +
"developer text,\n" +
"genre text,\n" +
"price double precision," +
" release_year integer, \n" +
"controller_support boolean,\n" +
"reviews integer,\n" +
"size integer not null,\n" +
"file_patch text not null);\n");
System.out.println("games table create");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('292030', 'The Witcher 3: Wild Hunt', 'CD Projekt Red', 'Role-playing', 29.99, 2015, True, 96, 798,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/292030.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('323190', 'Frostpunk', '11 bit studios', 'Strategy', 29.99, 2018, False, 91, 944,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/323190.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('359550', 'Tom Clancys Rainbow Six Siege', 'Ubisoft', 'First-person Shooter', 19.99, 2015, True, 82, 561,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/359550.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('489830', 'The Elder Scrolls V: Skyrim Special Edition', 'Bethesda Game Studios', 'First-person Shooter', 39.99, 2016, True, 96, 677,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/489830.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('1085660', 'Destiny 2', 'Bungie', 'First-person Shooter', 0.0, 2019, True, 74, 657,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/1085660.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('1151640', 'Horizon Zero Dawn Complete Edition', 'Guerrilla', 'Action-adventure', 49.99, 2020, True, 87, 915,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/1151640.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('1174180', 'Red Dead Redemption 2', 'Rockstar Games', 'Action-adventure', 59.99, 2018, True, 90, 771,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/1174180.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('1196590', 'Resident Evil Village', 'Capcom', 'Survival Horror', 39.99, 2021, True, 95, 811,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/1196590.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('1245620', 'Elden Ring', 'FromSoftware', 'Role-playing', 59.99, 2022, True, 94, 703,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/1245620.png' );");

statement.executeUpdate("INSERT INTO games (id, title, developer, genre, price, release_year, controller_support,reviews, size, file_patch)" +
" values ('2050650', 'Resident Evil 4', 'Capcom', 'Survival Horror', 59.99, 2023, True, 97, 618,'/home/abolfazl/Documents/AP/Eighth-Assignment-Steam/src/main/java/Server/Resources/2050650.png' );");

}

//make accounts table
resultSet = statement.executeQuery("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'accounts')");
resultSet.next();
if (!resultSet.getBoolean(1)) {
statement.executeUpdate("CREATE table accounts( id bigserial not null primary key, username text not null, password text not null, date_of_birth date not null)");
System.out.println("accounts table create");
}

//make downloads table
resultSet = statement.executeQuery("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'downloads')");
resultSet.next();
if (!resultSet.getBoolean(1)) {
statement.executeUpdate("CREATE table downloads( account_id bigint references accounts (id), game_id text references games (id), download_count integer not null); ");
System.out.println("downloads table create");
}

} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void closeConnection(){
try {
statement.close();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Connection getConnection() {
return connection;
}

public Statement getStatement() {
return statement;
}
}

2 changes: 1 addition & 1 deletion src/main/java/Server/Resources/1085660.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
2050650
1085660
Destiny 2
Bungie
First-person Shooter
Expand Down
Loading