From a2d696dea797faaa3157046c8ae89cd70e965bff Mon Sep 17 00:00:00 2001 From: scratko Date: Sat, 10 Aug 2024 02:46:56 +0300 Subject: Prefinal version Added client. Moved files to directories. --- server/server_data_processing.c | 337 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 server/server_data_processing.c (limited to 'server/server_data_processing.c') diff --git a/server/server_data_processing.c b/server/server_data_processing.c new file mode 100644 index 0000000..30953bf --- /dev/null +++ b/server/server_data_processing.c @@ -0,0 +1,337 @@ +#include "server_data_processing.h" +#include "server.h" + +#include +#include +#include +#include + +enum { + output_buffer_size = 1024 +}; + +static char output_buffer[output_buffer_size]; + +static int write_to_client(int fd, int length) +{ + return write(fd, output_buffer, length); +} + +static int read_from_client(int fd, char *buffer, int max_buffer_size) +{ + int read_result; + read_result = read(fd, buffer, max_buffer_size); + if(read_result <= 0) + return 0; + /* buffer overflow */ + if(read_result >= max_buffer_size) + return 0; + return read_result; +} + +int print_message_for_first_player(int fd) +{ + int data_size; + + data_size = sprintf(output_buffer, "%u\n", first_player); + return write_to_client(fd, data_size); +} + +int print_connected_players(int fd, int number) +{ + int data_size; + + data_size = sprintf(output_buffer, "%u:%u\n", confirmation_waiting, number); + return write_to_client(fd, data_size); +} + +/* + * 1 - ready + * 0 - buffer overflow or player closed session + * -1 - not ready + */ +int check_readiness(struct session *client) +{ + int read_result; + read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + if(!read_result) + return read_result; + if(client->buffer[0] == '\n') + return 1; + else + return -1; +} +/* + * example: 10#\A^\7v'\n' + * or 0'\n' + */ +static void copy_card_queue(int *offset, struct card_queue *cq) +{ + int length, i; + struct card_queue_item *next_attack_card; + + next_attack_card = NULL; + while((next_attack_card = get_next_card_from_queue(cq, next_attack_card))) { + length = strlen(next_attack_card->str); + for(i = 0; i < length; ++i, ++*offset) + *(output_buffer + *offset) = (next_attack_card->str)[i]; + /* delimiter */ + *(output_buffer + *offset) = '\\'; + ++*offset; + } + *(output_buffer + *offset-1) = ':'; +} + +/* + * example: 10#+\+Q#+A^+\+-+7v: + * or 0: + */ +static void copy_cards_on_table(int *offset, struct cards_on_table cot) +{ + int i, j, length; + for(i = 0; i <= cot.card_arr_idx; ++i) { + length = strlen(cot.card_arr[i]); + for(j = 0; j < length; ++j, ++*offset) + *(output_buffer + *offset) = cot.card_arr[i][j]; + /* delimiter */ + *(output_buffer + *offset) = '+'; + ++*offset; + } + *(output_buffer + *offset-1) = ':'; +} +/* + * example: 10#\A^\7v: + * or 10#\A^\7v'\n' + * or 0: + * or 0'\n' + */ +static void copy_own_deck(int *offset, player_cards deck) +{ + const char *card; + int length, i; + + while(deck) { + card = deck->str; + length = strlen(card); + for(i = 0; i < length; ++i, ++*offset) + *(output_buffer + *offset) = card[i]; + *(output_buffer + *offset) = '\\'; + ++*offset; + deck = deck->next; + } + *(output_buffer + *offset-1) = ':'; +} + +static void copy_base_info(int *free_pos, struct game_info *gi, + enum client_game_states state, player_cards deck, + int player_position) +{ + int i; + + *free_pos = + sprintf(output_buffer, "%u:%u:%u:%u:%s:", state, gi->players_number, + gi->shuffled_cards_left, player_position, gi->trump_card); + /* + * opponent's card count + * example: 2\6\3: + */ + for(i = 0; i < gi->players_number; ++i) { + + *free_pos += sprintf(output_buffer + *free_pos, "%u\\", + gi->card_quantity_arr[i]); + } + *(output_buffer + *free_pos-1) = ':'; + + if(gi->cot->card_arr_idx != -1) + copy_cards_on_table(free_pos, *gi->cot); + else + *free_pos += sprintf(output_buffer + *free_pos, "0:"); + + if(!is_empty_stack(deck)) + copy_own_deck(free_pos, deck); + else + *free_pos += sprintf(output_buffer + *free_pos, "0:"); +} + +int print_game_part(const struct session *client, struct game_info *gi) +{ + int free_pos; /* free_pos == data length */ + + copy_base_info(&free_pos, gi, client->state, client->deck, + client->player_position); + + switch(client->state) { + case display_only_table: + /* let the client print card tips and wait for input */ + case attack: + case defense: + /* + * who haven't got tossing card (including defender) must wait + * when other players make moves + */ + case tossing_expectation: + case tossing: + /* instead of last ':' */ + *(output_buffer + free_pos-1) = '\n'; + break; + /* other clents will be waiting particular player */ + case attack_expectation: + free_pos += sprintf(output_buffer + free_pos, "%u:", + gi->position_whose_turn); + *(output_buffer + free_pos-1) = '\n'; + break; + case defense_expectation: + /* copying whose turn */ + free_pos += sprintf(output_buffer + free_pos, "%u:", + gi->position_whose_turn); + /* copying card queue */ + if(is_empty_queue(gi->cq)) + free_pos += sprintf(output_buffer + free_pos, "0:"); + else + copy_card_queue(&free_pos, gi->cq); + *(output_buffer + free_pos-1) = '\n'; + default: + {} + } + return write_to_client(client->fd, free_pos); +} +#if 0 +static int is_receiving_cards_limit(int total_defense_cards, int total_attack_cards) +{ + if(total_defense_cards >= start_deck_size && + total_attack_cards == start_deck_size) { + return 1; + } else if(total_defense_cards == total_attack_cards) + return 1; + return 0; +} +#endif + +int get_cards_from_attacker(struct session *client, + const struct cards_on_table *cot, + const player_cards defense_deck, + struct card_queue *cq) +{ + int read_result, i, j; + int card_return_status = 0, all_cards_received_status = 1; + int data_length; + char given_card[4]; + const char *stack_card = NULL; + + read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + if(!read_result) + return read_result; + for(i = 0, j = 0; i < read_result && client->buffer[i] != '\n'; ++i) { + if(client->buffer[i] == '\\') { + given_card[j] = '\0'; + j = 0; + if(card_return_status) { + all_cards_received_status = 0; + break; + } + stack_card = remove_card_from_stack(&client->deck, given_card); + push_queue(cq, stack_card); + if(is_receiving_cards_limit(cot, defense_deck, cq)) + card_return_status = 1; + continue; + } + given_card[j] = client->buffer[i]; + ++j; + } + data_length = sprintf(output_buffer, "%d:%s\n", card_acceptance_status, + all_cards_received_status ? "all" : "not all"); + write_to_client(client->fd, data_length); + return read_result; +} + +/* + * 0 - error + * 1 - card was bited, not bited, or + * defender didn't want to continue defense phase + * + */ +int get_card_from_defender(struct session *client, struct cards_on_table *cot, + const char * trump_suit) +{ + int read_result, i; + char given_card[4]; + const char *stack_card = NULL; + + read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + if(!read_result) + return read_result; + for(i = 0; i < read_result && client->buffer[i] != '\n'; ++i) + given_card[i] = client->buffer[i]; + if(given_card[0] == '\n') + return 1; + given_card[i] = '\0'; + if(is_card_bit(cot->card_arr[cot->card_arr_idx-2], given_card, trump_suit)){ + stack_card = remove_card_from_stack(&client->deck, given_card); + put_defender_card_on_table(cot, stack_card); + return 1; + } else + return 0; +} + +/* + * 0 - buffer overflow or client closed connection + * 1 - some number of cards added to card queue + * 2 - card toss limit was reached when accepting cards from this player + * 3 - player refused to toss the card + * + * example: 10#\A^\7v\'\n' + */ +int get_cards_from_tossing_player(struct session *client, + const player_cards defense_deck, + struct cards_on_table *cot, + struct card_queue *cq) +{ + int read_result, i, j; + int card_return_status = 0, all_cards_received_status = 1; + int data_length; + char given_card[4]; + const char *stack_card = NULL; + + read_result = read_from_client(client->fd, client->buffer, max_buffer_size); + if(!read_result) + return read_result; + + for(i = 0, j = 0; i < read_result; ++i) { + if(client->buffer[i] == '\\') { + /* cancellation */ + if(given_card[0] == '\n') + return 3; + /* tossing limit was set */ + if(client->tm == cancel) { + /* it's impossible to accept cards due to tossing limit */ + data_length = + sprintf(output_buffer, "%d\n", tossing_limit_status); + write_to_client(client->fd, data_length); + return 3; + } + given_card[j] = '\0'; + j = 0; + if(card_return_status) { + all_cards_received_status = 0; + } else if(is_correct_tossing_card(given_card, cot)) { + stack_card = remove_card_from_stack(&client->deck, given_card); + push_queue(cq, stack_card); + if(is_receiving_cards_limit(cot, defense_deck, cq)) + { + card_return_status = 1; + } + } + continue; + } + given_card[j] = client->buffer[i]; + ++j; + } + /* 7 -- state for result of received cards */ + data_length = sprintf(output_buffer, "%d:%s\n", card_acceptance_status, + all_cards_received_status ? "all" : "not all"); + write_to_client(client->fd, data_length); + if(all_cards_received_status) + return 1; + else + return 2; +} -- cgit v1.2.3