├── .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 extends PlayerInGame> 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 |
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 |
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 |
--------------------------------------------------------------------------------