├── .gitignore ├── Docs ├── Draft │ ├── Design │ │ ├── first_scene.png │ │ ├── ingame.png │ │ ├── login.png │ │ ├── menu.png │ │ ├── note.txt │ │ ├── profile.png │ │ └── signup.png │ ├── JavaSocketProgramming.png │ ├── flow-09-11-2020.png │ ├── flow.png │ └── our_flow.png ├── flow-26-11-2020.png └── from_internet │ ├── UseJButton │ ├── Game.java │ └── Main.java │ └── UseJCanvas │ ├── ArtificialIntelligence.java │ ├── JCanvas.java │ ├── JEventQueue.java │ └── Main.java ├── README.md ├── build.xml ├── library └── mysql-connector-java-5.1.23-bin.jar ├── manifest.mf ├── nbproject ├── build-impl.xml ├── genfiles.properties ├── project.properties └── project.xml ├── publicKey ├── screenshots ├── admin.png ├── choose-avatar.png ├── connect-server.png ├── debai.png ├── find-match.png ├── ingame-infopane.png ├── ingame.png ├── login.png ├── main-menu.png ├── pair-match.png ├── profile.png └── signup.png └── src ├── Client ├── RunClient.java ├── controller │ └── SocketHandler.java ├── model │ ├── ChatItem.java │ ├── CurrentGame.java │ ├── PlayerInGame.java │ └── ProfileData.java └── view │ ├── asset │ ├── avatar │ │ ├── icons8_alien_96px.png │ │ ├── icons8_angry_face_meme_96px.png │ │ ├── icons8_animation_96px.png │ │ ├── icons8_avatar_96px.png │ │ ├── icons8_bad_piggies_96px.png │ │ ├── icons8_bendy_96px.png │ │ ├── icons8_captain_america_96px.png │ │ ├── icons8_circled_user_female_skin_type_7_96px.png │ │ ├── icons8_circled_user_male_skin_type_7_96px.png │ │ ├── icons8_confusion_96px.png │ │ ├── icons8_crash_bandicoot_96px.png │ │ ├── icons8_deadpool_96px.png │ │ ├── icons8_elektrovieh_96px.png │ │ ├── icons8_gandalf_96px.png │ │ ├── icons8_ghost_96px.png │ │ ├── icons8_groot_96px.png │ │ ├── icons8_hinata_96px.png │ │ ├── icons8_hulk_96px.png │ │ ├── icons8_ignore_96px.png │ │ ├── icons8_iron_man_96px.png │ │ ├── icons8_jake_96px.png │ │ ├── icons8_jetpack_joyride_96px.png │ │ ├── icons8_joker_dc_96px.png │ │ ├── icons8_logan_x_men_96px.png │ │ ├── icons8_magneto_96px.png │ │ ├── icons8_minecraft_main_character_96px.png │ │ ├── icons8_minecraft_skeleton_96px.png │ │ ├── icons8_minecraft_zombie_96px.png │ │ ├── icons8_morpheus_96px.png │ │ ├── icons8_naruto_96px.png │ │ ├── icons8_neo_96px.png │ │ ├── icons8_orc_96px.png │ │ ├── icons8_pelican_96px.png │ │ ├── icons8_pennywise_96px.png │ │ ├── icons8_pikachu_pokemon_96px.png │ │ ├── icons8_rick_sanchez_96px.png │ │ ├── icons8_sailor_moon_96px.png │ │ ├── icons8_saitama_96px.png │ │ ├── icons8_sasuke_uchiha_96px.png │ │ ├── icons8_sonic_the_hedgehog_96px.png │ │ ├── icons8_spider-man_head_96px.png │ │ ├── icons8_steven_universe_96px.png │ │ ├── icons8_super_mario_96px.png │ │ ├── icons8_the_flash_head_96px.png │ │ ├── icons8_transformer_96px.png │ │ ├── icons8_trinity_96px.png │ │ ├── icons8_trollface_96px.png │ │ ├── icons8_venom_head_96px.png │ │ ├── icons8_vietnam_96px.png │ │ └── icons8_year_of_rooster_96px.png │ ├── icons8_add_24px.png │ ├── icons8_anime_emoji_24px.png │ ├── icons8_birthday_cake_48px_2.png │ ├── icons8_cancel_24px.png │ ├── icons8_circle_24px.png │ ├── icons8_circled_0_24px.png │ ├── icons8_circled_play_24px.png │ ├── icons8_contact_24px.png │ ├── icons8_delete_24px.png │ ├── icons8_delete_24px_1.png │ ├── icons8_email_48px.png │ ├── icons8_exit_sign_24px.png │ ├── icons8_final_state_24px.png │ ├── icons8_flag_2_24px.png │ ├── icons8_forgot_password_48px.png │ ├── icons8_gender_48px.png │ ├── icons8_login_32px.png │ ├── icons8_logout_rounded_left_24px.png │ ├── icons8_name_48px_1.png │ ├── icons8_naruto_sign_24px.png │ ├── icons8_new_file_24px.png │ ├── icons8_ok_24px.png │ ├── icons8_open_door_24px.png │ ├── icons8_paper_plane_24px.png │ ├── icons8_password_48px.png │ ├── icons8_password_reset_48px.png │ ├── icons8_replay_24px.png │ ├── icons8_round_24px.png │ ├── icons8_slide_up_32px.png │ ├── icons8_sphere_30px.png │ ├── icons8_sword_48px.png │ ├── icons8_undo_24px.png │ ├── icons8_vision_24px.png │ └── logo.png │ ├── helper │ ├── LookAndFeel.java │ ├── PlayerInRoomCustomRenderer.java │ ├── Validation.java │ └── WorkWithFile.java │ └── scene │ ├── ChangePassword.form │ ├── ChangePassword.java │ ├── ConnectServer.form │ ├── ConnectServer.java │ ├── InGame.form │ ├── InGame.java │ ├── Login.form │ ├── Login.java │ ├── MainMenu.form │ ├── MainMenu.java │ ├── Profile.form │ ├── Profile.java │ ├── Signup.form │ └── Signup.java ├── Server ├── DB │ ├── Layers │ │ ├── BUS │ │ │ ├── GameMatchBUS.java │ │ │ └── PlayerBUS.java │ │ ├── DAL │ │ │ ├── GameMatchDAL.java │ │ │ └── PlayerDAL.java │ │ ├── DBConnector │ │ │ ├── DB_structure.txt │ │ │ └── MysqlConnector.java │ │ └── DTO │ │ │ ├── GameMatch.java │ │ │ └── Player.java │ └── carodb.sql ├── RunServer.java ├── controller │ ├── Admin.java │ ├── Client.java │ ├── ClientManager.java │ ├── Room.java │ └── RoomManager.java ├── game │ ├── GameLogic.java │ ├── caro │ │ ├── Caro.java │ │ ├── History.java │ │ └── TestTimerCaro.java │ └── cotuong │ │ └── CoTuong.java └── rsa_keypair │ ├── privateKey │ └── publicKey └── Shared ├── constant ├── Avatar.java ├── Code.java └── StreamData.java ├── helper ├── CountDownTimer.java ├── CustumDateTimeFormatter.java ├── Line.java ├── MyHash.java ├── Point.java └── RandomString.java └── security ├── AES.java ├── RSA.java └── RSAGenerator.java /.gitignore: -------------------------------------------------------------------------------- 1 | **/nbproject/private/ 2 | **/nbproject/Makefile-*.mk 3 | **/nbproject/Package-*.bash 4 | build/ 5 | nbbuild/ 6 | dist/ 7 | nbdist/ 8 | .nb-gradle/ -------------------------------------------------------------------------------- /Docs/Draft/Design/first_scene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/Design/first_scene.png -------------------------------------------------------------------------------- /Docs/Draft/Design/ingame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/Design/ingame.png -------------------------------------------------------------------------------- /Docs/Draft/Design/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/Design/login.png -------------------------------------------------------------------------------- /Docs/Draft/Design/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/Design/menu.png -------------------------------------------------------------------------------- /Docs/Draft/Design/note.txt: -------------------------------------------------------------------------------- 1 | 2 | File này note ý tưởng của Văn Hoàng 3 | Chủ yếu để lưu ý tưởng để t dùng chứ ko phải giải thích ý tưởng 4 | Nên đọc không hiểu thì thôi nhé :)) 5 | 6 | 7 | https://www.geeksforgeeks.org/multi-threaded-chat-application-set-1/ 8 | https://viblo.asia/p/gioi-thieu-uuid-trong-java-ORNZq4B3K0n 9 | 10 | 11 | 12 | Server: 13 | + Main Thread 14 | - ListRoomsController Thread 15 | - RoomController 16 | - Players 17 | - Watchers 18 | - Chat Thread 19 | - Broadcast method 20 | - ClientHandler 21 | 22 | - ClientConnectListener Thread 23 | 24 | Client: 25 | + Room (InGame) 26 | - GameBoard: Khung chứa các thứ thuộc về game đang chơi 27 | - Bàn caro 28 | - Chức năng 29 | - Lượt, thời gian 30 | - PlayersBoard: Khung chứa thông tin người chơi và người xem trong room 31 | => Tách riêng GameBoard và PlayersBoard 32 | để có sau này có thể chọn game để chơi cho Room 33 | PlayerBoard giữ nguyên, chỉ có GameBoard là được đổi qua game khác. 34 | 35 | + Dashboard 36 | + Profile 37 | 38 | === Chat ==== 39 | while (in.readLine() != -1) => Lấy tất cả data có trong socket buffer 40 | 41 | 42 | === cấu trúc === 43 | Main 44 | - Room 45 | - hashmap ClientHandler 46 | - CaroLogic extends Game 47 | - 48 | 49 | 50 | ====================================== 51 | socket: 52 | + type: 53 | - chung: exit, 54 | - client->server: login, logout, signup 55 | - server->client: login_result, logout_result, signup_result 56 | + data 57 | 58 | ======================================= 59 | game events: 60 | { 61 | type: Type.GAME_EVENT, 62 | game_event: UNDO, NEWGAME, CLICK, SURRENDER, 63 | 64 | x: 4, 65 | y: 5 66 | } -------------------------------------------------------------------------------- /Docs/Draft/Design/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/Design/profile.png -------------------------------------------------------------------------------- /Docs/Draft/Design/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/Design/signup.png -------------------------------------------------------------------------------- /Docs/Draft/JavaSocketProgramming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/JavaSocketProgramming.png -------------------------------------------------------------------------------- /Docs/Draft/flow-09-11-2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/flow-09-11-2020.png -------------------------------------------------------------------------------- /Docs/Draft/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/flow.png -------------------------------------------------------------------------------- /Docs/Draft/our_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/Draft/our_flow.png -------------------------------------------------------------------------------- /Docs/flow-26-11-2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/Docs/flow-26-11-2020.png -------------------------------------------------------------------------------- /Docs/from_internet/UseJButton/Game.java: -------------------------------------------------------------------------------- 1 | package Docs.FromInternet.UseJButton; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.event.*; 6 | 7 | public class Game extends JFrame implements ActionListener { 8 | 9 | Color background_cl = Color.white; 10 | Color x_cl = Color.red; 11 | Color y_cl = Color.blue; 12 | 13 | int column = 20, row = 30, count = 0; 14 | int xUndo[] = new int[column * row]; 15 | int yUndo[] = new int[column * row]; 16 | boolean tick[][] = new boolean[column + 2][row + 2]; 17 | int Size = 0; 18 | 19 | Container cn; 20 | JPanel pn, pn2; 21 | JLabel lb; 22 | JButton newGame_bt, undo_bt, exit_bt; 23 | private JButton b[][] = new JButton[column + 2][row + 2]; 24 | 25 | public Game(String s) { 26 | super(s); 27 | cn = this.getContentPane(); 28 | pn = new JPanel(); 29 | pn.setLayout(new GridLayout(column, row)); 30 | 31 | for (int i = 0; i <= column + 1; i++) { 32 | for (int j = 0; j <= row + 1; j++) { 33 | b[i][j] = new JButton(" "); 34 | b[i][j].setFont(new Font("Consolas", Font.BOLD, 20)); 35 | b[i][j].setActionCommand(i + " " + j); 36 | b[i][j].setBackground(background_cl); 37 | b[i][j].addActionListener(this); 38 | tick[i][j] = true; 39 | } 40 | } 41 | for (int i = 1; i <= column; i++) { 42 | for (int j = 1; j <= row; j++) { 43 | pn.add(b[i][j]); 44 | } 45 | } 46 | 47 | lb = new JLabel("X Đánh Trước"); 48 | newGame_bt = new JButton("New Game"); 49 | undo_bt = new JButton("Undo"); 50 | exit_bt = new JButton("Exit"); 51 | newGame_bt.addActionListener(this); 52 | undo_bt.addActionListener(this); 53 | exit_bt.addActionListener(this); 54 | exit_bt.setForeground(x_cl); 55 | cn.add(pn); 56 | pn2 = new JPanel(); 57 | pn2.setLayout(new FlowLayout()); 58 | pn2.add(lb); 59 | pn2.add(newGame_bt); 60 | pn2.add(undo_bt); 61 | pn2.add(exit_bt); 62 | cn.add(pn2, "North"); 63 | undo_bt.setEnabled(false); 64 | 65 | this.setVisible(true); 66 | this.setSize(1400, 1000); 67 | this.setLocationRelativeTo(null); 68 | this.setDefaultCloseOperation(EXIT_ON_CLOSE); 69 | } 70 | 71 | public boolean checkWin(int i, int j) { 72 | int d = 0, k = i, h; 73 | // kiểm tra hàng 74 | while (b[k][j].getText().equals(b[i][j].getText())) { 75 | d++; 76 | k++; 77 | } 78 | k = i - 1; 79 | while (b[k][j].getText().equals(b[i][j].getText())) { 80 | d++; 81 | k--; 82 | } 83 | if (d > 4) { 84 | return true; 85 | } 86 | d = 0; 87 | h = j; 88 | // kiểm tra cột 89 | while (b[i][h].getText().equals(b[i][j].getText())) { 90 | d++; 91 | h++; 92 | } 93 | h = j - 1; 94 | while (b[i][h].getText().equals(b[i][j].getText())) { 95 | d++; 96 | h--; 97 | } 98 | if (d > 4) { 99 | return true; 100 | } 101 | // kiểm tra đường chéo 1 102 | h = i; 103 | k = j; 104 | d = 0; 105 | while (b[i][j].getText().equals(b[h][k].getText())) { 106 | d++; 107 | h++; 108 | k++; 109 | } 110 | h = i - 1; 111 | k = j - 1; 112 | while (b[i][j].getText().equals(b[h][k].getText())) { 113 | d++; 114 | h--; 115 | k--; 116 | } 117 | if (d > 4) { 118 | return true; 119 | } 120 | // kiểm tra đường chéo 2 121 | h = i; 122 | k = j; 123 | d = 0; 124 | while (b[i][j].getText().equals(b[h][k].getText())) { 125 | d++; 126 | h++; 127 | k--; 128 | } 129 | h = i - 1; 130 | k = j + 1; 131 | while (b[i][j].getText().equals(b[h][k].getText())) { 132 | d++; 133 | h--; 134 | k++; 135 | } 136 | if (d > 4) { 137 | return true; 138 | } 139 | // nếu không đương chéo nào thỏa mãn thì trả về false. 140 | return false; 141 | } 142 | 143 | public void undo() { 144 | if (Size > 0) { 145 | b[xUndo[Size - 1]][yUndo[Size - 1]].setText(" "); 146 | b[xUndo[Size - 1]][yUndo[Size - 1]].setActionCommand(xUndo[Size - 1] + " " + yUndo[Size - 1]); 147 | b[xUndo[Size - 1]][yUndo[Size - 1]].setBackground(background_cl); 148 | tick[xUndo[Size - 1]][yUndo[Size - 1]] = true; 149 | count--; 150 | if (count % 2 == 0) { 151 | lb.setText("Lượt Của X"); 152 | } else { 153 | lb.setText("Lượt Của O"); 154 | } 155 | Size--; 156 | if (Size == 0) { 157 | undo_bt.setEnabled(false); 158 | } 159 | } 160 | } 161 | 162 | public void addPoint(int i, int j) { 163 | if (Size > 0) { 164 | b[xUndo[Size - 1]][yUndo[Size - 1]].setBackground(background_cl); 165 | } 166 | xUndo[Size] = i; 167 | yUndo[Size] = j; 168 | Size++; 169 | if (count % 2 == 0) { 170 | b[i][j].setText("X"); 171 | b[i][j].setForeground(x_cl); 172 | lb.setText("Lượt Của O"); 173 | } else { 174 | b[i][j].setText("O"); 175 | b[i][j].setForeground(y_cl); 176 | lb.setText("Lượt Của X"); 177 | } 178 | tick[i][j] = false; 179 | count = 1 - count; 180 | b[i][j].setBackground(Color.GRAY); 181 | undo_bt.setEnabled(true); 182 | } 183 | 184 | @Override 185 | public void actionPerformed(ActionEvent e) { 186 | if (e.getActionCommand() == "New Game") { 187 | new Game("CODELEARN - GAME DEMO"); 188 | this.dispose(); 189 | } else if (e.getActionCommand() == "Undo") { 190 | undo(); 191 | } else if (e.getActionCommand() == "Exit") { 192 | System.exit(0);; 193 | } else { 194 | String s = e.getActionCommand(); 195 | int k = s.indexOf(32); 196 | int i = Integer.parseInt(s.substring(0, k)); 197 | int j = Integer.parseInt(s.substring(k + 1, s.length())); 198 | if (tick[i][j]) { 199 | addPoint(i, j); 200 | } 201 | if (checkWin(i, j)) { 202 | lb.setBackground(Color.MAGENTA); 203 | lb.setText(b[i][j].getText() + " WIN"); 204 | for (i = 1; i <= column; i++) { 205 | for (j = 1; j <= row; j++) { 206 | b[i][j].setEnabled(false); 207 | } 208 | } 209 | undo_bt.setEnabled(false); 210 | newGame_bt.setBackground(Color.YELLOW); 211 | } 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /Docs/from_internet/UseJButton/Main.java: -------------------------------------------------------------------------------- 1 | package Docs.FromInternet.UseJButton; 2 | 3 | /* 4 | * To change this license header, choose License Headers in Project Properties. 5 | * To change this template file, choose Tools | Templates 6 | * and open the template in the editor. 7 | */ 8 | 9 | /** 10 | * 11 | * @author th016 12 | */ 13 | public class Main { 14 | public static void main(String[] args) { 15 | Game game = new Game("CODELEARN - GAME CARO"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Docs/from_internet/UseJCanvas/ArtificialIntelligence.java: -------------------------------------------------------------------------------- 1 | package Docs.FromInternet.UseJCanvas; 2 | 3 | // +------------------------------------------------------------+ 4 | // | Software: Caro 3.0 | 5 | // | Author: Hy Truong Son | 6 | // | Major: BSc. Computer Science | 7 | // | Class: 2013 - 2016 | 8 | // | Institution: Eotvos Lorand University | 9 | // | Email: sonpascal93@gmail.com | 10 | // | Website: http://people.inf.elte.hu/hytruongson/ | 11 | // | Copyright 2015 (c) Hy Truong Son. All rights reserved. | 12 | // +------------------------------------------------------------+ 13 | 14 | // +-------------------------------------------------------+ 15 | // | This class is the brain, intelligence of the software | 16 | // +-------------------------------------------------------+ 17 | import java.util.Random; 18 | 19 | public class ArtificialIntelligence { 20 | 21 | static int nextMoveX; 22 | static int nextMoveY; 23 | static Random generator = new Random(); 24 | static int DX[] = {-1, 1, 0, 0, -1, -1, 1, 1}; 25 | static int DY[] = {0, 0, -1, 1, -1, 1, -1, 1}; 26 | 27 | public static int RandomInt(int n) { 28 | return generator.nextInt(n); 29 | } 30 | 31 | public static int getNextMoveX() { 32 | return nextMoveX; 33 | } 34 | 35 | public static int getNextMoveY() { 36 | return nextMoveY; 37 | } 38 | 39 | public static void createTable(int table[][], int N, int nSteps, int x[], int y[], int whoFirst) { 40 | for (int i = 0; i < N; i++) { 41 | for (int j = 0; j < N; j++) { 42 | table[i][j] = 0; 43 | } 44 | } 45 | 46 | for (int i = 0; i < nSteps; i++) { 47 | if (whoFirst == -1) { 48 | if (i % 2 == 0) { 49 | table[x[i]][y[i]] = -1; 50 | } else { 51 | table[x[i]][y[i]] = 1; 52 | } 53 | } else if (i % 2 == 0) { 54 | table[x[i]][y[i]] = 1; 55 | } else { 56 | table[x[i]][y[i]] = -1; 57 | } 58 | } 59 | } 60 | 61 | public static int CheckWinner(int N, int nSteps, int x[], int y[], int whoFirst, int LengthWin) { 62 | int table[][] = new int[N][N]; 63 | createTable(table, N, nSteps, x, y, whoFirst); 64 | 65 | for (int i = 0; i < N; i++) { 66 | for (int j = 0; j < N; j++) { 67 | if (table[i][j] != 0) { 68 | for (int t = 0; t < 8; t++) { 69 | int sum = 0; 70 | for (int k = 0; k < LengthWin; k++) { 71 | int u = i + k * DX[t]; 72 | int v = j + k * DY[t]; 73 | if ((u >= 0) && (u < N) && (v >= 0) && (v < N)) { 74 | if (table[u][v] != table[i][j]) { 75 | break; 76 | } 77 | sum += table[u][v]; 78 | } else { 79 | break; 80 | } 81 | } 82 | if (sum == LengthWin) { 83 | return 1; 84 | } 85 | if (sum == -LengthWin) { 86 | return -1; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | public static boolean SearchSum(int table[][], int N, int length, int sum) { 97 | int FoundX = 0; 98 | int FoundY = 0; 99 | 100 | for (int i = 0; i < N; i++) { 101 | for (int j = 0; j < N; j++) { 102 | if (table[i][j] * sum >= 0) { 103 | for (int t = 0; t < 8; t++) { 104 | boolean check = true; 105 | int s = 0; 106 | 107 | for (int k = 0; k < length; k++) { 108 | int u = i + k * DX[t]; 109 | int v = j + k * DY[t]; 110 | 111 | if ((u >= 0) && (u < N) && (v >= 0) && (v < N)) { 112 | if (table[u][v] * sum >= 0) { 113 | s += table[u][v]; 114 | 115 | if (table[u][v] == 0) { 116 | FoundX = u; 117 | FoundY = v; 118 | } 119 | } else { 120 | check = false; 121 | break; 122 | } 123 | } else { 124 | check = false; 125 | break; 126 | } 127 | } 128 | 129 | if (check) { 130 | if (s == sum) { 131 | nextMoveX = FoundX; 132 | nextMoveY = FoundY; 133 | return true; 134 | } 135 | } 136 | } 137 | } 138 | } 139 | } 140 | return false; 141 | } 142 | 143 | public static void findNextMove(int N, int nSteps, int x[], int y[], int whoFirst, boolean hasAI) { 144 | if (nSteps == 0) { 145 | nextMoveX = RandomInt(N); 146 | nextMoveY = RandomInt(N); 147 | return; 148 | } 149 | 150 | int table[][] = new int[N][N]; 151 | createTable(table, N, nSteps, x, y, whoFirst); 152 | 153 | if (!hasAI) { 154 | for (int ntimes = 1; ntimes <= 100; ntimes++) { 155 | int i = RandomInt(N); 156 | int j = RandomInt(N); 157 | if (table[i][j] == 0) { 158 | nextMoveX = i; 159 | nextMoveY = j; 160 | return; 161 | } 162 | } 163 | for (int i = 0; i < N; i++) { 164 | for (int j = 0; j < N; j++) { 165 | if (table[i][j] == 0) { 166 | nextMoveX = i; 167 | nextMoveY = j; 168 | return; 169 | } 170 | } 171 | } 172 | } 173 | 174 | // AI program here 175 | if (SearchSum(table, N, 5, 4)) { 176 | return; 177 | } 178 | if (SearchSum(table, N, 5, -4)) { 179 | return; 180 | } 181 | 182 | if (SearchSum(table, N, 5, 3)) { 183 | return; 184 | } 185 | if (SearchSum(table, N, 5, -3)) { 186 | return; 187 | } 188 | 189 | if (SearchSum(table, N, 4, -3)) { 190 | return; 191 | } 192 | if (SearchSum(table, N, 4, 3)) { 193 | return; 194 | } 195 | 196 | if (SearchSum(table, N, 3, 2)) { 197 | return; 198 | } 199 | if (SearchSum(table, N, 3, -2)) { 200 | return; 201 | } 202 | if (SearchSum(table, N, 2, 1)) { 203 | return; 204 | } 205 | if (SearchSum(table, N, 2, -1)) { 206 | return; 207 | } 208 | 209 | for (int i = 0; i < N; i++) { 210 | for (int j = 0; j < N; j++) { 211 | if (table[i][j] == 0) { 212 | nextMoveX = i; 213 | nextMoveY = j; 214 | return; 215 | } 216 | } 217 | } 218 | } 219 | 220 | } 221 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Caro Online Game Java Socket Client Server bla bla 2 | 3 | Donate? Muốn hỗ trợ mình 1 ly cafe <3 [Donate here](https://github.com/HoangTran0410/HoangTran0410/blob/main/DONATE.md) 4 | 5 | ## 0. Giới thiệu 6 | 7 | Link [Facebook post](https://www.facebook.com/groups/j2team.community/permalink/1462938307371618) 8 | 9 | ## 1. Yêu cầu 10 | 11 | 12 | 13 | - yêu cầu một vài chỗ có vẻ không thân thiện người dùng như việc tự ghép trận, tự xem trận khi vào game ... nên mình đã làm khác tí, là tạo chức năng tìm trận và ghép cặp riêng với chức năng xem trận, người dùng sẽ có thể lựa chọn theo sở thích. 14 | 15 | ## 2. Cài đặt 16 | 17 | Hướng dẫn setup: 18 | - Cài mysql (mình dùng xampp), IDE (mình dùng Netbean 8.2) 19 | - Thêm cơ sở dữ liệu [src/Server/DB/carodb.sql](src/Server/DB/carodb.sql) vào mysql, đặt tên csdl là "carodb" 20 | - Chạy Server [src/Server/RunServer.java](src/Server/RunServer.java) mặc định sẽ chạy ở port 5056 21 | - Chạy Client [src/Client/RunClient.java](src/Client/RunClient.java) 22 | - Giao diện Connect Server hiện lên. Nhập IP, port tới Server (mặc định mình đã ghi sẵn ip server local rồi) 23 | - Ấn Kết nối và Chơi 24 | 25 | ## 3. Screenshots 26 | 27 | ### Server 28 | 29 | #### - Admin Console 30 | 31 | 32 | 33 | ### Client 34 | 35 | #### - Connect to server 36 | 37 | 38 | 39 | #### - Login 40 | 41 | 42 | 43 | #### - Signup 44 | 45 | 46 | 47 | #### - Select custom avatar 48 | 49 | 50 | 51 | #### - Main menu 52 | 53 | 54 | 55 | #### - Profile 56 | 57 | 58 | 59 | #### - Find game match 60 | 61 | 62 | 63 | #### - Pair game match 64 | 65 | 66 | 67 | #### - In-game Caro 68 | 69 | 70 | 71 | #### - In-game Caro right panel 72 | 73 | 74 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Builds, tests, and runs the project CaroOnline_SocketJava. 12 | 13 | 73 | 74 | -------------------------------------------------------------------------------- /library/mysql-connector-java-5.1.23-bin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/library/mysql-connector-java-5.1.23-bin.jar -------------------------------------------------------------------------------- /manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=32ea2b06 2 | build.xml.script.CRC32=bed70157 3 | build.xml.stylesheet.CRC32=8064a381@1.80.1.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=32ea2b06 7 | nbproject/build-impl.xml.script.CRC32=b1543fa8 8 | nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48 9 | -------------------------------------------------------------------------------- /nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=false 3 | annotation.processing.processors.list= 4 | annotation.processing.run.all.processors=true 5 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 6 | application.homepage= 7 | application.title=CaroOnline_SocketJava 8 | application.vendor=hoangtran 9 | auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml 10 | build.classes.dir=${build.dir}/classes 11 | build.classes.excludes=**/*.java,**/*.form 12 | # This directory is removed when the project is cleaned: 13 | build.dir=build 14 | build.generated.dir=${build.dir}/generated 15 | build.generated.sources.dir=${build.dir}/generated-sources 16 | # Only compile against the classpath explicitly listed here: 17 | build.sysclasspath=ignore 18 | build.test.classes.dir=${build.dir}/test/classes 19 | build.test.results.dir=${build.dir}/test/results 20 | # Uncomment to specify the preferred debugger connection transport: 21 | #debug.transport=dt_socket 22 | debug.classpath=\ 23 | ${run.classpath} 24 | debug.test.classpath=\ 25 | ${run.test.classpath} 26 | # Files in build.classes.dir which should be excluded from distribution jar 27 | dist.archive.excludes= 28 | # This directory is removed when the project is cleaned: 29 | dist.dir=dist 30 | dist.jar=${dist.dir}/CaroOnline_SocketJava.jar 31 | dist.javadoc.dir=${dist.dir}/javadoc 32 | endorsed.classpath= 33 | excludes= 34 | file.reference.mysql-connector-java-5.1.23-bin.jar=library\\mysql-connector-java-5.1.23-bin.jar 35 | includes=** 36 | jar.archive.disabled=${jnlp.enabled} 37 | jar.compress=false 38 | jar.index=${jnlp.enabled} 39 | javac.classpath=\ 40 | ${file.reference.mysql-connector-java-5.1.23-bin.jar} 41 | # Space-separated list of extra javac options 42 | javac.compilerargs= 43 | javac.deprecation=false 44 | javac.external.vm=true 45 | javac.processorpath=\ 46 | ${javac.classpath} 47 | javac.source=1.8 48 | javac.target=1.8 49 | javac.test.classpath=\ 50 | ${javac.classpath}:\ 51 | ${build.classes.dir} 52 | javac.test.processorpath=\ 53 | ${javac.test.classpath} 54 | javadoc.additionalparam= 55 | javadoc.author=false 56 | javadoc.encoding=${source.encoding} 57 | javadoc.noindex=false 58 | javadoc.nonavbar=false 59 | javadoc.notree=false 60 | javadoc.private=false 61 | javadoc.splitindex=true 62 | javadoc.use=true 63 | javadoc.version=false 64 | javadoc.windowtitle= 65 | jnlp.codebase.type=no.codebase 66 | jnlp.descriptor=application 67 | jnlp.enabled=false 68 | jnlp.mixed.code=default 69 | jnlp.offline-allowed=false 70 | jnlp.signed=false 71 | jnlp.signing= 72 | jnlp.signing.alias= 73 | jnlp.signing.keystore= 74 | main.class=client.RunClient 75 | # Optional override of default Application-Library-Allowable-Codebase attribute identifying the locations where your signed RIA is expected to be found. 76 | manifest.custom.application.library.allowable.codebase= 77 | # Optional override of default Caller-Allowable-Codebase attribute identifying the domains from which JavaScript code can make calls to your RIA without security prompts. 78 | manifest.custom.caller.allowable.codebase= 79 | # Optional override of default Codebase manifest attribute, use to prevent RIAs from being repurposed 80 | manifest.custom.codebase= 81 | # Optional override of default Permissions manifest attribute (supported values: sandbox, all-permissions) 82 | manifest.custom.permissions= 83 | manifest.file=manifest.mf 84 | meta.inf.dir=${src.dir}/META-INF 85 | mkdist.disabled=false 86 | platform.active=default_platform 87 | run.classpath=\ 88 | ${javac.classpath}:\ 89 | ${build.classes.dir} 90 | # Space-separated list of JVM arguments used when running the project. 91 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. 92 | # To set system properties for unit tests define test-sys-prop.name=value: 93 | run.jvmargs= 94 | run.test.classpath=\ 95 | ${javac.test.classpath}:\ 96 | ${build.test.classes.dir} 97 | source.encoding=UTF-8 98 | src.dir=src 99 | test.src.dir=test 100 | -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | CaroOnline_SocketJava 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /publicKey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/publicKey -------------------------------------------------------------------------------- /screenshots/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/admin.png -------------------------------------------------------------------------------- /screenshots/choose-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/choose-avatar.png -------------------------------------------------------------------------------- /screenshots/connect-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/connect-server.png -------------------------------------------------------------------------------- /screenshots/debai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/debai.png -------------------------------------------------------------------------------- /screenshots/find-match.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/find-match.png -------------------------------------------------------------------------------- /screenshots/ingame-infopane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/ingame-infopane.png -------------------------------------------------------------------------------- /screenshots/ingame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/ingame.png -------------------------------------------------------------------------------- /screenshots/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/login.png -------------------------------------------------------------------------------- /screenshots/main-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/main-menu.png -------------------------------------------------------------------------------- /screenshots/pair-match.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/pair-match.png -------------------------------------------------------------------------------- /screenshots/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/profile.png -------------------------------------------------------------------------------- /screenshots/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/screenshots/signup.png -------------------------------------------------------------------------------- /src/Client/RunClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client; 7 | 8 | import client.controller.SocketHandler; 9 | import client.view.helper.LookAndFeel; 10 | import client.view.scene.ChangePassword; 11 | import client.view.scene.ConnectServer; 12 | import client.view.scene.InGame; 13 | import client.view.scene.Login; 14 | import client.view.scene.MainMenu; 15 | import client.view.scene.Profile; 16 | import client.view.scene.Signup; 17 | 18 | /** 19 | * 20 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 21 | */ 22 | public class RunClient { 23 | 24 | public enum SceneName { 25 | CONNECTSERVER, 26 | LOGIN, 27 | SIGNUP, 28 | MAINMENU, 29 | CHANGEPASSWORD, 30 | INGAME, 31 | PROFILE 32 | } 33 | 34 | // scenes 35 | public static ConnectServer connectServerScene; 36 | public static Login loginScene; 37 | public static Signup signupScene; 38 | public static MainMenu mainMenuScene; 39 | public static ChangePassword changePasswordScene; 40 | public static InGame inGameScene; 41 | public static Profile profileScene; 42 | 43 | // controller 44 | public static SocketHandler socketHandler; 45 | 46 | public RunClient() { 47 | socketHandler = new SocketHandler(); 48 | initScene(); 49 | openScene(SceneName.CONNECTSERVER); 50 | } 51 | 52 | public void initScene() { 53 | connectServerScene = new ConnectServer(); 54 | loginScene = new Login(); 55 | signupScene = new Signup(); 56 | mainMenuScene = new MainMenu(); 57 | changePasswordScene = new ChangePassword(); 58 | inGameScene = new InGame(); 59 | profileScene = new Profile(); 60 | } 61 | 62 | public static void openScene(SceneName sceneName) { 63 | if (null != sceneName) { 64 | switch (sceneName) { 65 | case CONNECTSERVER: 66 | // tạo lại scene để tạo lại state mặc định 67 | // nếu chỉ setVisible(true) thì cũng open được scene cũ, nhưng state thì không phải mặc định 68 | connectServerScene = new ConnectServer(); 69 | connectServerScene.setVisible(true); 70 | break; 71 | case LOGIN: 72 | loginScene = new Login(); 73 | loginScene.setVisible(true); 74 | break; 75 | case SIGNUP: 76 | signupScene = new Signup(); 77 | signupScene.setVisible(true); 78 | break; 79 | case MAINMENU: 80 | mainMenuScene = new MainMenu(); 81 | mainMenuScene.setVisible(true); 82 | break; 83 | case CHANGEPASSWORD: 84 | changePasswordScene = new ChangePassword(); 85 | changePasswordScene.setVisible(true); 86 | break; 87 | case INGAME: 88 | inGameScene = new InGame(); 89 | inGameScene.setVisible(true); 90 | break; 91 | case PROFILE: 92 | profileScene = new Profile(); 93 | profileScene.setVisible(true); 94 | break; 95 | default: 96 | break; 97 | } 98 | } 99 | } 100 | 101 | public static void closeScene(SceneName sceneName) { 102 | if (null != sceneName) { 103 | switch (sceneName) { 104 | case CONNECTSERVER: 105 | connectServerScene.dispose(); 106 | break; 107 | case LOGIN: 108 | loginScene.dispose(); 109 | break; 110 | case SIGNUP: 111 | signupScene.dispose(); 112 | break; 113 | case MAINMENU: 114 | mainMenuScene.dispose(); 115 | break; 116 | case CHANGEPASSWORD: 117 | changePasswordScene.dispose(); 118 | break; 119 | case INGAME: 120 | inGameScene.dispose(); 121 | break; 122 | case PROFILE: 123 | profileScene.dispose(); 124 | break; 125 | default: 126 | break; 127 | } 128 | } 129 | } 130 | 131 | public static void closeAllScene() { 132 | connectServerScene.dispose(); 133 | loginScene.dispose(); 134 | signupScene.dispose(); 135 | mainMenuScene.dispose(); 136 | changePasswordScene.dispose(); 137 | inGameScene.dispose(); 138 | profileScene.dispose(); 139 | } 140 | 141 | public static void main(String[] args) { 142 | LookAndFeel.setNimbusLookAndFeel(); 143 | new RunClient(); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/Client/model/ChatItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.model; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class ChatItem { 13 | 14 | String time; 15 | String owner; 16 | String content; 17 | 18 | public ChatItem(String time, String owner, String content) { 19 | this.time = time; 20 | this.owner = owner; 21 | this.content = content; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "[" + time + "] " + owner + ": " + content; 27 | } 28 | 29 | public String getTime() { 30 | return time; 31 | } 32 | 33 | public void setTime(String time) { 34 | this.time = time; 35 | } 36 | 37 | public String getOwner() { 38 | return owner; 39 | } 40 | 41 | public void setOwner(String owner) { 42 | this.owner = owner; 43 | } 44 | 45 | public String getContent() { 46 | return content; 47 | } 48 | 49 | public void setContent(String content) { 50 | this.content = content; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/Client/model/CurrentGame.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.model; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * 12 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 13 | */ 14 | public class CurrentGame { 15 | 16 | ArrayList listViewer; 17 | ProfileData player1; 18 | ProfileData player2; 19 | boolean player1Turn; 20 | 21 | int[][] listCell; 22 | 23 | public CurrentGame() { 24 | 25 | } 26 | 27 | public ArrayList getListViewer() { 28 | return listViewer; 29 | } 30 | 31 | public void setListViewer(ArrayList listViewer) { 32 | this.listViewer = listViewer; 33 | } 34 | 35 | public ProfileData getPlayer1() { 36 | return player1; 37 | } 38 | 39 | public void setPlayer1(ProfileData player1) { 40 | this.player1 = player1; 41 | } 42 | 43 | public ProfileData getPlayer2() { 44 | return player2; 45 | } 46 | 47 | public void setPlayer2(ProfileData player2) { 48 | this.player2 = player2; 49 | } 50 | 51 | public boolean isPlayer1Turn() { 52 | return player1Turn; 53 | } 54 | 55 | public void setPlayer1Turn(boolean player1Turn) { 56 | this.player1Turn = player1Turn; 57 | } 58 | 59 | public int[][] getListCell() { 60 | return listCell; 61 | } 62 | 63 | public void setListCell(int[][] listCell) { 64 | this.listCell = listCell; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Client/model/PlayerInGame.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.model; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class PlayerInGame { 13 | 14 | String email; 15 | String nameId; 16 | String avatar; 17 | 18 | public PlayerInGame(String email, String nameId, String avatar) { 19 | this.email = email; 20 | this.nameId = nameId; 21 | this.avatar = avatar; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return nameId; 27 | } 28 | 29 | public String getEmail() { 30 | return email; 31 | } 32 | 33 | public void setEmail(String email) { 34 | this.email = email; 35 | } 36 | 37 | public String getNameId() { 38 | return nameId; 39 | } 40 | 41 | public void setNameId(String nameId) { 42 | this.nameId = nameId; 43 | } 44 | 45 | public String getAvatar() { 46 | return avatar; 47 | } 48 | 49 | public void setAvatar(String avatar) { 50 | this.avatar = avatar; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/Client/model/ProfileData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.model; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class ProfileData { 13 | 14 | int id; 15 | String email = "#"; // cài giá trị mặc định 16 | String name = "#"; 17 | String avatar = "icons8_circled_user_male_skin_type_7_96px.png"; 18 | String gender = "Nam"; 19 | int yearOfBirth = 1999; 20 | 21 | int score = 0; 22 | int matchCount = 0; 23 | int winCount = 0; 24 | int tieCount = 0; 25 | int loseCount = 0; 26 | int currentStreak = 0; 27 | float winRate = 0; 28 | 29 | public ProfileData() { 30 | } 31 | 32 | public ProfileData(int id, String email, String name, String avatar, String gender, int yearOfBirth, int score, int matchCount, int winCount, int tieCount, int loseCount, int currentStreak, float winRate) { 33 | this.id = id; 34 | this.email = email; 35 | this.name = name; 36 | this.avatar = avatar; 37 | this.yearOfBirth = yearOfBirth; 38 | this.gender = gender; 39 | this.score = score; 40 | this.matchCount = matchCount; 41 | this.winCount = winCount; 42 | this.tieCount = tieCount; 43 | this.loseCount = loseCount; 44 | this.currentStreak = currentStreak; 45 | this.winRate = winRate; 46 | } 47 | 48 | public int getId() { 49 | return id; 50 | } 51 | 52 | public void setId(int id) { 53 | this.id = id; 54 | } 55 | 56 | public String getEmail() { 57 | return email; 58 | } 59 | 60 | public void setEmail(String email) { 61 | this.email = email; 62 | } 63 | 64 | public String getName() { 65 | return name; 66 | } 67 | 68 | public void setName(String name) { 69 | this.name = name; 70 | } 71 | 72 | public String getAvatar() { 73 | return avatar; 74 | } 75 | 76 | public void setAvatar(String avatar) { 77 | this.avatar = avatar; 78 | } 79 | 80 | public int getYearOfBirth() { 81 | return yearOfBirth; 82 | } 83 | 84 | public void setYearOfBirth(int yearOfBirth) { 85 | this.yearOfBirth = yearOfBirth; 86 | } 87 | 88 | public String getGender() { 89 | return gender; 90 | } 91 | 92 | public void setGender(String gender) { 93 | this.gender = gender; 94 | } 95 | 96 | public int getScore() { 97 | return score; 98 | } 99 | 100 | public void setScore(int score) { 101 | this.score = score; 102 | } 103 | 104 | public int getMatchCount() { 105 | return matchCount; 106 | } 107 | 108 | public void setMatchCount(int matchCount) { 109 | this.matchCount = matchCount; 110 | } 111 | 112 | public int getWinCount() { 113 | return winCount; 114 | } 115 | 116 | public void setWinCount(int winCount) { 117 | this.winCount = winCount; 118 | } 119 | 120 | public int getTieCount() { 121 | return tieCount; 122 | } 123 | 124 | public void setTieCount(int tieCount) { 125 | this.tieCount = tieCount; 126 | } 127 | 128 | public int getLoseCount() { 129 | return loseCount; 130 | } 131 | 132 | public void setLoseCount(int loseCount) { 133 | this.loseCount = loseCount; 134 | } 135 | 136 | public int getCurrentStreak() { 137 | return currentStreak; 138 | } 139 | 140 | public void setCurrentStreak(int currentStreak) { 141 | this.currentStreak = currentStreak; 142 | } 143 | 144 | public float getWinRate() { 145 | return winRate; 146 | } 147 | 148 | public void setWinRate(float winRate) { 149 | this.winRate = winRate; 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_alien_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_alien_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_angry_face_meme_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_angry_face_meme_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_animation_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_animation_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_avatar_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_avatar_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_bad_piggies_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_bad_piggies_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_bendy_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_bendy_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_captain_america_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_captain_america_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_circled_user_female_skin_type_7_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_circled_user_female_skin_type_7_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_circled_user_male_skin_type_7_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_circled_user_male_skin_type_7_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_confusion_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_confusion_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_crash_bandicoot_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_crash_bandicoot_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_deadpool_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_deadpool_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_elektrovieh_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_elektrovieh_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_gandalf_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_gandalf_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_ghost_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_ghost_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_groot_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_groot_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_hinata_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_hinata_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_hulk_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_hulk_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_ignore_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_ignore_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_iron_man_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_iron_man_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_jake_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_jake_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_jetpack_joyride_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_jetpack_joyride_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_joker_dc_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_joker_dc_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_logan_x_men_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_logan_x_men_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_magneto_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_magneto_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_minecraft_main_character_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_minecraft_main_character_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_minecraft_skeleton_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_minecraft_skeleton_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_minecraft_zombie_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_minecraft_zombie_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_morpheus_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_morpheus_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_naruto_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_naruto_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_neo_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_neo_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_orc_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_orc_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_pelican_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_pelican_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_pennywise_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_pennywise_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_pikachu_pokemon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_pikachu_pokemon_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_rick_sanchez_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_rick_sanchez_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_sailor_moon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_sailor_moon_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_saitama_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_saitama_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_sasuke_uchiha_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_sasuke_uchiha_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_sonic_the_hedgehog_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_sonic_the_hedgehog_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_spider-man_head_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_spider-man_head_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_steven_universe_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_steven_universe_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_super_mario_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_super_mario_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_the_flash_head_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_the_flash_head_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_transformer_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_transformer_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_trinity_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_trinity_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_trollface_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_trollface_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_venom_head_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_venom_head_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_vietnam_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_vietnam_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/avatar/icons8_year_of_rooster_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/avatar/icons8_year_of_rooster_96px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_add_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_add_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_anime_emoji_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_anime_emoji_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_birthday_cake_48px_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_birthday_cake_48px_2.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_cancel_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_cancel_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_circle_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_circle_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_circled_0_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_circled_0_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_circled_play_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_circled_play_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_contact_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_contact_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_delete_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_delete_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_delete_24px_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_delete_24px_1.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_email_48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_email_48px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_exit_sign_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_exit_sign_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_final_state_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_final_state_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_flag_2_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_flag_2_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_forgot_password_48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_forgot_password_48px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_gender_48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_gender_48px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_login_32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_login_32px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_logout_rounded_left_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_logout_rounded_left_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_name_48px_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_name_48px_1.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_naruto_sign_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_naruto_sign_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_new_file_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_new_file_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_ok_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_ok_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_open_door_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_open_door_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_paper_plane_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_paper_plane_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_password_48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_password_48px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_password_reset_48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_password_reset_48px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_replay_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_replay_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_round_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_round_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_slide_up_32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_slide_up_32px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_sphere_30px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_sphere_30px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_sword_48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_sword_48px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_undo_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_undo_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/icons8_vision_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/icons8_vision_24px.png -------------------------------------------------------------------------------- /src/Client/view/asset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Client/view/asset/logo.png -------------------------------------------------------------------------------- /src/Client/view/helper/LookAndFeel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.view.helper; 7 | 8 | import client.RunClient; 9 | import java.awt.Component; 10 | import java.awt.Container; 11 | import javax.swing.UIManager; 12 | import javax.swing.UnsupportedLookAndFeelException; 13 | 14 | /** 15 | * 16 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 17 | */ 18 | public class LookAndFeel { 19 | 20 | // https://stackoverflow.com/a/10986504 21 | public static void enableComponents(Container container, boolean enable) { 22 | Component[] components = container.getComponents(); 23 | for (Component component : components) { 24 | component.setEnabled(enable); 25 | if (component instanceof Container) { 26 | enableComponents((Container) component, enable); 27 | } 28 | } 29 | } 30 | 31 | public static void setSystemLookAndFeel() { 32 | try { 33 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 34 | } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException e) { 35 | 36 | } 37 | } 38 | 39 | public static void setNimbusLookAndFeel() { 40 | /* Set the Nimbus look and feel */ 41 | // 42 | /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 43 | * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 44 | */ 45 | try { 46 | for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 47 | if ("Nimbus".equals(info.getName())) { 48 | javax.swing.UIManager.setLookAndFeel(info.getClassName()); 49 | break; 50 | } 51 | } 52 | } catch (ClassNotFoundException ex) { 53 | java.util.logging.Logger.getLogger(RunClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 54 | } catch (InstantiationException ex) { 55 | java.util.logging.Logger.getLogger(RunClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 56 | } catch (IllegalAccessException ex) { 57 | java.util.logging.Logger.getLogger(RunClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 58 | } catch (javax.swing.UnsupportedLookAndFeelException ex) { 59 | java.util.logging.Logger.getLogger(RunClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 60 | } 61 | // 62 | // 63 | // 64 | // 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Client/view/helper/PlayerInRoomCustomRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.view.helper; 7 | 8 | import client.model.PlayerInGame; 9 | import java.awt.Component; 10 | import javax.swing.ImageIcon; 11 | import javax.swing.JLabel; 12 | import javax.swing.JList; 13 | import javax.swing.ListCellRenderer; 14 | import shared.constant.Avatar; 15 | 16 | /** 17 | * 18 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 19 | */ 20 | // https://www.codejava.net/java-se/swing/jlist-custom-renderer-example 21 | public class PlayerInRoomCustomRenderer extends JLabel implements ListCellRenderer { 22 | 23 | @Override 24 | public Component getListCellRendererComponent(JList jlist, PlayerInGame p, int index, boolean isSelected, boolean cellHasFocus) { 25 | ImageIcon imageIcon = new ImageIcon(Avatar.PATH + p.getAvatar()); 26 | setIcon(imageIcon); 27 | setText(p.getNameId()); 28 | 29 | if (isSelected) { 30 | setBackground(jlist.getSelectionBackground()); 31 | setForeground(jlist.getSelectionForeground()); 32 | } else { 33 | setBackground(jlist.getBackground()); 34 | setForeground(jlist.getForeground()); 35 | } 36 | 37 | return this; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/Client/view/helper/Validation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.view.helper; 7 | 8 | import java.text.Normalizer; 9 | import java.time.LocalDate; 10 | import java.util.regex.Pattern; 11 | import javax.swing.JTextField; 12 | import javax.swing.SwingUtilities; 13 | 14 | /** 15 | * 16 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 17 | */ 18 | public class Validation { 19 | 20 | public static boolean checkEmail(String email) { 21 | String regex = "^[\\w-_\\.+]*[\\w-_\\.]\\@([\\w]+\\.)+[\\w]+[\\w]$"; 22 | return email.matches(regex); 23 | } 24 | 25 | public static boolean checkPassword(String pass) { 26 | return pass.length() >= 6 && pass.length() <= 30; 27 | } 28 | 29 | // Name is invalid if it changed after removing accents, or it has blank space 30 | public static boolean checkName(String name) { 31 | if (!removeAccent(name).equalsIgnoreCase(name) || name.contains(" ")) { 32 | return false; 33 | } 34 | return name.length() > 0 && name.length() <= 15; 35 | } 36 | 37 | //http://sinhviencntt.blogspot.com/2015/01/code-java-chuyen-oi-tieng-viet-co-dau.html 38 | public static String removeAccent(String s) { 39 | String temp = Normalizer.normalize(s, Normalizer.Form.NFD); 40 | Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); 41 | return pattern.matcher(temp).replaceAll(""); 42 | } 43 | 44 | public static boolean checkYearOfBirth(int year) { 45 | LocalDate date = LocalDate.now(); 46 | return year <= date.getYear() && year > date.minusYears(100).getYear(); 47 | } 48 | 49 | public static boolean checkInt(String value) { 50 | try { 51 | Integer.parseInt(value); 52 | return true; 53 | } catch (NumberFormatException e) { 54 | return false; 55 | } 56 | } 57 | 58 | // Listener for NumberInput fields. 59 | // Need to invoke changes to the document from the Event Dispatcher Thread, 60 | // otherwise 'Attempt to mutate notification' exception is Throwed 61 | // https://stackoverflow.com/questions/15206586/getting-attempt-to-mutate-notification-exception 62 | public static void checkNumberInputChanged(JTextField numberFormatedField) { 63 | Runnable doAssist = new Runnable() { 64 | String temp = numberFormatedField.getText();//temp = 1234a 65 | 66 | @Override 67 | public void run() { 68 | // check if input is Integer 69 | if (!checkInt(temp)) { // temp = 1234a 70 | // loop to remove the last char if not Integer until temp is Integer 71 | while (!checkInt(temp)) { // temp = 1234a 72 | temp = temp.substring(0, temp.length() - 1);// temp = 1234 73 | } 74 | // Set temp as text for the textField 75 | numberFormatedField.setText(temp); 76 | } 77 | 78 | } 79 | }; 80 | SwingUtilities.invokeLater(doAssist); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Client/view/helper/WorkWithFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.view.helper; 7 | 8 | import java.io.DataInputStream; 9 | import java.io.DataOutputStream; 10 | import java.io.FileInputStream; 11 | import java.io.FileNotFoundException; 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.util.logging.Level; 15 | import java.util.logging.Logger; 16 | 17 | /** 18 | * 19 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 20 | */ 21 | // source: https://raw.githubusercontent.com/HoangTran0410/SmartPhone_Store_Manage_Java/master/src/giaodienchuan/model/BackEnd/ReadWriteFile/WorkWithFile.java 22 | public class WorkWithFile { 23 | 24 | public static boolean write(String filepath, String s) { 25 | try (DataOutputStream os = new DataOutputStream(new FileOutputStream(filepath, false))) { 26 | os.writeUTF(s); 27 | return true; 28 | } catch (FileNotFoundException ex) { 29 | Logger.getLogger(WorkWithFile.class.getName()).log(Level.SEVERE, null, ex); 30 | } catch (IOException ex) { 31 | Logger.getLogger(WorkWithFile.class.getName()).log(Level.SEVERE, null, ex); 32 | } 33 | 34 | return false; 35 | } 36 | 37 | public static String read(String filepath) { 38 | try (DataInputStream os = new DataInputStream(new FileInputStream(filepath))) { 39 | String result = os.readUTF(); 40 | return result; 41 | } catch (FileNotFoundException ex) { 42 | Logger.getLogger(WorkWithFile.class.getName()).log(Level.SEVERE, null, ex); 43 | } catch (IOException ex) { 44 | Logger.getLogger(WorkWithFile.class.getName()).log(Level.SEVERE, null, ex); 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Client/view/scene/ConnectServer.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/Client/view/scene/ConnectServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package client.view.scene; 7 | 8 | import client.RunClient; 9 | import javax.swing.JOptionPane; 10 | 11 | /** 12 | * 13 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 14 | */ 15 | public class ConnectServer extends javax.swing.JFrame { 16 | 17 | /** 18 | * Creates new form ChooseServer 19 | */ 20 | public ConnectServer() { 21 | initComponents(); 22 | this.setLocationRelativeTo(null); 23 | 24 | // default is hidden 25 | pgbLoading.setVisible(false); 26 | } 27 | 28 | public void setLoading(boolean isLoading, String btnText) { 29 | pgbLoading.setVisible(isLoading); 30 | btnConnect.setEnabled(!isLoading); 31 | btnConnect.setText(isLoading ? btnText : "Kết nối"); 32 | } 33 | 34 | /** 35 | * This method is called from within the constructor to initialize the form. 36 | * WARNING: Do NOT modify this code. The content of this method is always 37 | * regenerated by the Form Editor. 38 | */ 39 | @SuppressWarnings("unchecked") 40 | // //GEN-BEGIN:initComponents 41 | private void initComponents() { 42 | 43 | txIP = new javax.swing.JTextField(); 44 | txPort = new javax.swing.JTextField(); 45 | jLabel2 = new javax.swing.JLabel(); 46 | btnConnect = new javax.swing.JButton(); 47 | jLabel3 = new javax.swing.JLabel(); 48 | jLabel4 = new javax.swing.JLabel(); 49 | pgbLoading = new javax.swing.JProgressBar(); 50 | 51 | setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 52 | setTitle("Kết nối"); 53 | 54 | txIP.setFont(new java.awt.Font("Consolas", 0, 18)); // NOI18N 55 | txIP.setText("127.0.0.1"); 56 | 57 | txPort.setFont(new java.awt.Font("Consolas", 0, 18)); // NOI18N 58 | txPort.setText("5056"); 59 | 60 | jLabel2.setFont(new java.awt.Font("Dialog", 1, 24)); // NOI18N 61 | jLabel2.setText("KẾT NỐI SERVER"); 62 | 63 | btnConnect.setFont(new java.awt.Font("Dialog", 1, 18)); // NOI18N 64 | btnConnect.setText("Kết nối"); 65 | btnConnect.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); 66 | btnConnect.addActionListener(new java.awt.event.ActionListener() { 67 | public void actionPerformed(java.awt.event.ActionEvent evt) { 68 | btnConnectActionPerformed(evt); 69 | } 70 | }); 71 | 72 | jLabel3.setText("IP"); 73 | 74 | jLabel4.setText("Port"); 75 | 76 | pgbLoading.setIndeterminate(true); 77 | 78 | javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 79 | getContentPane().setLayout(layout); 80 | layout.setHorizontalGroup( 81 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 82 | .addGroup(layout.createSequentialGroup() 83 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 84 | .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() 85 | .addGap(10, 10, 10) 86 | .addComponent(jLabel2)) 87 | .addGroup(layout.createSequentialGroup() 88 | .addContainerGap() 89 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 90 | .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 91 | .addComponent(pgbLoading, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE) 92 | .addGroup(layout.createSequentialGroup() 93 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 94 | .addComponent(txIP, javax.swing.GroupLayout.PREFERRED_SIZE, 207, javax.swing.GroupLayout.PREFERRED_SIZE) 95 | .addGroup(layout.createSequentialGroup() 96 | .addGap(92, 92, 92) 97 | .addComponent(jLabel3))) 98 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 99 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 100 | .addComponent(txPort) 101 | .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 102 | .addGap(0, 0, Short.MAX_VALUE) 103 | .addComponent(jLabel4) 104 | .addGap(29, 29, 29))))))) 105 | .addContainerGap()) 106 | ); 107 | layout.setVerticalGroup( 108 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 109 | .addGroup(layout.createSequentialGroup() 110 | .addContainerGap() 111 | .addComponent(jLabel2) 112 | .addGap(18, 18, 18) 113 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 114 | .addComponent(jLabel4) 115 | .addComponent(jLabel3)) 116 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 117 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 118 | .addComponent(txIP, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 119 | .addComponent(txPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) 120 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 24, Short.MAX_VALUE) 121 | .addComponent(pgbLoading, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 122 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 123 | .addComponent(btnConnect, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE) 124 | .addContainerGap()) 125 | ); 126 | 127 | pack(); 128 | }// //GEN-END:initComponents 129 | 130 | private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed 131 | String ip; 132 | int port; 133 | 134 | // validate input 135 | try { 136 | ip = txIP.getText(); 137 | port = Integer.parseInt(txPort.getText()); 138 | 139 | if (port < 0 || port > 65535) { 140 | JOptionPane.showMessageDialog(this, "Port phải từ 0 - 65535", "Sai port", JOptionPane.ERROR_MESSAGE); 141 | txPort.requestFocus(); 142 | return; 143 | } 144 | 145 | } catch (NumberFormatException e) { 146 | JOptionPane.showMessageDialog(this, "Port phải là số nguyên", "Sai port", JOptionPane.ERROR_MESSAGE); 147 | txPort.requestFocus(); 148 | return; 149 | } 150 | 151 | // connect to server 152 | connect(ip, port); 153 | }//GEN-LAST:event_btnConnectActionPerformed 154 | 155 | private void connect(String ip, int port) { 156 | // show loading 157 | setLoading(true, "Đang kết nối.."); 158 | 159 | // connect to server 160 | new Thread(() -> { 161 | // call controller 162 | String result = RunClient.socketHandler.connect(ip, port); 163 | 164 | // check result 165 | if (result.equals("success")) { 166 | onSuccess(); 167 | } else { 168 | String failedMsg = result.split(";")[1]; 169 | onFailed(failedMsg); 170 | } 171 | }).start(); 172 | } 173 | 174 | private void onSuccess() { 175 | // Kết nối thành công nhưng vẫn chờ server gửi thông báo đã nhận AES key 176 | // Scene sẽ được chuyển qua LoginScene khi client nhận được phản hồi từ server 177 | // => code chuyển scene được đưa vào socket handler, lúc listen nhận được AESKEY từ server 178 | // this.dispose(); 179 | // RunClient.openScene(RunClient.SceneName.LOGIN); 180 | 181 | // khi kết nối thành công sẽ đợi tạo kết nối bảo mật (gửi nhận AES key) 182 | setLoading(true, "Đang bảo mật.."); 183 | } 184 | 185 | private void onFailed(String failedMsg) { 186 | setLoading(false, null); 187 | JOptionPane.showMessageDialog(this, failedMsg, "Lỗi kết nối", JOptionPane.ERROR_MESSAGE); 188 | } 189 | 190 | /** 191 | * @param args the command line arguments 192 | */ 193 | public static void main(String args[]) { 194 | /* Set the Nimbus look and feel */ 195 | // 196 | /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 197 | * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 198 | */ 199 | try { 200 | for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 201 | if ("Nimbus".equals(info.getName())) { 202 | javax.swing.UIManager.setLookAndFeel(info.getClassName()); 203 | break; 204 | } 205 | } 206 | } catch (ClassNotFoundException ex) { 207 | java.util.logging.Logger.getLogger(ConnectServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 208 | } catch (InstantiationException ex) { 209 | java.util.logging.Logger.getLogger(ConnectServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 210 | } catch (IllegalAccessException ex) { 211 | java.util.logging.Logger.getLogger(ConnectServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 212 | } catch (javax.swing.UnsupportedLookAndFeelException ex) { 213 | java.util.logging.Logger.getLogger(ConnectServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 214 | } 215 | // 216 | // 217 | 218 | /* Create and display the form */ 219 | java.awt.EventQueue.invokeLater(new Runnable() { 220 | public void run() { 221 | new ConnectServer().setVisible(true); 222 | } 223 | }); 224 | } 225 | 226 | // Variables declaration - do not modify//GEN-BEGIN:variables 227 | private javax.swing.JButton btnConnect; 228 | private javax.swing.JLabel jLabel2; 229 | private javax.swing.JLabel jLabel3; 230 | private javax.swing.JLabel jLabel4; 231 | private javax.swing.JProgressBar pgbLoading; 232 | private javax.swing.JTextField txIP; 233 | private javax.swing.JTextField txPort; 234 | // End of variables declaration//GEN-END:variables 235 | } 236 | -------------------------------------------------------------------------------- /src/Client/view/scene/Login.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/BUS/GameMatchBUS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.BUS; 7 | 8 | import server.db.layers.DAL.GameMatchDAL; 9 | import server.db.layers.DTO.GameMatch; 10 | import java.util.ArrayList; 11 | 12 | /** 13 | * 14 | * @author nguye 15 | */ 16 | public class GameMatchBUS { 17 | 18 | ArrayList listGameMatch = new ArrayList<>(); 19 | GameMatchDAL gameMatchDAL = new GameMatchDAL(); 20 | 21 | public GameMatchBUS() { 22 | readDB(); 23 | } 24 | 25 | public void readDB() { 26 | listGameMatch = gameMatchDAL.readDB(); 27 | } 28 | 29 | public boolean add(GameMatch g) { 30 | boolean status = gameMatchDAL.add(g); 31 | 32 | if (status == true) { 33 | listGameMatch.add(g); 34 | } 35 | 36 | return status; 37 | } 38 | 39 | public boolean delete(int id) { 40 | boolean status = gameMatchDAL.delete(id); 41 | 42 | if (status == true) { 43 | for (int i = (listGameMatch.size() - 1); i >= 0; i--) { 44 | if (listGameMatch.get(i).getId() == id) { 45 | listGameMatch.remove(i); 46 | } 47 | } 48 | } 49 | 50 | return status; 51 | } 52 | 53 | public boolean update(GameMatch g) { 54 | boolean status = gameMatchDAL.update(g); 55 | 56 | if (status == true) { 57 | listGameMatch.forEach((gm) -> { 58 | gm = new GameMatch(g); 59 | }); 60 | } 61 | 62 | return status; 63 | } 64 | 65 | public GameMatch getById(int id) { 66 | for (GameMatch g : listGameMatch) { 67 | if (g.getId() == id) { 68 | return g; 69 | } 70 | } 71 | return null; 72 | } 73 | 74 | // ================ utils =================== 75 | public int calculateTotalMatch(int playerId) { 76 | int result = 0; 77 | 78 | for (GameMatch m : listGameMatch) { 79 | if (m.getPlayerID1() == playerId || m.getPlayerID2() == playerId) { 80 | result++; 81 | } 82 | } 83 | return result; 84 | } 85 | 86 | public int calculateWinCount(int playerId) { 87 | int result = 0; 88 | 89 | for (GameMatch m : listGameMatch) { 90 | if (m.getWinnerID() == playerId) { 91 | result++; 92 | } 93 | } 94 | return result; 95 | } 96 | 97 | public int calculateLongestWinStreak(int playerId) { 98 | int longest = 0; 99 | int current = 0; 100 | 101 | for (GameMatch m : listGameMatch) { 102 | if (m.getPlayerID1() == playerId || m.getPlayerID2() == playerId) { 103 | if (m.getWinnerID() == playerId) { 104 | current++; 105 | } else { 106 | if (current > longest) { 107 | longest = current; 108 | } 109 | current = 0; 110 | } 111 | } 112 | } 113 | 114 | return longest; 115 | } 116 | 117 | public float calculateWinRate(int playerId) { 118 | return (float) (100.00 * (calculateWinCount(playerId) / calculateTotalMatch(playerId))); 119 | } 120 | 121 | public ArrayList getList() { 122 | return listGameMatch; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/BUS/PlayerBUS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.BUS; 7 | 8 | import server.db.layers.DAL.PlayerDAL; 9 | import server.db.layers.DTO.Player; 10 | import java.util.ArrayList; 11 | import shared.constant.Code; 12 | 13 | /** 14 | * 15 | * @author nguye 16 | */ 17 | public class PlayerBUS { 18 | 19 | ArrayList listPlayer = new ArrayList<>(); 20 | PlayerDAL playerDAL = new PlayerDAL(); 21 | 22 | public PlayerBUS() { 23 | readDB(); 24 | } 25 | 26 | public void readDB() { 27 | listPlayer = playerDAL.readDB(); 28 | } 29 | 30 | public boolean add(Player p) { 31 | boolean status = playerDAL.add(p); 32 | 33 | if (status == true) { 34 | listPlayer.add(p); 35 | } 36 | 37 | return status; 38 | } 39 | 40 | public boolean delete(int id) { 41 | boolean status = playerDAL.delete(id); 42 | 43 | if (status == true) { 44 | for (int i = (listPlayer.size() - 1); i >= 0; i--) { 45 | if (listPlayer.get(i).getId() == id) { 46 | listPlayer.remove(i); 47 | } 48 | } 49 | } 50 | 51 | return status; 52 | } 53 | 54 | public boolean update(Player p) { 55 | boolean status = playerDAL.update(p); 56 | 57 | if (status == true) { 58 | listPlayer.forEach((pl) -> { 59 | pl = new Player(p); 60 | }); 61 | } 62 | 63 | return status; 64 | } 65 | 66 | public Player getById(int id) { 67 | for (Player p : listPlayer) { 68 | if (p.getId() == id) { 69 | return p; 70 | } 71 | } 72 | return null; 73 | } 74 | 75 | public Player getByEmail(String email) { 76 | for (Player p : listPlayer) { 77 | if (p.getEmail().equals(email)) { 78 | return p; 79 | } 80 | } 81 | return null; 82 | } 83 | 84 | public ArrayList getList() { 85 | return listPlayer; 86 | } 87 | 88 | public String checkLogin(String email, String password) { 89 | // code vòng for như getByEmail là được, nhưng netbeans nó hiện bóng đèn sáng ấn vào thì ra code này 90 | // thấy "ngầu" nên để lại :)) 91 | // return listPlayer.stream().anyMatch((p) -> (p.getEmail().equals(email) && p.getPassword().equals(password))); 92 | // nhưng chợt nhận ra có block player nữa, nên phải trả về String chứ ko được boolean :( 93 | 94 | // check email 95 | Player p = getByEmail(email); 96 | if (p == null) { 97 | return "failed;" + Code.ACCOUNT_NOT_FOUND; 98 | } 99 | 100 | // check password 101 | if (!p.getPassword().equals(password)) { 102 | return "failed;" + Code.WRONG_PASSWORD; 103 | } 104 | 105 | // check blocked 106 | if (p.isBlocked()) { 107 | return "failed;" + Code.ACCOUNT_BLOCKED; 108 | } 109 | 110 | return "success;" + email; 111 | } 112 | 113 | public String changePassword(String email, String oldPassword, String newPassword) { 114 | // check email 115 | Player p = getByEmail(email); 116 | if (p == null) { 117 | return "failed;" + Code.ACCOUNT_NOT_FOUND; 118 | } 119 | 120 | // check password 121 | if (!p.getPassword().equals(oldPassword)) { 122 | return "failed;" + Code.WRONG_PASSWORD; 123 | } 124 | 125 | // đặt pass mới 126 | p.setPassword(newPassword); 127 | boolean status = update(p); 128 | if (!status) { 129 | // lỗi không xác định 130 | return "failed;Lỗi khi đổi mật khẩu"; 131 | } 132 | 133 | return "success"; 134 | } 135 | 136 | public String signup(String email, String password, String avatar, String name, String gender, int yearOfBirth) { 137 | 138 | // check email 139 | Player p = getByEmail(email); 140 | if (p != null) { 141 | return "failed;" + Code.EMAIL_EXISTED; 142 | } 143 | 144 | // thêm vào db 145 | boolean status = add(new Player(email, password, avatar, name, gender, yearOfBirth)); 146 | if (!status) { 147 | // lỗi ko xác định 148 | return "failed;Lỗi khi đăng ký"; 149 | } 150 | 151 | return "success"; 152 | } 153 | 154 | public String editProfile(String email, String newEmail, String name, String avatar, int yearOfBirth, String gender) { 155 | // check trung email 156 | if (!newEmail.equals(email) && getByEmail(newEmail) != null) { 157 | return "failed;" + Code.EMAIL_EXISTED; 158 | } 159 | 160 | // check email 161 | Player p = getByEmail(email); 162 | if (p == null) { 163 | return "failed;" + Code.ACCOUNT_NOT_FOUND; 164 | } 165 | 166 | // set data 167 | p.setEmail(newEmail); 168 | p.setName(name); 169 | p.setAvatar(avatar); 170 | p.setYearOfBirth(yearOfBirth); 171 | p.setGender(gender); 172 | 173 | // update 174 | boolean status = update(p); 175 | 176 | if (!status) { 177 | return "failed;Lỗi khi cập nhật thông tin cá nhân"; 178 | } 179 | 180 | return "success;" + newEmail; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/DAL/GameMatchDAL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.DAL; 7 | 8 | import server.db.layers.DBConnector.MysqlConnector; 9 | import server.db.layers.DTO.GameMatch; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.ArrayList; 13 | import java.sql.PreparedStatement; 14 | import java.time.LocalDateTime; 15 | import java.util.logging.Level; 16 | import java.util.logging.Logger; 17 | 18 | /** 19 | * 20 | * @author nguye 21 | */ 22 | public class GameMatchDAL { 23 | 24 | MysqlConnector connector; 25 | 26 | public GameMatchDAL() { 27 | 28 | } 29 | 30 | public ArrayList readDB() { 31 | ArrayList result = new ArrayList<>(); 32 | connector = new MysqlConnector(); 33 | 34 | try { 35 | String qry = "SELECT * FROM gamematch;"; 36 | PreparedStatement stm = connector.getConnection().prepareStatement(qry); 37 | ResultSet rs = connector.sqlQry(stm); 38 | 39 | if (rs != null) { 40 | while (rs.next()) { 41 | GameMatch g = new GameMatch( 42 | rs.getInt("ID"), 43 | rs.getInt("PlayerID1"), 44 | rs.getInt("PlayerID2"), 45 | rs.getInt("WinnerID"), 46 | rs.getInt("PlayTime"), 47 | rs.getInt("TotalMove"), 48 | LocalDateTime.parse(rs.getString("StartedTime")), 49 | rs.getString("Chat") 50 | ); 51 | 52 | result.add(g); 53 | } 54 | } 55 | 56 | } catch (SQLException e) { 57 | System.err.println("Error while trying to read Matchs info from database!"); 58 | } finally { 59 | connector.closeConnection(); 60 | } 61 | 62 | return result; 63 | } 64 | 65 | public boolean add(GameMatch m) { 66 | boolean result = false; 67 | connector = new MysqlConnector(); 68 | 69 | try { 70 | String sql = "INSERT INTO GameMatch(PlayerID1,PlayerID2,WinnerID,PlayTime,TotalMove,StartedTime) " 71 | + "VALUES(?,?,?,?,?,?)"; 72 | PreparedStatement stm = connector.getConnection().prepareStatement(sql); 73 | stm.setInt(1, m.getPlayerID1()); 74 | stm.setInt(2, m.getPlayerID2()); 75 | stm.setInt(3, m.getWinnerID()); 76 | stm.setInt(4, m.getPlayTime()); 77 | stm.setInt(5, m.getTotalMove()); 78 | stm.setString(6, m.getStartedTime().toString()); 79 | 80 | result = connector.sqlUpdate(stm); 81 | } catch (SQLException ex) { 82 | Logger.getLogger(GameMatchDAL.class.getName()).log(Level.SEVERE, null, ex); 83 | } finally { 84 | connector.closeConnection(); 85 | } 86 | 87 | return result; 88 | } 89 | 90 | public boolean update(GameMatch m) { 91 | boolean result = false; 92 | connector = new MysqlConnector(); 93 | 94 | try { 95 | String sql = "UPDATE GameMatch SET " 96 | + "PlayerID1=?," 97 | + "PlayerID2=?," 98 | + "WinnerID=?," 99 | + "PlayTime=?," 100 | + "TotalMove=?," 101 | + "StartedTime=?" 102 | + " WHERE ID=?"; 103 | 104 | PreparedStatement stm = connector.getConnection().prepareStatement(sql); 105 | stm.setInt(1, m.getPlayerID1()); 106 | stm.setInt(2, m.getPlayerID2()); 107 | stm.setInt(3, m.getWinnerID()); 108 | stm.setInt(4, m.getPlayTime()); 109 | stm.setInt(5, m.getTotalMove()); 110 | stm.setString(6, m.getStartedTime().toString()); 111 | stm.setInt(7, m.getId()); 112 | 113 | result = connector.sqlUpdate(stm); 114 | } catch (SQLException ex) { 115 | Logger.getLogger(GameMatchDAL.class.getName()).log(Level.SEVERE, null, ex); 116 | } finally { 117 | connector.closeConnection(); 118 | } 119 | 120 | return result; 121 | } 122 | 123 | public boolean delete(int id) { 124 | boolean result = false; 125 | connector = new MysqlConnector(); 126 | 127 | try { 128 | String qry = "DELETE FROM GameMatch WHERE ID=?"; 129 | 130 | PreparedStatement stm = connector.getConnection().prepareStatement(qry); 131 | stm.setInt(1, id); 132 | 133 | result = connector.sqlUpdate(stm); 134 | } catch (SQLException ex) { 135 | Logger.getLogger(GameMatchDAL.class.getName()).log(Level.SEVERE, null, ex); 136 | } finally { 137 | connector.closeConnection(); 138 | } 139 | 140 | return result; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/DAL/PlayerDAL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.DAL; 7 | 8 | import server.db.layers.DBConnector.MysqlConnector; 9 | import server.db.layers.DTO.Player; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.util.ArrayList; 14 | import java.util.logging.Level; 15 | import java.util.logging.Logger; 16 | 17 | /** 18 | * 19 | * @author nguye 20 | */ 21 | public class PlayerDAL { 22 | 23 | MysqlConnector connector; 24 | 25 | public PlayerDAL() { 26 | 27 | } 28 | 29 | public ArrayList readDB() { 30 | ArrayList result = new ArrayList<>(); 31 | connector = new MysqlConnector(); 32 | 33 | try { 34 | String qry = "SELECT * FROM Player;"; 35 | PreparedStatement stm = connector.getConnection().prepareStatement(qry); 36 | ResultSet rs = connector.sqlQry(stm); 37 | 38 | if (rs != null) { 39 | while (rs.next()) { 40 | Player p = new Player( 41 | rs.getInt("ID"), 42 | rs.getString("Email"), 43 | rs.getString("Password"), 44 | rs.getString("Avatar"), 45 | rs.getString("Name"), 46 | rs.getString("Gender"), 47 | rs.getInt("YearOfBirth"), 48 | rs.getInt("Score"), 49 | rs.getInt("MatchCount"), 50 | rs.getInt("WinCount"), 51 | rs.getInt("LoseCount"), 52 | rs.getInt("CurrentStreak"), 53 | rs.getBoolean("Blocked") 54 | ); 55 | result.add(p); 56 | } 57 | } 58 | 59 | } catch (SQLException e) { 60 | System.err.println("Error while trying to read Players info from database!"); 61 | } finally { 62 | connector.closeConnection(); 63 | } 64 | 65 | return result; 66 | } 67 | 68 | public boolean add(Player p) { 69 | boolean result = false; 70 | connector = new MysqlConnector(); 71 | 72 | try { 73 | String qry = "INSERT INTO Player(Email,Password,Avatar,Name,Gender,YearOfBirth,Score,MatchCount,WinCount,LoseCount,CurrentStreak,Blocked) " 74 | + "VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"; 75 | 76 | PreparedStatement stm = connector.getConnection().prepareStatement(qry); 77 | stm.setString(1, p.getEmail()); 78 | stm.setString(2, p.getPassword()); 79 | stm.setString(3, p.getAvatar()); 80 | stm.setString(4, p.getName()); 81 | stm.setString(5, p.getGender()); 82 | stm.setInt(6, p.getYearOfBirth()); 83 | stm.setInt(7, p.getScore()); 84 | stm.setInt(8, p.getMatchCount()); 85 | stm.setInt(9, p.getWinCount()); 86 | stm.setInt(10, p.getLoseCount()); 87 | stm.setInt(11, p.getCurrentStreak()); 88 | stm.setBoolean(12, p.isBlocked()); 89 | 90 | result = connector.sqlUpdate(stm); 91 | } catch (SQLException ex) { 92 | Logger.getLogger(PlayerDAL.class.getName()).log(Level.SEVERE, null, ex); 93 | } finally { 94 | connector.closeConnection(); 95 | } 96 | 97 | return result; 98 | } 99 | 100 | public boolean update(Player p) { 101 | boolean result = false; 102 | connector = new MysqlConnector(); 103 | 104 | try { 105 | String qry = "UPDATE Player SET " 106 | + "Email=?," 107 | + "Password=?," 108 | + "Avatar=?," 109 | + "Name=?," 110 | + "Gender=?," 111 | + "YearOfBirth=?," 112 | + "Score=?," 113 | + "MatchCount=?," 114 | + "WinCount=?," 115 | + "LoseCount=?," 116 | + "CurrentStreak=?," 117 | + "Blocked=?" 118 | + " WHERE ID=?"; 119 | 120 | PreparedStatement stm = connector.getConnection().prepareStatement(qry); 121 | 122 | stm.setString(1, p.getEmail()); 123 | stm.setString(2, p.getPassword()); 124 | stm.setString(3, p.getAvatar()); 125 | stm.setString(4, p.getName()); 126 | stm.setString(5, p.getGender()); 127 | stm.setInt(6, p.getYearOfBirth()); 128 | stm.setInt(7, p.getScore()); 129 | stm.setInt(8, p.getMatchCount()); 130 | stm.setInt(9, p.getWinCount()); 131 | stm.setInt(10, p.getLoseCount()); 132 | stm.setInt(11, p.getCurrentStreak()); 133 | stm.setBoolean(12, p.isBlocked()); 134 | stm.setInt(13, p.getId()); 135 | 136 | result = connector.sqlUpdate(stm); 137 | } catch (SQLException ex) { 138 | Logger.getLogger(PlayerDAL.class.getName()).log(Level.SEVERE, null, ex); 139 | } finally { 140 | connector.closeConnection(); 141 | } 142 | 143 | return result; 144 | } 145 | 146 | public boolean delete(int id) { 147 | boolean result = false; 148 | connector = new MysqlConnector(); 149 | 150 | try { 151 | String qry = "DELETE FROM player WHERE ID=?"; 152 | 153 | PreparedStatement stm = connector.getConnection().prepareStatement(qry); 154 | stm.setInt(1, id); 155 | 156 | result = connector.sqlUpdate(stm); 157 | } catch (SQLException ex) { 158 | Logger.getLogger(PlayerDAL.class.getName()).log(Level.SEVERE, null, ex); 159 | } 160 | return result; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/DBConnector/DB_structure.txt: -------------------------------------------------------------------------------- 1 | - Player 2 | ID : AUTO_INCREASEMENT 3 | Email : varchar(50) (unique) 4 | Password : varchar(50) (hash) 5 | Name : varchar(50) 6 | Avatar : varchar(50) (file path) 7 | Gender : varchar(10) (nam-nữ-ẩn) 8 | YearOfBirth : int(4) năm sinh (1999, 2000, ..) 9 | Score : int(11) điểm thành tích 10 | MatchCount : int(11) số trận đã đấu 11 | WinCount : int(11) số trận thắng 12 | LoseCount : int(11) số trận thua 13 | CurrentStreak : int(11) chuỗi thắng/thua liên tiếp ở thời điểm hiện tại (số âm là chuỗi thua, số dương là chuỗi thắng) 14 | Blocked : tinyint(1) bị block hay không 15 | 16 | - GameMatch 17 | ID : AUTO_INCREASEMENT 18 | PlayerID1 : int(11) player id 1 19 | PlayerID2 : int(11) player id 2 20 | WinnerID : int(11) winnner id (null nếu hòa) 21 | PlayTime : int(11) thời lượng chơi (giây) 22 | TotalMove : int(11) số bước di chuyển 23 | StartedTime : datetime thời gian bắt đầu trận đấu 24 | Chat : varchar(50) file url, lưu chat vào file (optional) 25 | 26 | 27 | ============= hiện tại bỏ ====================================================== 28 | Rank (Optional) 29 | // Bậc xếp hạng, giống lmht, cho ng chơi có mục tiêu phấn đấu :)) 30 | + id : AUTO_INCREASEMENT 31 | + name : nchar(20) Đồng-Bạc-Vàng-Bạch Kim- gì gì đó. 32 | + scorerequired : int (điểm cần để thuộc rank này) 33 | + description : nchar(50) 34 | 35 | Friend (optional) 36 | + id : AUTO_INCREASEMENT 37 | + user1 : playerID 38 | + user2 : playerID 39 | + datemakefriend : datetime -------------------------------------------------------------------------------- /src/Server/DB/Layers/DBConnector/MysqlConnector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.DBConnector; 7 | 8 | import java.sql.PreparedStatement; 9 | import java.sql.Connection; 10 | import java.sql.DriverManager; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | 14 | /** 15 | * 16 | * @author nguye 17 | */ 18 | public class MysqlConnector { 19 | 20 | Connection conn = null; 21 | 22 | String server = "localhost:3306"; 23 | String db = "carodb"; 24 | String user = "root"; 25 | String pass = ""; 26 | 27 | public MysqlConnector() { 28 | checkDriver(); 29 | setupConnection(); 30 | } 31 | 32 | public void logIn(String userName, String pass) { 33 | this.user = userName; 34 | this.pass = pass; 35 | setupConnection(); 36 | } 37 | 38 | boolean checkDriver() { 39 | try { 40 | Class.forName("com.mysql.jdbc.Driver"); 41 | return true; 42 | } catch (ClassNotFoundException e) { 43 | System.err.println("Khong tim thay Driver mysql !!"); 44 | return false; 45 | } 46 | } 47 | 48 | public boolean setupConnection() { 49 | try { 50 | String url = "jdbc:mysql://" + server + "/" + db + "?useUnicode=true&characterEncoding=UTF-8"; 51 | conn = DriverManager.getConnection(url, user, pass); 52 | return true; 53 | } catch (SQLException e) { 54 | System.err.println("Loi ket noi DB: " + e.getMessage()); 55 | return false; 56 | } 57 | } 58 | 59 | public ResultSet sqlQry(PreparedStatement stm) { 60 | if (checkConnection()) { 61 | try { 62 | ResultSet rs = stm.executeQuery(); 63 | return rs; 64 | } catch (SQLException e) { 65 | System.err.println("Loi thuc thi sql query: " + stm.toString() + " , " + e.getMessage()); 66 | } 67 | } 68 | return null; 69 | } 70 | 71 | public boolean sqlUpdate(PreparedStatement stm) { 72 | if (checkConnection()) { 73 | try { 74 | stm.executeUpdate(); 75 | return true; 76 | } catch (SQLException e) { 77 | System.err.println("Loi thuc thi sql update: " + stm.toString() + " , " + e.getMessage()); 78 | } 79 | } 80 | return false; 81 | } 82 | 83 | public boolean checkConnection() { 84 | if (conn == null) { 85 | return false; 86 | } 87 | return true; 88 | } 89 | 90 | public boolean closeConnection() { 91 | try { 92 | if (conn != null) { 93 | conn.close(); 94 | } 95 | return true; 96 | 97 | } catch (SQLException e) { 98 | System.err.println("Không thể đóng kết nối tới " + db); 99 | return false; 100 | } 101 | } 102 | 103 | public Connection getConnection() { 104 | return conn; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/DTO/GameMatch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.DTO; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * 12 | * @author nguye 13 | */ 14 | public class GameMatch { 15 | 16 | int id; 17 | int playerID1; 18 | int playerID2; 19 | int winnerID; 20 | int playTime; 21 | int totalMove; 22 | LocalDateTime startedTime; 23 | String chat = ""; 24 | 25 | public GameMatch(int id, int playerID1, int playerID2, int winnerID, int playTime, int totalMove, LocalDateTime startedTime, String chat) { 26 | this.id = id; 27 | this.playerID1 = playerID1; 28 | this.playerID2 = playerID2; 29 | this.winnerID = winnerID; 30 | this.playTime = playTime; 31 | this.totalMove = totalMove; 32 | this.startedTime = startedTime; 33 | this.chat = chat; 34 | } 35 | 36 | public GameMatch(int playerID1, int playerID2, int winnerID, int playTime, int totalMove, LocalDateTime startedTime) { 37 | this.playerID1 = playerID1; 38 | this.playerID2 = playerID2; 39 | this.winnerID = winnerID; 40 | this.playTime = playTime; 41 | this.totalMove = totalMove; 42 | this.startedTime = startedTime; 43 | } 44 | 45 | public GameMatch(GameMatch g) { 46 | this.id = g.id; 47 | this.playerID1 = g.playerID1; 48 | this.playerID2 = g.playerID2; 49 | this.winnerID = g.winnerID; 50 | this.playTime = g.playTime; 51 | this.totalMove = g.totalMove; 52 | this.startedTime = g.startedTime; 53 | this.chat = g.chat; 54 | } 55 | 56 | public int getId() { 57 | return id; 58 | } 59 | 60 | public void setId(int id) { 61 | this.id = id; 62 | } 63 | 64 | public int getPlayerID1() { 65 | return playerID1; 66 | } 67 | 68 | public void setPlayerID1(int playerID1) { 69 | this.playerID1 = playerID1; 70 | } 71 | 72 | public int getPlayerID2() { 73 | return playerID2; 74 | } 75 | 76 | public void setPlayerID2(int playerID2) { 77 | this.playerID2 = playerID2; 78 | } 79 | 80 | public int getWinnerID() { 81 | return winnerID; 82 | } 83 | 84 | public void setWinnerID(int winnerID) { 85 | this.winnerID = winnerID; 86 | } 87 | 88 | public int getPlayTime() { 89 | return playTime; 90 | } 91 | 92 | public void setPlayTime(int playTime) { 93 | this.playTime = playTime; 94 | } 95 | 96 | public int getTotalMove() { 97 | return totalMove; 98 | } 99 | 100 | public void setTotalMove(int totalMove) { 101 | this.totalMove = totalMove; 102 | } 103 | 104 | public LocalDateTime getStartedTime() { 105 | return startedTime; 106 | } 107 | 108 | public void setStartedTime(LocalDateTime startedTime) { 109 | this.startedTime = startedTime; 110 | } 111 | 112 | public String getChat() { 113 | return chat; 114 | } 115 | 116 | public void setChat(String chat) { 117 | this.chat = chat; 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/Server/DB/Layers/DTO/Player.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.db.layers.DTO; 7 | 8 | /** 9 | * 10 | * @author nguye 11 | */ 12 | public class Player { 13 | 14 | int id; 15 | String email; 16 | String password; 17 | String avatar; 18 | String name; 19 | String gender; 20 | int yearOfBirth; 21 | int score = 0; // gia tri mac dinh 22 | int matchCount = 0; 23 | int winCount = 0; 24 | int loseCount = 0; 25 | int currentStreak = 0; // số âm là chuỗi thua, dương là chuỗi thắng 26 | boolean blocked = false; 27 | 28 | public Player() { 29 | 30 | } 31 | 32 | public void addScore(int toAdd) { 33 | this.score += toAdd; 34 | } 35 | 36 | public Player(int id, String email, String password, String avatar, String name, String gender, int yearOfBirth, int score, int matchCount, int winCount, int loseCount, int currentStreak, boolean blocked) { 37 | this.id = id; 38 | this.email = email; 39 | this.password = password; 40 | this.avatar = avatar; 41 | this.name = name; 42 | this.gender = gender; 43 | this.yearOfBirth = yearOfBirth; 44 | this.score = score; 45 | this.matchCount = matchCount; 46 | this.winCount = winCount; 47 | this.loseCount = loseCount; 48 | this.currentStreak = currentStreak; 49 | this.blocked = blocked; 50 | } 51 | 52 | public Player(String email, String password, String avatar, String name, String gender, int yearOfBirth) { 53 | this.email = email; 54 | this.password = password; 55 | this.avatar = avatar; 56 | this.name = name; 57 | this.gender = gender; 58 | this.yearOfBirth = yearOfBirth; 59 | } 60 | 61 | public Player(Player p) { 62 | this.id = p.id; 63 | this.email = p.email; 64 | this.password = p.password; 65 | this.avatar = p.avatar; 66 | this.name = p.name; 67 | this.gender = p.gender; 68 | this.yearOfBirth = p.yearOfBirth; 69 | this.score = p.score; 70 | this.matchCount = p.matchCount; 71 | this.winCount = p.winCount; 72 | this.loseCount = p.loseCount; 73 | this.currentStreak = p.currentStreak; 74 | this.blocked = p.blocked; 75 | } 76 | 77 | public int calculateTieCount() { 78 | return matchCount - winCount - loseCount; 79 | } 80 | 81 | public float calculateWinRate() { 82 | if (this.matchCount == 0) { 83 | return 0; 84 | } 85 | 86 | return (float) (100.0 * winCount / matchCount); 87 | } 88 | 89 | public String getNameId() { 90 | return name + " #" + id; 91 | } 92 | 93 | public int getId() { 94 | return id; 95 | } 96 | 97 | public void setId(int id) { 98 | this.id = id; 99 | } 100 | 101 | public String getEmail() { 102 | return email; 103 | } 104 | 105 | public void setEmail(String email) { 106 | this.email = email; 107 | } 108 | 109 | public String getPassword() { 110 | return password; 111 | } 112 | 113 | public void setPassword(String password) { 114 | this.password = password; 115 | } 116 | 117 | public String getAvatar() { 118 | return avatar; 119 | } 120 | 121 | public void setAvatar(String avatar) { 122 | this.avatar = avatar; 123 | } 124 | 125 | public String getName() { 126 | return name; 127 | } 128 | 129 | public void setName(String name) { 130 | this.name = name; 131 | } 132 | 133 | public String getGender() { 134 | return gender; 135 | } 136 | 137 | public void setGender(String gender) { 138 | this.gender = gender; 139 | } 140 | 141 | public int getYearOfBirth() { 142 | return yearOfBirth; 143 | } 144 | 145 | public void setYearOfBirth(int yearOfBirth) { 146 | this.yearOfBirth = yearOfBirth; 147 | } 148 | 149 | public int getScore() { 150 | return score; 151 | } 152 | 153 | public void setScore(int score) { 154 | this.score = score; 155 | } 156 | 157 | public int getMatchCount() { 158 | return matchCount; 159 | } 160 | 161 | public void setMatchCount(int matchCount) { 162 | this.matchCount = matchCount; 163 | } 164 | 165 | public int getWinCount() { 166 | return winCount; 167 | } 168 | 169 | public void setWinCount(int winCount) { 170 | this.winCount = winCount; 171 | } 172 | 173 | public int getLoseCount() { 174 | return loseCount; 175 | } 176 | 177 | public void setLoseCount(int loseCount) { 178 | this.loseCount = loseCount; 179 | } 180 | 181 | public int getCurrentStreak() { 182 | return currentStreak; 183 | } 184 | 185 | public void setCurrentStreak(int currentStreak) { 186 | this.currentStreak = currentStreak; 187 | } 188 | 189 | public boolean isBlocked() { 190 | return blocked; 191 | } 192 | 193 | public void setBlocked(boolean blocked) { 194 | this.blocked = blocked; 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /src/Server/DB/carodb.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 127.0.0.1 3 | -- Server version: 10.5.5-MariaDB - mariadb.org binary distribution 4 | -- Server OS: Win64 5 | -- HeidiSQL Version: 11.0.0.5919 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8 */; 10 | /*!50503 SET NAMES utf8mb4 */; 11 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 12 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 13 | 14 | 15 | -- Dumping database structure for carodb 16 | CREATE DATABASE IF NOT EXISTS `carodb` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */; 17 | USE `carodb`; 18 | 19 | -- Dumping structure for table carodb.gamematch 20 | CREATE TABLE IF NOT EXISTS `gamematch` ( 21 | `ID` int(11) NOT NULL AUTO_INCREMENT, 22 | `PlayerID1` int(11) NOT NULL, 23 | `PlayerID2` int(11) NOT NULL, 24 | `WinnerID` int(11) DEFAULT NULL, 25 | `PlayTime` int(11) NOT NULL, 26 | `TotalMove` int(11) NOT NULL, 27 | `StartedTime` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 28 | `Chat` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 29 | PRIMARY KEY (`ID`) 30 | ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 31 | 32 | -- Dumping data for table carodb.gamematch: ~6 rows (approximately) 33 | /*!40000 ALTER TABLE `gamematch` DISABLE KEYS */; 34 | REPLACE INTO `gamematch` (`ID`, `PlayerID1`, `PlayerID2`, `WinnerID`, `PlayTime`, `TotalMove`, `StartedTime`, `Chat`) VALUES 35 | (1, 1, 2, 1, 10, 15, '2020-11-23T17:22:06.081', NULL), 36 | (2, 2, 3, 2, 20, 25, '2020-11-23T17:22:06.081', NULL), 37 | (3, 3, 4, 4, 30, 35, '2020-11-23T17:22:06.081', NULL), 38 | (4, 1, 4, 4, 40, 45, '2020-11-23T17:22:06.081', NULL), 39 | (5, 3, 2, 3, 50, 55, '2020-11-23T17:22:06.081', NULL), 40 | (6, 4, 5, 5, 90, 50, '2020-11-23T17:22:06.081', NULL); 41 | /*!40000 ALTER TABLE `gamematch` ENABLE KEYS */; 42 | 43 | -- Dumping structure for table carodb.player 44 | CREATE TABLE IF NOT EXISTS `player` ( 45 | `ID` int(11) NOT NULL AUTO_INCREMENT, 46 | `Email` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 47 | `Password` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 48 | `Avatar` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 49 | `Name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, 50 | `Gender` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Nam', 51 | `YearOfBirth` int(4) NOT NULL DEFAULT 2000, 52 | `Score` int(11) NOT NULL DEFAULT 0, 53 | `MatchCount` int(11) NOT NULL DEFAULT 0, 54 | `WinCount` int(11) NOT NULL DEFAULT 0, 55 | `LoseCount` int(11) NOT NULL DEFAULT 0, 56 | `CurrentStreak` int(11) NOT NULL DEFAULT 0, 57 | `Rank` int(11) NOT NULL DEFAULT -1, 58 | `Blocked` tinyint(1) NOT NULL DEFAULT 0, 59 | PRIMARY KEY (`ID`), 60 | UNIQUE KEY `UNIQUE` (`Email`) USING BTREE 61 | ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 62 | 63 | -- Dumping data for table carodb.player: ~10 rows (approximately) 64 | /*!40000 ALTER TABLE `player` DISABLE KEYS */; 65 | REPLACE INTO `player` (`ID`, `Email`, `Password`, `Avatar`, `Name`, `Gender`, `YearOfBirth`, `Score`, `MatchCount`, `WinCount`, `LoseCount`, `CurrentStreak`, `Rank`, `Blocked`) VALUES 66 | (1, '99.hoangtran@gmail.com', 'df10ef8509dc176d733d59549e7dbfaf', 'icons8_alien_96px.png', 'hoang tran', 'nam', 1999, 0, 2, 1, 1, 0, 0, 0), 67 | (2, 'hientran@gmail.com', 'df10ef8509dc176d733d59549e7dbfaf', 'icons8_angry_face_meme_96px.png', 'thu hien', 'nữ', 1988, 0, 3, 1, 2, 0, 0, 0), 68 | (3, 'nguyenthienhuu@gmail.com', 'df10ef8509dc176d733d59549e7dbfaf', 'icons8_angry_face_meme_96px.png', 'huu', 'nữ', 1999, 0, 2, 2, 0, 0, 0, 0), 69 | (4, 'dinhkhoa@gmail.com', 'df10ef8509dc176d733d59549e7dbfaf', 'icons8_angry_face_meme_96px.png', 'khoa', 'nữ', 1987, 0, 3, 0, 3, 0, 0, 1), 70 | (5, 'admin@manager.com', 'df10ef8509dc176d733d59549e7dbfaf', 'icons8_circled_user_male_skin_type_7_96px.png', 'admin', 'Nam', 1999, 0, 1, 1, 0, 0, 0, 0), 71 | (6, 'anh@gmail.com', 'e10adc3949ba59abbe56e057f20f883e', 'icons8_circled_user_male_skin_type_7_96px.png', 'anhanh', 'Nam', 1987, 0, 0, 0, 0, 0, -1, 0), 72 | (7, 'anhhai@gmail.com', 'e10adc3949ba59abbe56e057f20f883e', 'icons8_circled_user_male_skin_type_7_96px.png', 'heo', 'Nam', 1987, 0, 0, 0, 0, 0, -1, 0), 73 | (8, 'ecec@gmail.com', 'e10adc3949ba59abbe56e057f20f883e', 'icons8_circled_user_male_skin_type_7_96px.png', 'heo', 'Nam', 1997, 0, 0, 0, 0, 0, -1, 0), 74 | (9, 'superman@yahoo.com', 'e10adc3949ba59abbe56e057f20f883e', 'icons8_circled_user_male_skin_type_7_96px.png', 'man', 'Nam', 2000, 0, 0, 0, 0, 0, -1, 0), 75 | (10, 'yes@gmail.com', 'e10adc3949ba59abbe56e057f20f883e', 'icons8_circled_user_male_skin_type_7_96px.png', 'nonono', 'Nam', 1987, 0, 0, 0, 0, 0, -1, 0); 76 | /*!40000 ALTER TABLE `player` ENABLE KEYS */; 77 | 78 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 79 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 80 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 81 | -------------------------------------------------------------------------------- /src/Server/RunServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server; 7 | 8 | import server.controller.Admin; 9 | import server.controller.Client; 10 | import server.controller.ClientManager; 11 | import server.controller.RoomManager; 12 | import java.io.IOException; 13 | import java.net.ServerSocket; 14 | import java.net.Socket; 15 | import java.util.concurrent.ArrayBlockingQueue; 16 | import java.util.concurrent.ThreadPoolExecutor; 17 | import java.util.concurrent.TimeUnit; 18 | import java.util.logging.Level; 19 | import java.util.logging.Logger; 20 | import shared.security.RSA; 21 | 22 | /** 23 | * 24 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 25 | */ 26 | public class RunServer { 27 | 28 | public static volatile ClientManager clientManager; 29 | public static volatile RoomManager roomManager; 30 | public static volatile RSA serverSide; 31 | public static boolean isShutDown = false; 32 | public static ServerSocket ss; 33 | 34 | public RunServer() { 35 | 36 | try { 37 | int port = 5056; 38 | 39 | ss = new ServerSocket(port); 40 | System.out.println("Created Server at port " + port + "."); 41 | 42 | // init rsa key 43 | serverSide = new RSA() 44 | .preparePrivateKey("src/Server/rsa_keypair/privateKey"); 45 | 46 | // init managers 47 | clientManager = new ClientManager(); 48 | roomManager = new RoomManager(); 49 | 50 | // create threadpool 51 | ThreadPoolExecutor executor = new ThreadPoolExecutor( 52 | 10, // corePoolSize 53 | 100, // maximumPoolSize 54 | 10, // thread timeout 55 | TimeUnit.SECONDS, 56 | new ArrayBlockingQueue<>(8) // queueCapacity 57 | ); 58 | 59 | // admin 60 | executor.execute(new Admin()); 61 | 62 | // server main loop - listen to client's connection 63 | while (!isShutDown) { 64 | try { 65 | // socket object to receive incoming client requests 66 | Socket s = ss.accept(); 67 | // System.out.println("+ New Client connected: " + s); 68 | 69 | // create new client runnable object 70 | Client c = new Client(s); 71 | clientManager.add(c); 72 | 73 | // execute client runnable 74 | executor.execute(c); 75 | 76 | } catch (IOException ex) { 77 | // Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 78 | isShutDown = true; 79 | } 80 | } 81 | 82 | System.out.println("shutingdown executor..."); 83 | executor.shutdownNow(); 84 | 85 | } catch (IOException ex) { 86 | Logger.getLogger(RunServer.class.getName()).log(Level.SEVERE, null, ex); 87 | } 88 | } 89 | 90 | public static void main(String[] args) { 91 | new RunServer(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Server/controller/Admin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.controller; 7 | 8 | import java.io.IOException; 9 | import server.RunServer; 10 | import java.util.Scanner; 11 | import java.util.logging.Level; 12 | import java.util.logging.Logger; 13 | import server.db.layers.BUS.GameMatchBUS; 14 | import server.db.layers.BUS.PlayerBUS; 15 | import server.db.layers.DTO.GameMatch; 16 | import server.db.layers.DTO.Player; 17 | 18 | /** 19 | * 20 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 21 | */ 22 | public class Admin implements Runnable { 23 | 24 | GameMatchBUS gameMatchBus; 25 | PlayerBUS playerBus; 26 | 27 | @Override 28 | public void run() { 29 | Scanner s = new Scanner(System.in); 30 | String inp; 31 | 32 | while (!RunServer.isShutDown) { 33 | System.out.print("AdminCommand> "); 34 | inp = s.nextLine(); 35 | try { 36 | if (inp.equalsIgnoreCase("user-count")) { 37 | System.out.println("> " + RunServer.clientManager.getSize()); 38 | } else if (inp.equalsIgnoreCase("best-user")) { 39 | showBestPlayerInfo(getBestUser()); 40 | } else if (inp.equalsIgnoreCase("shortest-match")) { 41 | showShortestMatch(getShortestMatch()); 42 | } else if (inp.indexOf("block") == 0) { 43 | System.out.println(blockUser(inp.split(" ")[1])); 44 | } else if (inp.indexOf("log") == 0) { 45 | showGameMatchDetails(inp.split(" ")[1]); 46 | } else if (inp.equalsIgnoreCase("room-count")) { 47 | System.out.println("> " + RunServer.roomManager.getSize()); 48 | } else if (inp.equalsIgnoreCase("shutdown")) { 49 | System.out.println("shuting down..."); 50 | RunServer.isShutDown = true; 51 | 52 | try { 53 | RunServer.ss.close(); 54 | } catch (IOException ex) { 55 | Logger.getLogger(Admin.class.getName()).log(Level.SEVERE, null, ex); 56 | } 57 | } 58 | }catch(ArrayIndexOutOfBoundsException e){ 59 | System.out.println("Thiếu tham số !!!"); 60 | } 61 | 62 | if (inp.equalsIgnoreCase("help")) { 63 | System.out.println("===[List commands]======================\n" 64 | + "======= Thiết yếu =======\n" 65 | + "user-count: số người đang online\n" 66 | + "best-user: thông tin user thắng nhiều nhất\n" 67 | + "shortest-match: thông tin trận đấu có thời gian ngắn nhất\n" 68 | + "block : block user có email là \n" 69 | + "log : xem thông tin trận đấu có mã là \n" 70 | + "======= Thêm =======\n" 71 | + "room-count: số phòng đang mở\n" 72 | + "shutdown: tắt server\n" 73 | + "======================================="); 74 | } 75 | } 76 | } 77 | 78 | // Get player with the most win count 79 | private Player getBestUser() { 80 | Player bestPlayer = null; 81 | playerBus = new PlayerBUS(); 82 | int max = 0; 83 | for (Player p : playerBus.getList()) { 84 | if (p.getWinCount() > max) { 85 | max = p.getWinCount(); 86 | bestPlayer = new Player(p); 87 | } 88 | } 89 | return bestPlayer; 90 | } 91 | 92 | private void showBestPlayerInfo(Player p) { 93 | System.out.println("Player with the most win count: " 94 | + p.getName() + " - " + p.getEmail()); 95 | System.out.println("Win count: " + p.getWinCount()); 96 | } 97 | 98 | // Get the match with the shortest play time 99 | public GameMatch getShortestMatch() { 100 | gameMatchBus = new GameMatchBUS(); 101 | GameMatch shortestMatch = null; 102 | int min = gameMatchBus.getList().get(0).getTotalMove(); 103 | for (GameMatch m : gameMatchBus.getList()) { 104 | if (m.getPlayTime() < min) { 105 | min = m.getPlayTime(); 106 | shortestMatch = new GameMatch(m); 107 | } 108 | } 109 | return shortestMatch; 110 | } 111 | 112 | private void showShortestMatch(GameMatch m) { 113 | playerBus = new PlayerBUS(); 114 | Player p1 = new Player(playerBus.getById(m.getPlayerID1())); 115 | Player p2 = new Player(playerBus.getById(m.getPlayerID2())); 116 | System.out.println("The match with shortest play time: "); 117 | System.out.println("Player 1: " + p1.getName()); 118 | System.out.println("Player 1: " + p2.getName()); 119 | System.out.println("Play time: " + m.getPlayTime() + " second"); 120 | } 121 | 122 | // Block user with provided email 123 | private String blockUser(String email) { 124 | playerBus = new PlayerBUS(); 125 | for (Player p : playerBus.getList()) { 126 | if (p.getEmail().equalsIgnoreCase(email)) { 127 | p.setBlocked(true); 128 | return playerBus.update(p) ? "Success" : "Fail"; 129 | } 130 | } 131 | return "Cant find user with provided email!"; 132 | } 133 | 134 | // Get Game match with provide id 135 | private void showGameMatchDetails(String id) { 136 | gameMatchBus = new GameMatchBUS(); 137 | playerBus = new PlayerBUS(); 138 | GameMatch m = gameMatchBus.getById(Integer.parseInt(id)); 139 | System.out.println("Match id: " + m.getId()); 140 | System.out.println(" + Player 1: " + playerBus.getById(m.getPlayerID1()).getName()); 141 | System.out.println(" + Player 2: " + playerBus.getById(m.getPlayerID2()).getName()); 142 | System.out.println(" + Winner: " + playerBus.getById(m.getWinnerID()).getName()); 143 | System.out.println(" + Play time in second: " + m.getPlayTime()); 144 | System.out.println(" + Total move: " + m.getTotalMove()); 145 | } 146 | 147 | public static void main(String[] args) { 148 | Admin ad = new Admin(); 149 | ad.run(); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Server/controller/ClientManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.controller; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * 12 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 13 | */ 14 | public class ClientManager { 15 | 16 | ArrayList clients; 17 | 18 | public ClientManager() { 19 | clients = new ArrayList<>(); 20 | } 21 | 22 | public boolean add(Client c) { 23 | if (!clients.contains(c)) { 24 | clients.add(c); 25 | return true; 26 | } 27 | return true; 28 | } 29 | 30 | public boolean remove(Client c) { 31 | if (clients.contains(c)) { 32 | clients.remove(c); 33 | return true; 34 | } 35 | return false; 36 | } 37 | 38 | public Client find(String email) { 39 | for (Client c : clients) { 40 | if (c.getLoginPlayer() != null && c.getLoginPlayer().getEmail().equals(email)) { 41 | return c; 42 | } 43 | } 44 | return null; 45 | } 46 | 47 | public void broadcast(String msg) { 48 | clients.forEach((c) -> { 49 | c.sendData(msg); 50 | }); 51 | } 52 | 53 | public Client findClientFindingMatch() { 54 | for (Client c : clients) { 55 | if (c.isFindingMatch()) { 56 | return c; 57 | } 58 | } 59 | 60 | return null; 61 | } 62 | 63 | public int getSize() { 64 | return clients.size(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Server/controller/Room.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.controller; 7 | 8 | import java.time.LocalDate; 9 | import java.time.LocalDateTime; 10 | import server.game.caro.Caro; 11 | import server.game.GameLogic; 12 | import java.util.ArrayList; 13 | import java.util.concurrent.Callable; 14 | import server.RunServer; 15 | import server.db.layers.BUS.GameMatchBUS; 16 | import server.db.layers.DTO.GameMatch; 17 | import server.game.caro.History; 18 | import shared.constant.StreamData; 19 | 20 | /** 21 | * 22 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 23 | */ 24 | public class Room { 25 | 26 | String id; 27 | Caro gamelogic; 28 | Client client1 = null, client2 = null; 29 | ArrayList clients = new ArrayList<>(); 30 | boolean gameStarted = false; 31 | 32 | public LocalDateTime startedTime; 33 | 34 | public Room(String id) { 35 | // room id 36 | this.id = id; 37 | 38 | // create game logic 39 | gamelogic = new Caro(); 40 | } 41 | 42 | public boolean isGameStarted() { 43 | return gameStarted; 44 | } 45 | 46 | public void startGame() { 47 | startedTime = LocalDateTime.now(); 48 | gameStarted = true; 49 | gamelogic.getTurnTimer() 50 | .setTimerCallBack( 51 | // end turn callback 52 | (Callable) () -> { 53 | // TURN_TIMER_END; 54 | broadcast( 55 | StreamData.Type.GAME_EVENT + ";" 56 | + StreamData.Type.TURN_TIMER_END.name() + ";" 57 | + gamelogic.getLastMoveEmail() 58 | ); 59 | return null; 60 | }, 61 | // tick turn callback 62 | (Callable) () -> { 63 | broadcast( 64 | StreamData.Type.GAME_EVENT + ";" 65 | + StreamData.Type.TURN_TICK.name() + ";" 66 | + gamelogic.getTurnTimer().getCurrentTick() 67 | ); 68 | return null; 69 | }, 70 | // tick interval 71 | Caro.TURN_TIME_LIMIT / 10 72 | ); 73 | 74 | gamelogic.getMatchTimer() 75 | .setTimerCallBack( 76 | // end match callback 77 | (Callable) () -> { 78 | 79 | // tinh diem hoa 80 | new GameMatchBUS().add(new GameMatch( 81 | client1.getLoginPlayer().getId(), 82 | client1.getLoginPlayer().getId(), 83 | -1, 84 | gamelogic.getMatchTimer().getCurrentTick(), 85 | gamelogic.getHistory().size(), 86 | startedTime 87 | )); 88 | 89 | broadcast( 90 | StreamData.Type.GAME_EVENT + ";" 91 | + StreamData.Type.MATCH_TIMER_END.name() 92 | ); 93 | return null; 94 | }, 95 | // tick match callback 96 | (Callable) () -> { 97 | broadcast( 98 | StreamData.Type.GAME_EVENT + ";" 99 | + StreamData.Type.MATCH_TICK.name() + ";" 100 | + gamelogic.getMatchTimer().getCurrentTick() 101 | ); 102 | return null; 103 | }, 104 | // tick interval 105 | Caro.MATCH_TIME_LIMIT / 10 106 | ); 107 | } 108 | 109 | // add/remove client 110 | public boolean addClient(Client c, boolean isWatcher) { 111 | if (!clients.contains(c)) { 112 | clients.add(c); 113 | 114 | if (!isWatcher) { 115 | if (client1 == null) { 116 | client1 = c; 117 | } else if (client2 == null) { 118 | client2 = c; 119 | } 120 | } 121 | 122 | return true; 123 | } 124 | return false; 125 | } 126 | 127 | public boolean removeClient(Client c) { 128 | if (clients.contains(c)) { 129 | clients.remove(c); 130 | return true; 131 | } 132 | return false; 133 | } 134 | 135 | // broadcast messages 136 | public void broadcast(String msg) { 137 | clients.forEach((c) -> { 138 | c.sendData(msg); 139 | }); 140 | } 141 | 142 | public void close(String reason) { 143 | // notify all client in room 144 | broadcast(StreamData.Type.CLOSE_ROOM.name() + ";" + reason); 145 | 146 | // remove reference 147 | clients.forEach((client) -> { 148 | client.setJoinedRoom(null); 149 | }); 150 | 151 | // remove all clients 152 | clients.clear(); 153 | 154 | // remove room 155 | RunServer.roomManager.remove(this); 156 | } 157 | 158 | // get room data 159 | public String getFullData() { 160 | String data = ""; 161 | 162 | // player data 163 | data += getClient12InGameData() + ";"; 164 | data += getListClientData() + ";"; 165 | // timer 166 | data += getTimerData() + ";"; 167 | // board 168 | data += getBoardData(); 169 | 170 | return data; 171 | } 172 | 173 | public String getTimerData() { 174 | String data = ""; 175 | 176 | data += Caro.MATCH_TIME_LIMIT + ";" + gamelogic.getMatchTimer().getCurrentTick() + ";"; 177 | data += Caro.TURN_TIME_LIMIT + ";" + gamelogic.getTurnTimer().getCurrentTick(); 178 | 179 | return data; 180 | } 181 | 182 | public String getBoardData() { 183 | ArrayList history = gamelogic.getHistory(); 184 | 185 | String data = history.size() + ";"; 186 | for (History his : history) { 187 | data += his.getRow() + ";" + his.getColumn() + ";" + his.getPlayerEmail() + ";"; 188 | } 189 | 190 | return data.substring(0, data.length() - 1); // bỏ dấu ; ở cuối 191 | } 192 | 193 | public String getClient12InGameData() { 194 | String data = ""; 195 | 196 | data += (client1 == null ? Client.getEmptyInGameData() : client1.getInGameData() + ";"); 197 | data += (client2 == null ? Client.getEmptyInGameData() : client2.getInGameData()); 198 | 199 | return data; 200 | } 201 | 202 | public String getListClientData() { 203 | // kết quả trả về có dạng playerCount;player1_data;player2_data;...;playerN_data 204 | 205 | String data = clients.size() + ";"; 206 | 207 | for (Client c : clients) { 208 | data += c.getInGameData() + ";"; 209 | } 210 | 211 | return data.substring(0, data.length() - 1); // bỏ dấu ; ở cuối 212 | } 213 | 214 | // gets sets 215 | public String getId() { 216 | return id; 217 | } 218 | 219 | public void setId(String id) { 220 | this.id = id; 221 | } 222 | 223 | public GameLogic getGamelogic() { 224 | return gamelogic; 225 | } 226 | 227 | public void setGamelogic(Caro gamelogic) { 228 | this.gamelogic = gamelogic; 229 | } 230 | 231 | public Client getClient1() { 232 | return client1; 233 | } 234 | 235 | public void setClient1(Client client1) { 236 | this.client1 = client1; 237 | } 238 | 239 | public Client getClient2() { 240 | return client2; 241 | } 242 | 243 | public void setClient2(Client client2) { 244 | this.client2 = client2; 245 | } 246 | 247 | public ArrayList getClients() { 248 | return clients; 249 | } 250 | 251 | public void setClients(ArrayList clients) { 252 | this.clients = clients; 253 | } 254 | 255 | } 256 | -------------------------------------------------------------------------------- /src/Server/controller/RoomManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.controller; 7 | 8 | import java.util.ArrayList; 9 | import shared.helper.RandomString; 10 | 11 | /** 12 | * 13 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 14 | */ 15 | public class RoomManager { 16 | 17 | ArrayList rooms; 18 | RandomString idGenerator; 19 | 20 | public RoomManager() { 21 | rooms = new ArrayList<>(); 22 | idGenerator = new RandomString(5); 23 | } 24 | 25 | public Room createRoom() { 26 | Room room = new Room(idGenerator.nextString()); 27 | rooms.add(room); 28 | 29 | return room; 30 | } 31 | 32 | public boolean add(Room r) { 33 | if (!rooms.contains(r)) { 34 | rooms.add(r); 35 | return true; 36 | } 37 | return true; 38 | } 39 | 40 | public boolean remove(Room r) { 41 | if (rooms.contains(r)) { 42 | rooms.remove(r); 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | public Room find(String id) { 49 | for (Room r : rooms) { 50 | if (r.getId().equals(id)) { 51 | return r; 52 | } 53 | } 54 | return null; 55 | } 56 | 57 | public int getSize() { 58 | return rooms.size(); 59 | } 60 | 61 | public ArrayList getRooms() { 62 | return rooms; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Server/game/GameLogic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.game; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class GameLogic { 13 | 14 | public GameLogic() { 15 | } 16 | 17 | public String receiveDataFromClient(String received) { 18 | return ""; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/Server/game/caro/Caro.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.game.caro; 7 | 8 | import shared.helper.CountDownTimer; 9 | import java.util.ArrayList; 10 | import shared.helper.Line; 11 | import shared.helper.Point; 12 | import server.game.GameLogic; 13 | 14 | /** 15 | * 16 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 17 | */ 18 | public class Caro extends GameLogic { 19 | 20 | public static final int ROW = 16, COL = 16; 21 | public static final int TURN_TIME_LIMIT = 30, MATCH_TIME_LIMIT = 10 * 60; 22 | 23 | ArrayList history; 24 | History preMove; 25 | String[][] board; 26 | 27 | CountDownTimer turnTimer; 28 | CountDownTimer matchTimer; 29 | 30 | public Caro() { 31 | init(); 32 | } 33 | 34 | public void init() { 35 | turnTimer = new CountDownTimer(TURN_TIME_LIMIT); 36 | matchTimer = new CountDownTimer(MATCH_TIME_LIMIT); 37 | 38 | board = new String[ROW][COL]; 39 | history = new ArrayList<>(); 40 | preMove = null; 41 | 42 | // init board 43 | for (int i = 0; i < ROW; i++) { 44 | for (int j = 0; j < COL; j++) { 45 | board[i][j] = " "; 46 | } 47 | } 48 | } 49 | 50 | public void restartTurnTimer() { 51 | turnTimer.restart(); 52 | } 53 | 54 | public void resumeTimer() { 55 | turnTimer.resume(); 56 | matchTimer.resume(); 57 | } 58 | 59 | public void pauseTimer() { 60 | turnTimer.pause(); 61 | matchTimer.pause(); 62 | } 63 | 64 | public void cancelTimer() { 65 | if (turnTimer != null) { 66 | turnTimer.cancel(); 67 | } 68 | 69 | if (matchTimer != null) { 70 | matchTimer.cancel(); 71 | } 72 | } 73 | 74 | public void addHistory(int row, int col, String playerEmail) { 75 | History newHis = new History(row, col, playerEmail); 76 | history.add(newHis); 77 | preMove = newHis; 78 | } 79 | 80 | public ArrayList getHistory() { 81 | return history; 82 | } 83 | 84 | public boolean move(int row, int col, String playerEmail) { 85 | // nếu người này đã đánh trước đó thì không cho đánh nữa 86 | if (preMove != null && preMove.getPlayerEmail().equals(playerEmail)) { 87 | return false; 88 | } 89 | 90 | // nếu vị trí đánh nằm ngoài board 91 | if (row < 0 && row >= ROW && col < 0 && col >= COL) { 92 | return false; 93 | } 94 | 95 | // nếu vị trí đó đã đánh rồi 96 | if (!board[row][col].equals(" ")) { 97 | return false; 98 | } 99 | 100 | board[row][col] = playerEmail; 101 | addHistory(row, col, playerEmail); 102 | return true; 103 | } 104 | 105 | public String getValueAt(int x, int y) { 106 | if (x >= 0 && x < COL && y >= 0 && y < ROW) { 107 | return board[y][x]; 108 | } 109 | 110 | return " "; 111 | } 112 | 113 | public Line CheckWin(int row, int column) { 114 | Point currentCell = new Point(column, row); 115 | Point backDir, frontDir; 116 | Line winPath; 117 | 118 | // ============ check chieu ngang ============= 119 | backDir = new Point(-1, 0); 120 | frontDir = new Point(1, 0); 121 | winPath = this.checkWinTemplate(currentCell, backDir, frontDir); 122 | if (winPath != null) { 123 | return winPath; 124 | } 125 | // ============ check chieu doc ============ 126 | backDir = new Point(0, -1); 127 | frontDir = new Point(0, 1); 128 | winPath = this.checkWinTemplate(currentCell, backDir, frontDir); 129 | if (winPath != null) { 130 | return winPath; 131 | } 132 | // ============ check cheo trai sang phai ============ 133 | backDir = new Point(-1, -1); 134 | frontDir = new Point(1, 1); 135 | winPath = this.checkWinTemplate(currentCell, backDir, frontDir); 136 | if (winPath != null) { 137 | return winPath; 138 | } 139 | // ============ check cheo phai sang trai ============ 140 | backDir = new Point(1, -1); 141 | frontDir = new Point(-1, 1); 142 | winPath = this.checkWinTemplate(currentCell, backDir, frontDir); 143 | if (winPath != null) { 144 | return winPath; 145 | } 146 | 147 | return null; 148 | } 149 | 150 | public Line checkWinTemplate(Point currentCell, Point backDir, Point frontDir) { 151 | // get data from current cell 152 | String currentData = this.getValueAt(currentCell.x, currentCell.y); 153 | 154 | // if there is nodata => out 155 | if (currentData.equals(" ")) { 156 | return null; 157 | } 158 | 159 | // đếm số lượng ô thỏa điều kiện (>= 5 ô liên tiếp là win) 160 | int count = 1; 161 | Point from, to, temp; 162 | 163 | // count to back 164 | from = currentCell; 165 | while (true) { 166 | temp = new Point(from.x + backDir.x, from.y + backDir.y); 167 | String data = this.getValueAt(temp.x, temp.y); 168 | 169 | if (!data.equals(currentData)) { 170 | break; 171 | } 172 | from = temp; 173 | count++; 174 | } 175 | 176 | // count to front 177 | to = currentCell; 178 | while (true) { 179 | temp = new Point(to.x + frontDir.x, to.y + frontDir.y); 180 | String data = this.getValueAt(temp.x, temp.y); 181 | 182 | if (!data.equals(currentData)) { 183 | break; 184 | } 185 | to = temp; 186 | count++; 187 | } 188 | 189 | // nếu có 5 ô giống nhau liên tiếp nhau => win 190 | if (count == 5) { 191 | return new Line(from.x, from.y, to.x, to.y); 192 | } 193 | 194 | return null; 195 | } 196 | 197 | public CountDownTimer getTurnTimer() { 198 | return turnTimer; 199 | } 200 | 201 | public CountDownTimer getMatchTimer() { 202 | return matchTimer; 203 | } 204 | 205 | public String getLastMoveEmail() { 206 | return history.get(history.size() - 1).getPlayerEmail(); 207 | } 208 | 209 | public int getProgressTurnTimeValue() { 210 | return 100 * turnTimer.getCurrentTick() / TURN_TIME_LIMIT; 211 | } 212 | 213 | public int getProgressMatchTimeValue() { 214 | return 100 * matchTimer.getCurrentTick() / MATCH_TIME_LIMIT; 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/Server/game/caro/History.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.game.caro; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class History { 13 | 14 | int row; 15 | int column; 16 | String playerEmail; 17 | 18 | public History(int row, int column, String playerEmail) { 19 | this.row = row; 20 | this.column = column; 21 | this.playerEmail = playerEmail; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return row + ";" + column + ";" + playerEmail; 27 | } 28 | 29 | public int getRow() { 30 | return row; 31 | } 32 | 33 | public void setRow(int row) { 34 | this.row = row; 35 | } 36 | 37 | public int getColumn() { 38 | return column; 39 | } 40 | 41 | public void setColumn(int column) { 42 | this.column = column; 43 | } 44 | 45 | public String getPlayerEmail() { 46 | return playerEmail; 47 | } 48 | 49 | public void setPlayerEmail(String playerId) { 50 | this.playerEmail = playerId; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Server/game/caro/TestTimerCaro.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.game.caro; 7 | 8 | import java.util.concurrent.Callable; 9 | 10 | /** 11 | * 12 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 13 | */ 14 | public class TestTimerCaro { 15 | 16 | public TestTimerCaro() { 17 | Caro caro = new Caro(); 18 | Callable endCallback, tickCallback; 19 | 20 | endCallback = (Callable) () -> { 21 | System.out.println("END"); 22 | throw new Exception(); 23 | }; 24 | 25 | tickCallback = (Callable) () -> { 26 | if (caro.getTurnTimer().getCurrentTick() == 10) { 27 | caro.cancelTimer(); 28 | } 29 | System.out.println(caro.getTurnTimer().getCurrentTick()); 30 | throw new Exception(); 31 | }; 32 | 33 | caro.getTurnTimer().setTimerCallBack(endCallback, tickCallback, 1); 34 | 35 | // thằng caro làm việc shutdown chương trình trở nên khó khăn... 36 | // chưa biết cách tắt thread do thằng caro callable tạo ra 37 | } 38 | 39 | public static void main(String[] args) { 40 | new TestTimerCaro(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Server/game/cotuong/CoTuong.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package server.game.cotuong; 7 | 8 | import server.game.GameLogic; 9 | 10 | /** 11 | * 12 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 13 | */ 14 | public class CoTuong extends GameLogic { 15 | 16 | public CoTuong() { 17 | System.out.println("Co Tuong constructor"); 18 | } 19 | 20 | @Override 21 | public String receiveDataFromClient(String received) { 22 | System.out.println("Game CoTuong received: " + received); 23 | return ""; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Server/rsa_keypair/privateKey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Server/rsa_keypair/privateKey -------------------------------------------------------------------------------- /src/Server/rsa_keypair/publicKey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoangTran0410/CaroOnline_SocketJava/91936052647358d40ccb5b1a34e5f1ca60d695ce/src/Server/rsa_keypair/publicKey -------------------------------------------------------------------------------- /src/Shared/constant/Avatar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.constant; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class Avatar { 13 | 14 | public static final String ASSET_PATH = "src/client/view/asset/"; 15 | public static final String PATH = "src/client/view/asset/avatar/"; 16 | public static final String PATH_RESOURCE = "/client/view/asset/avatar/"; 17 | public static final String EMPTY_AVATAR = "icons8_confusion_96px.png"; 18 | 19 | // https://www.dropboxforum.com/t5/Dropbox-files-folders/How-to-Copy-file-Names-within-a-Folder-Create-a-table-of/td-p/253141 20 | public static final String[] LIST = { 21 | "icons8_circled_user_male_skin_type_7_96px.png", 22 | "icons8_circled_user_female_skin_type_7_96px.png", 23 | "icons8_alien_96px.png", 24 | "icons8_angry_face_meme_96px.png", 25 | "icons8_animation_96px.png", 26 | "icons8_avatar_96px.png", 27 | "icons8_bad_piggies_96px.png", 28 | "icons8_bendy_96px.png", 29 | "icons8_captain_america_96px.png", 30 | "icons8_crash_bandicoot_96px.png", 31 | "icons8_deadpool_96px.png", 32 | "icons8_elektrovieh_96px.png", 33 | "icons8_gandalf_96px.png", 34 | "icons8_ghost_96px.png", 35 | "icons8_groot_96px.png", 36 | "icons8_hinata_96px.png", 37 | "icons8_hulk_96px.png", 38 | "icons8_ignore_96px.png", 39 | "icons8_iron_man_96px.png", 40 | "icons8_jake_96px.png", 41 | "icons8_jetpack_joyride_96px.png", 42 | "icons8_joker_dc_96px.png", 43 | "icons8_logan_x_men_96px.png", 44 | "icons8_magneto_96px.png", 45 | "icons8_minecraft_main_character_96px.png", 46 | "icons8_minecraft_skeleton_96px.png", 47 | "icons8_minecraft_zombie_96px.png", 48 | "icons8_morpheus_96px.png", 49 | "icons8_naruto_96px.png", 50 | "icons8_neo_96px.png", 51 | "icons8_orc_96px.png", 52 | "icons8_pelican_96px.png", 53 | "icons8_pennywise_96px.png", 54 | "icons8_pikachu_pokemon_96px.png", 55 | "icons8_rick_sanchez_96px.png", 56 | "icons8_sailor_moon_96px.png", 57 | "icons8_sasuke_uchiha_96px.png", 58 | "icons8_sonic_the_hedgehog_96px.png", 59 | "icons8_spider-man_head_96px.png", 60 | "icons8_steven_universe_96px.png", 61 | "icons8_super_mario_96px.png", 62 | "icons8_the_flash_head_96px.png", 63 | "icons8_transformer_96px.png", 64 | "icons8_trinity_96px.png", 65 | "icons8_venom_head_96px.png", 66 | "icons8_vietnam_96px.png", 67 | "icons8_year_of_rooster_96px.png", 68 | "icons8_saitama_96px.png", 69 | "icons8_trollface_96px.png" 70 | }; 71 | 72 | public static String getAvatarFilNameFromPath(String path) { 73 | String[] splitted = path.split("/"); 74 | return splitted[splitted.length - 1]; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Shared/constant/Code.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.constant; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class Code { 13 | 14 | public static String ACCOUNT_NOT_FOUND = "Không tìm thấy tài khoản."; 15 | public static String ACCOUNT_BLOCKED = "Tài khoản đang bị khóa."; 16 | public static String ACCOUNT_LOGEDIN = "Tài khoản đã được đăng nhập ở nơi khác."; 17 | public static String WRONG_PASSWORD = "Mật khẩu không đúng."; 18 | public static String EMAIL_EXISTED = "Email đã tồn tại."; 19 | public static String CANNOT_JOINROOM = "Không thể vào phòng."; 20 | public static String ALREADY_INROOM = "Bạn đang ở trong phòng rồi."; 21 | public static String COMPETITOR_LEAVE = "Đối thủ đã thoát."; 22 | public static String COMPETITOR_CHOOSE_NO = "Đối thủ đã không đồng ý ghép cặp."; 23 | public static String YOU_CHOOSE_NO = "Bạn đã không đồng ý ghép cặp."; 24 | public static String ROOM_NOTFOUND = "Không tìm thấy phòng."; 25 | public static String CANT_LEAVE_ROOM = "Không thể thoát phòng."; 26 | public static String UNKNOW_GAME_EVENT = "Game event không xác định."; 27 | } 28 | -------------------------------------------------------------------------------- /src/Shared/constant/StreamData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.constant; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class StreamData { 13 | 14 | /* Cách đọc hiểu đống bên dưới? 15 | => Đống bên dưới được viết comment theo cấu trúc sau: 16 | 17 | Tên type // mô tả / dữ liệu gửi đi từ client / dữ liệu trả về từ server 18 | */ 19 | public enum Type { 20 | // security 21 | AESKEY, // client gửi aes key cho server / aeskey đã được mã hóa / server không cần phản hồi 22 | 23 | // auth 24 | LOGIN, // chức năng đăng nhập / email, password / success hoặc failed 25 | SIGNUP, // chức năng đăng ký / thông tin đăng ký / success hoặc failed 26 | LOGOUT, // chức năng đăng xuất / không cần dữ liệu thêm / success hoặc failed 27 | 28 | // main menu 29 | LIST_ROOM, // lấy danh sách phòng hiện tại / ko cần dữ liệu thêm / dữ liệu danh sách phòng 30 | LIST_ONLINE, // lấy danh sách người chơi đang online / không cần dữ liệu thêm / dữ liệu danh sách online 31 | CREATE_ROOM, // chức năng tạo phòng / không cần dữ liệu thêm / success hoặc failed 32 | JOIN_ROOM, // chức năng vào phòng, nếu chưa có đủ người thì chơi, đủ rồi thì xem / id phòng / success hoặc failed 33 | WATCH_ROOM, // chức năng vào xem / id phòng / success hoặc failed 34 | 35 | // pair match 36 | FIND_MATCH, // chức năng tìm trận / không cần dữ liệu thêm / success hoặc failed 37 | CANCEL_FIND_MATCH, // chức năng hủy tìm trận / không cần dữ liệu thêm / success hoặc failed 38 | REQUEST_PAIR_MATCH, // chức năng hỏi user có đồng ý ghép cặp không / đồng ý hay không / thông tin user sẽ ghép cặp 39 | RESULT_PAIR_MATCH, // chức năng gửi thông báo đồng ý ghép cặp / _chỉ có server gửi có client loại type này_ / kết quả ghép cặp 40 | 41 | // in game 42 | DATA_ROOM, // dữ liệu phòng khi vừa vào phòng / id phòng / dữ liệu phòng 43 | CHAT_ROOM, // chức năng chat phòng / dữ liệu chat / dữ liệu chat (gửi broadcast trong phòng) 44 | LEAVE_ROOM, // chức năng thoát phòng / không cần dữ liệu thêm / success hoặc failed 45 | CLOSE_ROOM, // chức năng đóng phòng / chỉ có server gửi type này cho client 46 | 47 | // profile 48 | GET_PROFILE, // chức năng xem hồ sơ cá nhân / email user muốn xem thông tin / dữ liệu user 49 | EDIT_PROFILE, // chức năng chỉnh thông tin cá nhân / thông tin cá nhân mới / success hoặc failed 50 | CHANGE_PASSWORD, // chức năng đổi mật khẩu / mật khẩu cũ, mật khẩu mới / success hoặc failed 51 | 52 | // game 53 | GAME_EVENT, // 54 | 55 | // caro game 56 | START, // chức năng bắt đầu game (khi 1 trong 2 người chơi bắt đầu move) / server gửi broadcast tới room 57 | MOVE, // chức năng đánh caro tại 1 ô / vị trí ô / success thì broadcast vị trí ô cho mọi người trong phòng, failed khi vị trí không hợp lệ 58 | UNDO, // chức năng đánh lại / không cần dữ liệu thêm / gửi request broadcast (cho mọi người biết là muốn đánh lại, kể cả viewer) 59 | UNDO_ACCEPT, // chắc năng đồng ý đánh lại / đồng ý hay không / gửi result broadcast (cho mọi người biết người chơi có đồng ý cho đánh lại hay không) 60 | NEW_GAME, // chức năng tạo game mới / không cần dữ liệu thêm / nếu game chưa end thì gửi request accept tới đối thủ 61 | NEW_GAME_ACCEPT, // chức năng đồng ý tạo game mới / đồng ý hay không / gửi result broadcast làm mới trận 62 | SURRENDER, // chức năng đầu hàng / không có dữ liệu thêm / gửi broadcast 63 | WIN, // chỉ có server mới gửi type này cho client 64 | TURN_TICK, 65 | MATCH_TICK, 66 | MATCH_TIMER_END, // hết giờ / server gửi tới client 67 | TURN_TIMER_END, // hết thời gian turn / server gửi tới client 68 | 69 | // specific 70 | UNKNOW_TYPE, // khi client gửi type không xác định 71 | EXIT, // chức năng tắt game / không cần dữ liệu thêm / bradcast thoát game 72 | } 73 | 74 | // https://stackoverflow.com/a/6667365 75 | public static Type getType(String typeName) { 76 | Type result = Type.UNKNOW_TYPE; 77 | 78 | try { 79 | result = Enum.valueOf(StreamData.Type.class, typeName); 80 | } catch (Exception e) { 81 | System.err.println("Unknow type: " + e.getMessage()); 82 | } 83 | 84 | return result; 85 | } 86 | 87 | public static Type getTypeFromData(String data) { 88 | String typeStr = data.split(";")[0]; 89 | return getType(typeStr); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Shared/helper/CountDownTimer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.helper; 7 | 8 | import java.util.Timer; 9 | import java.util.TimerTask; 10 | import java.util.concurrent.Callable; 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | import java.util.logging.Level; 14 | import java.util.logging.Logger; 15 | import server.game.caro.Caro; 16 | 17 | /** 18 | * 19 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 20 | */ 21 | public class CountDownTimer { 22 | 23 | int timeLimit; 24 | int currentTick; 25 | int tickInterval; 26 | Timer timer; 27 | ExecutorService executor; 28 | 29 | boolean isPaused = false; 30 | 31 | public CountDownTimer(int _timeLimit) { 32 | timeLimit = _timeLimit; 33 | currentTick = _timeLimit; 34 | tickInterval = 1; // default is 1 35 | timer = new Timer(); 36 | executor = Executors.newFixedThreadPool(2); 37 | } 38 | 39 | public void pause() { 40 | isPaused = true; 41 | } 42 | 43 | public void resume() { 44 | isPaused = false; 45 | } 46 | 47 | public void restart() { 48 | currentTick = timeLimit; 49 | resume(); 50 | } 51 | 52 | public void cancel() { 53 | timer.cancel(); 54 | timer.purge(); 55 | executor.shutdownNow(); 56 | } 57 | 58 | // https://stackoverflow.com/a/4685606 59 | public void setTimerCallBack(Callable endCallback, Callable tickCallback, int _tickInterval) { 60 | tickInterval = _tickInterval; 61 | 62 | timer.scheduleAtFixedRate(new TimerTask() { 63 | @Override 64 | public void run() { 65 | if (!isPaused) { 66 | currentTick--; 67 | 68 | // sau tickInterval giây, sẽ gọi 1 lần tick-callback 69 | if (tickCallback != null && (timeLimit - currentTick) % tickInterval == 0) { 70 | try { 71 | executor.submit(tickCallback); 72 | } catch (Exception ex) { 73 | Logger.getLogger(Caro.class.getName()).log(Level.SEVERE, null, ex); 74 | } 75 | } 76 | 77 | // khi đếm ngược tới 0 sẽ gọi end-callback 78 | if (currentTick <= 0) { 79 | try { 80 | if (endCallback != null) { 81 | executor.submit(endCallback); 82 | } 83 | executor.shutdown(); 84 | } catch (Exception ex) { 85 | Logger.getLogger(Caro.class.getName()).log(Level.SEVERE, null, ex); 86 | } 87 | timer.cancel(); 88 | timer.purge(); 89 | } 90 | } 91 | } 92 | }, 0, 1000); 93 | } 94 | 95 | public int getCurrentTick() { 96 | return currentTick; 97 | } 98 | 99 | public void setCurrentTick(int currentTick) { 100 | this.currentTick = currentTick; 101 | } 102 | 103 | public int getTimeLimit() { 104 | return timeLimit; 105 | } 106 | 107 | public void setTimeLimit(int timeLimit) { 108 | this.timeLimit = timeLimit; 109 | } 110 | 111 | public int getTickInterval() { 112 | return tickInterval; 113 | } 114 | 115 | public void setTickInterval(int tickInterval) { 116 | this.tickInterval = tickInterval; 117 | } 118 | 119 | public Timer getTimer() { 120 | return timer; 121 | } 122 | 123 | public void setTimer(Timer timer) { 124 | this.timer = timer; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/Shared/helper/CustumDateTimeFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.helper; 7 | 8 | import java.text.SimpleDateFormat; 9 | import java.util.Calendar; 10 | 11 | /** 12 | * 13 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 14 | */ 15 | public class CustumDateTimeFormatter { 16 | 17 | // https://stackoverflow.com/a/6953926 18 | public static String getCurrentTimeFormatted() { 19 | return new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()); 20 | } 21 | 22 | public static String secondsToMinutes(int seconds) { 23 | return addZero(seconds / 60) + ":" + addZero(seconds % 60); 24 | } 25 | 26 | public static String addZero(int n) { 27 | if (n < 10) { 28 | return "0" + n; 29 | } 30 | return "" + n; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Shared/helper/Line.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.helper; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class Line { 13 | 14 | public int x1, x2, y1, y2; 15 | 16 | public Line(int x1, int y1, int x2, int y2) { 17 | this.x1 = x1; 18 | this.y1 = y1; 19 | this.x2 = x2; 20 | this.y2 = y2; 21 | } 22 | 23 | public Line(Point p1, Point p2) { 24 | this.x1 = p1.x; 25 | this.y1 = p1.y; 26 | this.x2 = p2.x; 27 | this.y2 = p2.y; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/helper/MyHash.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.helper; 7 | 8 | import java.math.BigInteger; 9 | import java.nio.charset.StandardCharsets; 10 | import java.security.MessageDigest; 11 | import java.security.NoSuchAlgorithmException; 12 | import java.security.SecureRandom; 13 | import java.security.spec.InvalidKeySpecException; 14 | import java.security.spec.KeySpec; 15 | import java.util.logging.Level; 16 | import java.util.logging.Logger; 17 | import javax.crypto.SecretKeyFactory; 18 | import javax.crypto.spec.PBEKeySpec; 19 | 20 | /** 21 | * 22 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 23 | */ 24 | public class MyHash { 25 | 26 | // https://www.baeldung.com/java-password-hashing#2-implementing-pbkdf2-in-java 27 | // hàm này mỗi lần hash_sha_256 lại ra 1 chuỗi khác nhau, và không hiển thị trong console được, khó hiểu 28 | // => Không dùng 29 | public static String hash_WTF(String str) { 30 | try { 31 | SecureRandom random = new SecureRandom(); 32 | byte[] salt = new byte[16]; 33 | random.nextBytes(salt); 34 | KeySpec spec = new PBEKeySpec(str.toCharArray(), salt, 65536, 128); 35 | SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 36 | 37 | byte[] hash = factory.generateSecret(spec).getEncoded(); 38 | 39 | return new String(hash); 40 | 41 | } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) { 42 | Logger.getLogger(MyHash.class.getName()).log(Level.SEVERE, null, ex); 43 | } 44 | 45 | return ""; 46 | } 47 | 48 | // https://stackoverflow.com/a/5531479 49 | // hàm này dùng sha256 nhưng cũng không hiển thị trong console được 50 | public static String hash_sha_256(String str) { 51 | try { 52 | MessageDigest digest = MessageDigest.getInstance("SHA-256"); 53 | byte[] hash = digest.digest(str.getBytes(StandardCharsets.UTF_8)); 54 | 55 | return new String(hash); 56 | } catch (NoSuchAlgorithmException ex) { 57 | Logger.getLogger(MyHash.class.getName()).log(Level.SEVERE, null, ex); 58 | } 59 | 60 | return ""; 61 | } 62 | 63 | // https://www.geeksforgeeks.org/md5-hash-in-java/ 64 | // hàm này dùng md5 65 | public static String hash(String str) { 66 | try { 67 | // Static getInstance method is called with hashing MD5 68 | MessageDigest md = MessageDigest.getInstance("MD5"); 69 | 70 | // digest() method is called to calculate message digest 71 | // of an input digest() return array of byte 72 | byte[] messageDigest = md.digest(str.getBytes()); 73 | 74 | // Convert byte array into signum representation 75 | BigInteger no = new BigInteger(1, messageDigest); 76 | 77 | // Convert message digest into hex value 78 | String hashtext = no.toString(16); 79 | while (hashtext.length() < 32) { 80 | hashtext = "0" + hashtext; 81 | } 82 | return hashtext; 83 | 84 | } catch (NoSuchAlgorithmException e) { 85 | System.err.println(e.getMessage()); 86 | } 87 | 88 | return ""; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/Shared/helper/Point.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.helper; 7 | 8 | /** 9 | * 10 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 11 | */ 12 | public class Point { 13 | 14 | public int x, y; 15 | 16 | public Point(int x, int y) { 17 | this.x = x; 18 | this.y = y; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Shared/helper/RandomString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.helper; 7 | 8 | import java.security.SecureRandom; 9 | import java.util.Locale; 10 | import java.util.Objects; 11 | import java.util.Random; 12 | 13 | /** 14 | * 15 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 16 | */ 17 | // source: https://stackoverflow.com/a/41156 18 | public class RandomString { 19 | 20 | /** 21 | * Generate a random string. 22 | */ 23 | public String nextString() { 24 | for (int idx = 0; idx < buf.length; ++idx) { 25 | buf[idx] = symbols[random.nextInt(symbols.length)]; 26 | } 27 | return new String(buf); 28 | } 29 | 30 | public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 31 | public static final String lower = upper.toLowerCase(Locale.ROOT); 32 | public static final String digits = "0123456789"; 33 | public static final String alphanum = upper + lower + digits; 34 | private final Random random; 35 | private final char[] symbols; 36 | private final char[] buf; 37 | 38 | public RandomString(int length, Random random, String symbols) { 39 | if (length < 1) { 40 | throw new IllegalArgumentException(); 41 | } 42 | if (symbols.length() < 2) { 43 | throw new IllegalArgumentException(); 44 | } 45 | this.random = Objects.requireNonNull(random); 46 | this.symbols = symbols.toCharArray(); 47 | this.buf = new char[length]; 48 | } 49 | 50 | /** 51 | * Create an alphanumeric string generator. 52 | */ 53 | public RandomString(int length, Random random) { 54 | this(length, random, alphanum); 55 | } 56 | 57 | /** 58 | * Create an alphanumeric strings from a secure generator. 59 | */ 60 | public RandomString(int length) { 61 | this(length, new SecureRandom()); 62 | } 63 | 64 | /** 65 | * Create session identifiers. 66 | */ 67 | public RandomString() { 68 | this(21); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/Shared/security/AES.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.security; 7 | 8 | import java.security.MessageDigest; 9 | import java.util.Arrays; 10 | import java.util.Base64; 11 | import java.util.UUID; 12 | import javax.crypto.Cipher; 13 | import javax.crypto.spec.SecretKeySpec; 14 | 15 | /** 16 | * 17 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 18 | */ 19 | // https://teamvietdev.com/ma-hoa-va-giai-ma-aes-trong-java/ 20 | public class AES { 21 | 22 | String secretKey; 23 | 24 | public AES() { 25 | secretKey = UUID.randomUUID().toString(); 26 | } 27 | 28 | public AES(String secretKey) { 29 | this.secretKey = secretKey; 30 | } 31 | 32 | public String getSecretKey() { 33 | return secretKey; 34 | } 35 | 36 | public void setSecretKey(String secretKey) { 37 | this.secretKey = secretKey; 38 | } 39 | 40 | public String encrypt(String strToEncrypt) { 41 | try { 42 | MessageDigest sha = MessageDigest.getInstance("SHA-1"); 43 | byte[] key = secretKey.getBytes("UTF-8"); 44 | key = sha.digest(key); 45 | key = Arrays.copyOf(key, 16); 46 | 47 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 48 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 49 | cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); 50 | 51 | return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); 52 | } catch (Exception e) { 53 | System.out.println(e.toString()); 54 | } 55 | 56 | return strToEncrypt; 57 | } 58 | 59 | public String decrypt(String strToDecrypt) { 60 | try { 61 | MessageDigest sha = MessageDigest.getInstance("SHA-1"); 62 | byte[] key = secretKey.getBytes("UTF-8"); 63 | key = sha.digest(key); 64 | key = Arrays.copyOf(key, 16); 65 | 66 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 67 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 68 | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); 69 | 70 | return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))); 71 | } catch (Exception e) { 72 | System.out.println(e.toString()); 73 | } 74 | 75 | return strToDecrypt; 76 | } 77 | 78 | public static void main(String[] args) { 79 | String secretKey = UUID.randomUUID().toString(); 80 | String originalString = "teamvietdev.com"; 81 | 82 | AES testAES = new AES(secretKey); 83 | 84 | System.out.println("SecretKey: " + secretKey); 85 | 86 | String encryptedString = testAES.encrypt(originalString); 87 | System.out.println("Encrypt: " + encryptedString); 88 | 89 | String decryptedString = testAES.decrypt(encryptedString); 90 | System.out.println("Decrypt: " + decryptedString); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Shared/security/RSA.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.security; 7 | 8 | import java.io.File; 9 | import java.nio.file.Files; 10 | import java.security.InvalidKeyException; 11 | import java.security.KeyFactory; 12 | import java.security.NoSuchAlgorithmException; 13 | import java.security.PrivateKey; 14 | import java.security.PublicKey; 15 | import java.security.spec.PKCS8EncodedKeySpec; 16 | import java.security.spec.X509EncodedKeySpec; 17 | import java.util.Base64; 18 | import java.util.logging.Level; 19 | import java.util.logging.Logger; 20 | import javax.crypto.BadPaddingException; 21 | import javax.crypto.Cipher; 22 | import javax.crypto.IllegalBlockSizeException; 23 | import javax.crypto.NoSuchPaddingException; 24 | 25 | /** 26 | * 27 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 28 | */ 29 | // https://stackjava.com/demo/code-java-vi-du-ma-hoa-giai-ma-voi-rsa.html 30 | public class RSA { 31 | 32 | PublicKey publicKey; 33 | PrivateKey privateKey; 34 | Cipher cipher; 35 | 36 | public RSA() { 37 | try { 38 | cipher = Cipher.getInstance("RSA"); 39 | } catch (NoSuchAlgorithmException | NoSuchPaddingException ex) { 40 | Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex); 41 | } 42 | } 43 | 44 | public RSA preparePublicKey(String publicKeyPath) { 45 | try { 46 | publicKey = getPublicKeyFromFile(publicKeyPath); 47 | } catch (Exception ex) { 48 | Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex); 49 | } 50 | return this; 51 | } 52 | 53 | public RSA preparePrivateKey(String privateKeyPath) { 54 | try { 55 | privateKey = getPrivateKeyFromFile(privateKeyPath); 56 | } catch (Exception ex) { 57 | Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex); 58 | } 59 | return this; 60 | } 61 | 62 | public PublicKey getPublicKeyFromFile(String filePath) throws Exception { 63 | byte[] keyBytes = Files.readAllBytes(new File(filePath).toPath()); 64 | X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); 65 | KeyFactory kf = KeyFactory.getInstance("RSA"); 66 | return kf.generatePublic(spec); 67 | } 68 | 69 | public PrivateKey getPrivateKeyFromFile(String filePath) throws Exception { 70 | byte[] keyBytes = Files.readAllBytes(new File(filePath).toPath()); 71 | PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); 72 | KeyFactory kf = KeyFactory.getInstance("RSA"); 73 | return kf.generatePrivate(spec); 74 | } 75 | 76 | public String encrypt(String original) { 77 | if(publicKey == null) { 78 | System.err.println("Không thể mã hóa! Chưa có public key."); 79 | } 80 | 81 | try { 82 | cipher.init(Cipher.ENCRYPT_MODE, publicKey); 83 | 84 | byte[] byteEncrypted = cipher.doFinal(original.getBytes()); 85 | String encrypted = Base64.getEncoder().encodeToString(byteEncrypted); 86 | 87 | return encrypted; 88 | 89 | } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) { 90 | Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex); 91 | } 92 | 93 | return ""; 94 | } 95 | 96 | public String decrypt(String encrypted) { 97 | if(privateKey == null) { 98 | System.err.println("Không thể giải mã! Chưa có private key."); 99 | } 100 | try { 101 | cipher.init(Cipher.DECRYPT_MODE, privateKey); 102 | 103 | byte[] byteDecrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted)); 104 | String decrypted = new String(byteDecrypted); 105 | 106 | return decrypted; 107 | 108 | } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) { 109 | Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex); 110 | } 111 | 112 | return ""; 113 | } 114 | 115 | public static void main(String[] args) throws Exception { 116 | RSA serverSide = new RSA() 117 | .preparePrivateKey("src/Server/rsa_keypair/privateKey") 118 | .preparePublicKey("src/Server/rsa_keypair/publicKey"); 119 | 120 | RSA clientSide = new RSA() 121 | .preparePublicKey("src/Server/rsa_keypair/publicKey"); 122 | 123 | String original = "stackjava.com"; 124 | System.out.println("Original: " + original); 125 | 126 | String encrypted = clientSide.encrypt(original); 127 | System.out.println("Encrypted: " + encrypted); 128 | 129 | String decrypted = serverSide.decrypt(encrypted); 130 | System.out.println("Decrypted: " + decrypted); 131 | 132 | // Lỗi javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes 133 | // => hay: https://stackoverflow.com/a/46828430 134 | // 24/11/2020 => đã fix xong, Dùng Base64.getDecoder().decode() khi decrypt dữ liệu 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/Shared/security/RSAGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package shared.security; 7 | 8 | import java.io.File; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.security.KeyPair; 12 | import java.security.KeyPairGenerator; 13 | import java.security.NoSuchAlgorithmException; 14 | import java.security.PrivateKey; 15 | import java.security.PublicKey; 16 | 17 | /** 18 | * 19 | * @author Hoang Tran < hoang at 99.hoangtran@gmail.com > 20 | */ 21 | // https://stackjava.com/demo/code-java-vi-du-ma-hoa-giai-ma-voi-rsa.html 22 | public class RSAGenerator { 23 | 24 | public static final String PUBLIC_KEY_FILE = "rsa_keypair/publicKey"; 25 | public static final String PRIVATE_KEY_FILE = "rsa_keypair/privateKey"; 26 | public static String basePath = ""; 27 | 28 | private KeyPairGenerator keyGen; 29 | private KeyPair pair; 30 | private PrivateKey privateKey; 31 | private PublicKey publicKey; 32 | 33 | public RSAGenerator(int keylength, String basePath) { 34 | try { 35 | this.basePath = basePath; 36 | this.keyGen = KeyPairGenerator.getInstance("RSA"); 37 | this.keyGen.initialize(keylength); 38 | } catch (NoSuchAlgorithmException e) { 39 | System.err.println(e.getMessage()); 40 | } 41 | } 42 | 43 | public void createKeys() { 44 | this.pair = this.keyGen.generateKeyPair(); 45 | this.privateKey = pair.getPrivate(); 46 | this.publicKey = pair.getPublic(); 47 | } 48 | 49 | public PrivateKey getPrivateKey() { 50 | return this.privateKey; 51 | } 52 | 53 | public PublicKey getPublicKey() { 54 | return this.publicKey; 55 | } 56 | 57 | public void writeToFile(String path, byte[] key) throws IOException { 58 | try { 59 | File f = new File(path); 60 | f.getParentFile().mkdirs(); 61 | 62 | FileOutputStream fos = new FileOutputStream(f); 63 | fos.write(key); 64 | fos.flush(); 65 | fos.close(); 66 | } catch (Exception e) { 67 | System.err.println(e.getMessage()); 68 | } 69 | } 70 | 71 | public void generateKeysToFile() { 72 | try { 73 | System.out.println("Starting generate..."); 74 | this.createKeys(); 75 | this.writeToFile(basePath + PUBLIC_KEY_FILE, this.getPublicKey().getEncoded()); 76 | this.writeToFile(basePath + PRIVATE_KEY_FILE, this.getPrivateKey().getEncoded()); 77 | System.out.println("Generated to '" + basePath + "' !"); 78 | } catch (IOException e) { 79 | System.err.println(e.getMessage()); 80 | } 81 | } 82 | 83 | public static void main(String[] args) { 84 | new RSAGenerator(1024, "src/Server/").generateKeysToFile(); 85 | } 86 | } 87 | --------------------------------------------------------------------------------