diff --git a/tps/enunciado/tp3.pdf b/tps/enunciado/tp3.pdf new file mode 100644 index 0000000..8b89210 Binary files /dev/null and b/tps/enunciado/tp3.pdf differ diff --git a/tps/fonte/Game.c b/tps/fonte/Game.c new file mode 100644 index 0000000..7ff30eb --- /dev/null +++ b/tps/fonte/Game.c @@ -0,0 +1,645 @@ +/** + * @file Game.c + * @author Pedro Costa + * @version 0.1 + * @date 2022-09-25 + * + * @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; + +// -------------------------------------------------------------------------------- // + +// Functions +bool isFim(char *str) { return str[0] == 'F' && str[1] == 'I' && str[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) - 2] == '\"') + sub[strlen(sub) - 2] = '\0'; + strcpy(game->genres[game->count_genres++], sub); + break; + } + } + } + else + { + substring(sub, &line[atr_index], strlen(line) - 1 - atr_index); + sub[strlen(line) - 2 - atr_index] = '\0'; + strcpy(game->genres[game->count_genres++], sub); + } + } +} + +// ---------------------------------------------------------------------------------------------------------- // + +int main() +{ + char csvFile[20]; + scanf("%s", csvFile); + + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t read; + + fp = fopen(csvFile, "r"); + + if (fp == NULL) + exit(EXIT_FAILURE); + + // ------------------------------------------------------------ // + + while ((read = getline(&line, &len, fp)) != -1) + { + Game game; + game_start(&game); + game_read(&game, line); + game_print(&game); + } + + // ------------------------------------------------------------ // + fclose(fp); + + if (line) + free(line); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tps/fonte/Game.java b/tps/fonte/Game.java new file mode 100644 index 0000000..4fdc197 --- /dev/null +++ b/tps/fonte/Game.java @@ -0,0 +1,490 @@ + +/** + * @file Game.java + * @author Pedro Costa + * @version 0.1 + * @date 2022-09-25 + * + * @copyright Copyright (c) 2022 + */ +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Locale; + +public class Game { + + static SimpleDateFormat default_dateFormat = new SimpleDateFormat("MMM/yyyy", Locale.ENGLISH); + + private String name, owners, website, developers; + private ArrayList languages, genres; + private Date release_date; + private int app_id, age, dlcs, avg_playtime; + private float price, upvotes; + private boolean windows, mac, linux; + + public Game() { + this.name = this.owners = this.website = this.developers = null; + this.languages = new ArrayList(); + this.genres = new ArrayList(); + this.release_date = null; + this.app_id = this.age = this.dlcs = this.avg_playtime = -1; + this.price = this.upvotes = -1; + this.windows = this.mac = this.linux = false; + } + + public Game(String name, String owners, String website, String developers, ArrayList languages, + ArrayList genres, Date release_date, int app_id, int age, int dlcs, int upvotes, int avg_playtime, + float price, boolean windows, boolean mac, boolean linux) { + this.name = name; + this.owners = owners; + this.website = website; + this.developers = developers; + this.languages = languages; + this.genres = genres; + this.release_date = release_date; + this.app_id = app_id; + this.age = age; + this.dlcs = dlcs; + this.upvotes = upvotes; + this.avg_playtime = avg_playtime; + this.price = price; + this.windows = windows; + this.mac = mac; + this.linux = linux; + } + + public void setName(String name) { + this.name = name; + } + + public void setOwners(String owners) { + this.owners = owners; + } + + public void setWebsite(String website) { + this.website = website; + } + + public void setDevelopers(String developers) { + this.developers = developers; + } + + public void setLanguages(ArrayList languages) { + this.languages = languages; + } + + public void setGenres(ArrayList genres) { + this.genres = genres; + } + + public void setReleaseDate(Date release_date) { + this.release_date = release_date; + } + + public void setAppId(int app_id) { + this.app_id = app_id; + } + + public void setAge(int age) { + this.age = age; + } + + public void setDlcs(int dlcs) { + this.dlcs = dlcs; + } + + public void setAvgPlaytime(int avg_playtime) { + this.avg_playtime = avg_playtime; + } + + public void setPrice(float price) { + this.price = price; + } + + public void setUpvotes(float upvotes) { + this.upvotes = upvotes; + } + + public void setWindows(boolean windows) { + this.windows = windows; + } + + public void setMac(boolean mac) { + this.mac = mac; + } + + public void setLinux(boolean linux) { + this.linux = linux; + } + + public String getName() { + return this.name; + } + + public String getOwners() { + return this.owners; + } + + public String getWebsite() { + return this.website; + } + + public String getDevelopers() { + return this.developers; + } + + public ArrayList getLanguages() { + return this.languages; + } + + public ArrayList getGenres() { + return this.genres; + } + + public Date getReleaseDate() { + return this.release_date; + } + + public int getAppId() { + return this.app_id; + } + + public int getAge() { + return this.age; + } + + public int getDlcs() { + return this.dlcs; + } + + public int getAvgPlaytime() { + return this.avg_playtime; + } + + public float getPrice() { + return this.price; + } + + public float getUpvotes() { + return this.upvotes; + } + + public boolean getWindows() { + return this.windows; + } + + public boolean getMac() { + return this.mac; + } + + public boolean getLinux() { + return this.linux; + } + + public Game clone() { + Game cloned = new Game(); + cloned.name = this.name; + cloned.owners = this.owners; + cloned.website = this.website; + cloned.developers = this.developers; + cloned.languages = this.languages; + cloned.genres = this.genres; + cloned.release_date = this.release_date; + cloned.app_id = this.app_id; + cloned.age = this.age; + cloned.dlcs = this.dlcs; + cloned.avg_playtime = this.avg_playtime; + cloned.price = this.price; + cloned.upvotes = this.upvotes; + cloned.windows = this.windows; + cloned.mac = this.mac; + cloned.linux = this.linux; + return cloned; + } + + public void ler(String line) { + char c_search; + int index = 0, atr_index = 0; + + // ---------------------------------- // + // Find "AppID" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.app_id = Integer.parseInt(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "Name" + if (line.charAt(atr_index) != ',') { + if (line.charAt(atr_index) == '\"') { + atr_index++; + c_search = '\"'; + } else + c_search = ','; + while (true) { + index++; + if (line.charAt(index) == c_search) { + this.name = line.substring(atr_index, index); + if (c_search == ',') + index++; + else if (c_search == '\"') + index += 2; + atr_index = index; + break; + } + } + } else + atr_index = ++index; + + // ---------------------------------- // + // Find release date + if (line.charAt(atr_index) != ',') { + SimpleDateFormat df; + if (line.charAt(atr_index) == '\"') { + df = new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH); + atr_index++; + c_search = '\"'; + } else { + df = new SimpleDateFormat("MMM yyyy", Locale.ENGLISH); + c_search = ','; + } + while (true) { + index++; + if (line.charAt(index) == c_search) { + try { + this.release_date = df.parse(line.substring(atr_index, index)); + } catch (java.text.ParseException e) { + e.printStackTrace(); + } + if (c_search == ',') + index++; + else if (c_search == '\"') + index += 2; + atr_index = index; + break; + } + } + } else + atr_index = ++index; + + // ---------------------------------- // + // Find "Owners" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.owners = line.substring(atr_index, index); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "Age" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.age = Integer.parseInt(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "Price" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.price = Float.parseFloat(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "DLCs" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.dlcs = Integer.parseInt(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "Languages" + while (true) { + index++; + if (line.charAt(index) == ']') { + index++; + if (line.charAt(index) == ',') + index++; + else if (line.charAt(index) == '\"') + index += 2; + atr_index = index; + break; + } else if (line.charAt(index) == '\'') { + int wordStart = index + 1; + while (true) { + index++; + if (line.charAt(index) == '\'') { + this.languages.add(line.substring(wordStart, index)); + break; + } + } + } + } + + // ---------------------------------- // + // Find "Website" + if (line.charAt(atr_index) != ',') { + if (line.charAt(atr_index) == '\"') { + atr_index++; + c_search = '\"'; + } else + c_search = ','; + + while (true) { + index++; + if (line.charAt(index) == c_search) { + this.website = line.substring(atr_index, index); + atr_index = ++index; + break; + } + } + } else + atr_index = ++index; + + // ---------------------------------- // + + // Find "Windows" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.windows = Boolean.parseBoolean(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // Find "Mac" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.mac = Boolean.parseBoolean(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // Find "Linux" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.linux = Boolean.parseBoolean(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "Upvotes" + int positives, negatives; + while (true) { + index++; + if (line.charAt(index) == ',') { + positives = Integer.parseInt(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + while (true) { + index++; + if (line.charAt(index) == ',') { + negatives = Integer.parseInt(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + this.upvotes = (float) (positives * 100) / (float) (positives + negatives); + + // ---------------------------------- // + // Find "AVG Playtime" + while (true) { + index++; + if (line.charAt(index) == ',') { + this.avg_playtime = Integer.parseInt(line.substring(atr_index, index)); + atr_index = ++index; + break; + } + } + + // ---------------------------------- // + // Find "Developers" + if (line.charAt(atr_index) != ',') { + if (line.charAt(atr_index) == '\"') { + atr_index++; + c_search = '\"'; + } else + c_search = ','; + while (true) { + index++; + if (line.charAt(index) == c_search) { + this.developers = line.substring(atr_index, index); + atr_index = ++index; + break; + } + } + } else + atr_index = ++index; + // ---------------------------------- // + + // Find "Genres" + if (index < line.length() - 1) { + if (line.charAt(index) == ',') + atr_index = ++index; + if (line.charAt(atr_index) == '\"') { + atr_index++; + while (true) { + index++; + if (line.charAt(index) == ',') { + this.genres.add(line.substring(atr_index, index)); + atr_index = ++index; + } else if (line.charAt(index) == '\"') { + this.genres.add(line.substring(atr_index, line.length() - 1)); + break; + } + } + } else + this.genres.add(line.substring(atr_index, line.length())); + } + } + + public void imprimir() { + String avg_pt = null; + if (this.avg_playtime == 0) + avg_pt = "null "; + else if (this.avg_playtime < 60) + avg_pt = this.avg_playtime + "m "; + else { + if (this.avg_playtime % 60 == 0) + avg_pt = this.avg_playtime / 60 + "h "; + else + avg_pt = (this.avg_playtime / 60) + "h " + (this.avg_playtime % 60) + "m "; + } + + DecimalFormat df = new DecimalFormat("##"); + System.out.println(this.app_id + " " + this.name + " " + default_dateFormat.format(this.release_date) + " " + + this.owners + " " + this.age + " " + String.format("%.2f", this.price) + " " + this.dlcs + " " + + this.languages + " " + this.website + " " + this.windows + " " + this.mac + " " + this.linux + " " + + (Float.isNaN(this.upvotes) ? "0.0% " : df.format(this.upvotes) + "% ") + avg_pt + this.developers + + " " + this.genres); + } +} \ No newline at end of file