728 lines
16 KiB
C
728 lines
16 KiB
C
/**
|
|
|
|
* @file Game.c
|
|
* @author Pedro Lopes
|
|
* @version 0.2
|
|
* @date 2022-10-02
|
|
* @copyright Copyright (c) 2022
|
|
|
|
**/
|
|
|
|
// -------------------------------------------------------------------------------- //
|
|
|
|
// Includes
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <math.h>
|
|
|
|
// -------------------------------------------------------------------------------- //
|
|
|
|
// 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;
|
|
} |