Coverage report for ai


src/
File: src/client/Client.cpp
Date: 2024-06-25 10:57:00
Lines:
0/123
0.0%
Functions:
0/15
0.0%
Branches:
0/178
0.0%

Line Branch Exec Source
1 /*
2 ** EPITECH PROJECT, 2024
3 ** zappy/ai/client
4 ** File description:
5 ** Client.cpp
6 */
7
8 #include "Client.hpp"
9
10 Client::Client(const std::string &host, const std::string &teamName, int port)
11 : _host(host), _teamName(teamName), _port(port)
12 {
13 setupConnection();
14 }
15
16 Client::~Client()
17 {
18 close(_sockfd);
19 }
20
21 void Client::run()
22 {
23 printColor("Run client\n\n", BRIGHT_BLUE);
24
25 authenticate();
26 loop();
27 }
28
29 void Client::setupConnection()
30 {
31 _sockfd = socket(AF_INET, SOCK_STREAM, 0);
32 if (_sockfd < 0)
33 {
34 perror("Socket creation failed");
35 exit(EXIT_FAILURE);
36 }
37
38 struct sockaddr_in serv_addr;
39
40 serv_addr.sin_family = AF_INET;
41 serv_addr.sin_port = htons(_port);
42 if (inet_pton(AF_INET, _host.c_str(), &serv_addr.sin_addr) <= 0)
43 {
44 perror("Invalid address or address not supported");
45 exit(EXIT_FAILURE);
46 }
47 if (connect(_sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
48 {
49 perror("Connection failed");
50 exit(EXIT_FAILURE);
51 }
52 else
53 printColor("🚀✅ Connected to server: " + _host + ":" + std::to_string(_port) + " on team: " + _teamName + "\n", BRIGHT_BLUE);
54 }
55
56 void Client::authenticate()
57 {
58 std::string buffer;
59 Message _message;
60 unsigned int timeToGetIdentity = 0;
61 std::string askForIdentity = "";
62
63 // To pass the first message WELCOME
64 recvMessage(buffer);
65
66 // Ask two time for identity
67 _message.format("I'm_searching_my_identity");
68 askForIdentity = "Broadcast " + _message.content;
69 sendMessage(_teamName);
70 sendMessage(askForIdentity);
71 sendMessage(askForIdentity);
72 _message.content = "";
73
74 auto condition = [&]()
75 { return timeToGetIdentity < 3; };
76
77 auto action = [&]()
78 {
79 std::string response;
80 recvMessage(response);
81 if (response.find("ko") != std::string::npos)
82 {
83 PRINT_ERROR("Authentication failed: verify teamName");
84 close(_sockfd);
85 exit(EXIT_FAILURE);
86 }
87 if (response.find("message") != std::string::npos)
88 {
89 _message.content = response;
90 _message.vigenereDecrypt();
91 return;
92 }
93 timeToGetIdentity++;
94 _messageToReadBeforeStart--;
95 };
96 interactWithServer(condition, action);
97 try
98 {
99 initBot(_message.content);
100 }
101 catch (const ClientException &e)
102 {
103 PRINT_ERROR(e.what());
104 close(_sockfd);
105 exit(EXIT_FAILURE);
106 }
107 }
108
109 void Client::initBot(const std::string identityMessage)
110 {
111 unsigned int id = 0;
112 unsigned int currentMessageId = 0;
113
114 if (!identityMessage.empty())
115 {
116 std::cout << "identityMessage: " << identityMessage << std::endl;
117 std::string job = "";
118 std::string prefixId = "you_are_bot=";
119 std::string prefixJob = "your_job=";
120 std::string prefixCurrentMessageId = "currentMessageId=";
121 size_t pos = identityMessage.find(prefixId);
122 size_t posJob = identityMessage.find(prefixJob);
123 size_t posCurrentMessageId = identityMessage.find(prefixCurrentMessageId);
124
125 if (pos != std::string::npos)
126 {
127 std::string idStr = identityMessage.substr(pos + prefixId.size());
128 id = std::stoi(idStr);
129 }
130 if (posCurrentMessageId != std::string::npos)
131 {
132 std::string currentMessageIdStr = identityMessage.substr(posCurrentMessageId + prefixCurrentMessageId.size());
133 currentMessageId = std::stoi(currentMessageIdStr);
134 }
135 if (posJob != std::string::npos)
136 {
137 job = identityMessage.substr(posJob + prefixJob.size());
138 if (job.find("SIMPLE_BOT") != std::string::npos)
139 _bot = BotFactory::createBot("SimpleBot");
140 }
141 else
142 {
143 _bot = BotFactory::createBot("SimpleBot");
144 }
145 }
146 else
147 {
148 _bot = BotFactory::createBot("SimpleBot"); // TODO: is forker normally
149 if (_bot == nullptr)
150 throw ClientException("BotFactory failed");
151 }
152 if (_bot != nullptr)
153 {
154 _bot->init(_sockfd, _teamName, _host, _port, id, currentMessageId);
155 }
156 else
157 {
158 throw ClientException("Bot is null");
159 }
160 }
161
162 void Client::sendMessage(const std::string &message)
163 {
164 std::string messageToSend = message + "\n";
165
166 send(_sockfd, messageToSend.c_str(), messageToSend.size(), 0);
167 }
168
169 void Client::loop()
170 {
171 // clear messsages of servers before start
172 auto condition = [&]()
173 { return _messageToReadBeforeStart > 0; };
174 auto action = [&]()
175 {
176 std::string response;
177 recvMessage(response);
178 _messageToReadBeforeStart--;
179 };
180 interactWithServer(condition, action);
181
182 _bot->run("start");
183 auto conditionStart = [&]()
184 { return true; };
185 auto actionStart = [&]()
186 {
187 std::string response;
188 recvMessage(response);
189 _bot->run(response);
190 };
191 interactWithServer(conditionStart, actionStart);
192 }
193
194 void Client::recvMessage(std::string &buffer)
195 {
196 char recvBuffer[1024] = {0};
197 int valread = read(_sockfd, recvBuffer, 1024);
198
199 if (valread < 0)
200 {
201 PRINT_ERROR("Read failed");
202 close(_sockfd);
203 exit(FAILURE);
204 }
205 else if (valread == 0)
206 {
207 PRINT_ERROR("Server closed the connection");
208 close(_sockfd);
209 exit(FAILURE);
210 }
211
212 buffer = std::string(recvBuffer, valread);
213 }
214
215 template <typename ConditionFunc, typename ActionFunc>
216 void Client::interactWithServer(ConditionFunc condition, ActionFunc action)
217 {
218 while (condition())
219 {
220 FD_ZERO(&_readfds);
221 FD_SET(_sockfd, &_readfds);
222 _tv.tv_sec = 0;
223 _tv.tv_usec = 10000;
224 int activity = select(_sockfd + 1, &_readfds, NULL, NULL, &_tv);
225
226 if (activity > 0 && FD_ISSET(_sockfd, &_readfds))
227 action();
228 }
229 }
230