/** * @file Game.c * @author Pedro Lopes * @version 0.2 * @date 2022-10-02 * @copyright Copyright (c) 2022 **/ // -------------------------------------------------------------------------------- // // Includes #include #include #include #include #include // -------------------------------------------------------------------------------- // // Definitions #define MAX_GAMES 9000 #define MAX_FIELD_SIZE 250 #define MAX_STRING_ARRAY_SIZE 100 // -------------------------------------------------------------------------------- // // Structs typedef struct { int year, month; } Date; typedef struct { char name[MAX_FIELD_SIZE], owners[MAX_FIELD_SIZE], website[MAX_FIELD_SIZE], developers[MAX_FIELD_SIZE], languages[MAX_STRING_ARRAY_SIZE][30], genres[MAX_STRING_ARRAY_SIZE][30]; Date release_date; int app_id, age, dlcs, avg_playtime, count_languages, count_genres; float price, upvotes; bool windows_os, mac_os, linux_os; } Game; // -------------------------------------------------------------------------------- // // Global variables Game games[MAX_GAMES]; int n = 0; // -------------------------------------------------------------------------------- // // Functions bool isFim(char* line) { return line[0] == 'F' && line[1] == 'I' && line[2] == 'M'; } void substring(char *string, char *string_start, int length) { strncpy(string, string_start, length); string[length] = '\0'; } char *getMonthName(int month) { switch(month) { case 1: return "Jan"; break; case 2: return "Feb"; break; case 3: return "Mar"; break; case 4: return "Apr"; break; case 5: return "May"; break; case 6: return "Jun"; break; case 7: return "Jul"; break; case 8: return "Aug"; break; case 9: return "Sep"; break; case 10: return "Oct"; break; case 11: return "Nov"; break; case 12: return "Dec"; break; default: return "N/A"; break; } } int getMonthNumber(char* month) { if(!strcmp(month, "Jan")) return 1; else if(!strcmp(month, "Feb")) return 2; else if(!strcmp(month, "Mar")) return 3; else if(!strcmp(month, "Apr")) return 4; else if(!strcmp(month, "May")) return 5; else if(!strcmp(month, "Jun")) return 6; else if(!strcmp(month, "Jul")) return 7; else if(!strcmp(month, "Aug")) return 8; else if(!strcmp(month, "Sep")) return 9; else if(!strcmp(month, "Oct")) return 10; else if(!strcmp(month, "Nov")) return 11; else if(!strcmp(month, "Dec")) return 12; } // -------------------------------------------------------------------------------- // // Class game functions void game_start(Game *game) { strcpy(game -> name, ""); strcpy(game -> owners, ""); strcpy(game -> website, ""); strcpy(game -> developers, ""); for(int i = 0; i < MAX_STRING_ARRAY_SIZE; i++) { strcpy(game -> languages[i], ""); strcpy(game -> genres[i], ""); } game -> release_date.month = -1; game -> release_date.year = -1; game -> app_id = -1; game -> age = -1; game -> dlcs = -1; game -> avg_playtime = -1; game -> price = -1; game -> upvotes = -1; game -> windows_os = false; game -> mac_os = false; game -> linux_os = false; game -> count_languages = 0; game -> count_genres = 0; } void game_print(Game *game) { int hours = game -> avg_playtime / 60, minutes = game -> avg_playtime % 60; printf("%i %s %s/%04i %s %i %.2f %i [", game -> app_id, game -> name, getMonthName(game -> release_date.month), game -> release_date.year, game -> owners, game -> age, game -> price, game -> dlcs); for(int i = 0; i < game -> count_languages; i++) { printf("%s%s", game -> languages[i], i < game -> count_languages - 1 ? ", " : ""); } printf("] %s %s %s %s ", game -> website, game -> windows_os ? "true" : "false", game -> mac_os ? "true" : "false", game -> linux_os ? "true" : "false"); if(isnan(game -> upvotes)) printf("0.0%% "); else printf("%.0f%% ", game -> upvotes); if(hours > 0) { printf("%ih ", hours); if(minutes > 0) printf("%im ", minutes); } else { if(minutes > 0) printf("%im ", minutes); else printf("null "); } printf("%s [", game -> developers); for(int i = 0; i < game -> count_genres; i++) { printf("%s%s", game -> genres[i], i < game -> count_genres - 1 ? ", " : ""); } printf("]\n"); } Game game_clone(Game *game) { Game cloned; strcpy(cloned.name, game -> name); strcpy(cloned.owners, game -> owners); strcpy(cloned.website, game -> website); strcpy(cloned.developers, game -> developers); for(int i = 0; i < game -> count_languages; i++) strcpy(cloned.languages[i], game -> languages[i]); for(int i = 0; i < game -> count_genres; i++) strcpy(cloned.genres[i], game -> genres[i]); cloned.release_date.month = game -> release_date.month; cloned.release_date.year = game -> release_date.year; cloned.app_id = game -> app_id; cloned.age = game -> age; cloned.dlcs = game -> dlcs; cloned.avg_playtime = game -> avg_playtime; cloned.price = game -> price; cloned.upvotes = game -> upvotes; cloned.windows_os = game -> windows_os; cloned.mac_os = game -> mac_os; cloned.linux_os = game -> linux_os; return cloned; } void game_read(Game *game, char *line) { char c_search, sub[MAX_FIELD_SIZE]; int index = 0, atr_index = 0; // ------------------------------------------------------------ // // Find "AppID" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); game -> app_id = atoi(sub); atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "Name" if(line[atr_index] != ',') { if(line[atr_index] == '\"') { atr_index++; c_search = '\"'; } else c_search = ','; while(true) { index++; if(line[index] == c_search) { substring(sub, &line[atr_index], index - atr_index); strcpy(game -> name, sub); if(c_search == ',') index++; else if(c_search == '\"') index += 2; atr_index = index; break; } } } else { strcpy(game -> name, "null"); atr_index = ++index; } // ------------------------------------------------------------ // // Find release date if(line[atr_index] != ',') { if(line[atr_index] == '\"') { atr_index++; c_search = '\"'; } else c_search = ','; while(true) { index++; if(line[index] == c_search) { substring(sub, &line[atr_index], index - atr_index); char subDate[10]; substring(subDate, &sub[0], 3); game -> release_date.month = getMonthNumber(subDate); if(c_search == ',') { substring(subDate, &sub[4], 4); game -> release_date.year = atoi(subDate); index++; } else if(c_search == '\"') { int nmbSpace = 0; for(int i = 0; ; i++) { if(sub[i] == ' ') nmbSpace++; if(nmbSpace == 2) { i++; substring(subDate, &sub[i], 4); game -> release_date.year = atoi(subDate); break; } } index += 2; } atr_index = index; break; } } } else { game -> release_date.month = 0; game -> release_date.year = 0; atr_index = ++index; } // ------------------------------------------------------------ // // Find "Owners" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); strcpy(game -> owners, sub); atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "Age" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); game -> age = atoi(sub); atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "Price" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); game -> price = atof(sub); atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "DLCs" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); game -> dlcs = atoi(sub); atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "Languages" while(true) { index++; if(line[index] == ']') { index++; if(line[index] == ',') index++; else if(line[index] == '\"') index += 2; atr_index = index; break; } else if(line[index] == '\'') { int wordStart = index + 1; while(true) { index++; if(line[index] == '\'') { substring(sub, &line[wordStart], index - wordStart); strcpy(game -> languages[game -> count_languages++], sub); break; } } } } // ------------------------------------------------------------ // // Find "Website" if(line[atr_index] != ',') { if(line[atr_index] == '\"') { atr_index++; c_search = '\"'; } else c_search = ','; while(true) { index++; if(line[index] == c_search) { substring(sub, &line[atr_index], index - atr_index); strcpy(game -> website, sub); atr_index = ++index; break; } } } else { strcpy(game -> website, "null"); atr_index = ++index; } // ------------------------------------------------------------ // // Find "Windows" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); if(!strcmp(sub, "True")) game -> windows_os = true; atr_index = ++index; break; } } // Find "Mac" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); if(!strcmp(sub, "True")) game -> mac_os = true; atr_index = ++index; break; } } // Find "Linux" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); if(!strcmp(sub, "True")) game -> linux_os = true; atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "Upvotes" int positives, negatives; while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); positives = atoi(sub); atr_index = ++index; break; } } while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); negatives = atoi(sub); atr_index = ++index; break; } } game -> upvotes = (float)(positives * 100) / (float)(positives + negatives); // ------------------------------------------------------------ // // Find "AVG Playtime" while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); game -> avg_playtime = atoi(sub); atr_index = ++index; break; } } // ------------------------------------------------------------ // // Find "Developers" if(line[atr_index] != ',') { if(line[atr_index] == '\"') { atr_index++; c_search = '\"'; } else c_search = ','; while(true) { index++; if(line[index] == c_search) { substring(sub, &line[atr_index], index - atr_index); strcpy(game -> developers, sub); atr_index = ++index; break; } } } else { strcpy(game -> developers, "null"); atr_index = ++index; } // ------------------------------------------------------------ // // Find "Genres" if(index < strlen(line) - 1) { if(line[index] == ',') atr_index = ++index; if(line[atr_index] == '\"') { atr_index++; while(true) { index++; if(line[index] == ',') { substring(sub, &line[atr_index], index - atr_index); strcpy(game -> genres[game -> count_genres++], sub); atr_index = ++index; } else if(line[index] == '\"') { substring(sub, &line[atr_index], strlen(line) - 1 - atr_index); if(sub[strlen(sub) - 1] == '\"') sub[strlen(sub) - 1] = '\0'; else if(sub[strlen(sub) - 2] == '\"') sub[strlen(sub) - 2] = '\0'; strcpy(game -> genres[game -> count_genres++], sub); break; } } } else { substring(sub, &line[atr_index], strlen(line) - 2 - atr_index); strcpy(game -> genres[game -> count_genres++], sub); } } } // -------------------------------------------------------------------------------- // // Functions - List void list_insert(Game x) { if(n >= MAX_GAMES) { printf("Insert error: MAX_GAMES reached"); exit(1); } games[n++] = x; } // ---------------------------------------------------------------------------------------------------------- // int main() { // ------------------------------------------------------------ // // First part - Read all games // Open CSV file FILE *fp; char *line = NULL; size_t len = 0; size_t read; fp = fopen("/tmp/games.csv", "r"); if(fp == NULL) exit(EXIT_FAILURE); // ------------------------- // // Fill games list while((read = getline(&line, &len, fp)) != -1) { Game game; game_start(&game); game_read(&game, line); list_insert(game); } // ------------------------- // fclose(fp); if(line) free(line); // ------------------------------------------------------------ // // Second part - Print .in games char in[15]; scanf(" %[^\n]s", in); while(true) { if(isFim(in)) break; else { int app_id = atoi(in); for(int i = 0; i < n; i++) { if(games[i].app_id == app_id) { game_print(&games[i]); break; } } // ------------------------- // scanf(" %[^\n]s", in); } } return EXIT_SUCCESS; }