From 5928464304e9adaa6f665355e2a0d225866b01d3 Mon Sep 17 00:00:00 2001 From: Jiri Karlik Date: Fri, 9 Aug 2024 19:43:54 +0200 Subject: [PATCH] Transfer to Gitea --- Lab0/scratch/Scratch Project.sb3 | Bin 0 -> 6034 bytes Lab1/credit/credit.c | 135 +++++++++++ Lab1/hello/hello.c | 9 + Lab1/mario/mario.c | 53 +++++ Lab1/population/population.c | 34 +++ Lab2/readability/readability.c | 54 +++++ Lab2/scrabble/scrabble.c | 53 +++++ Lab2/substitution/substitution.c | 96 ++++++++ Lab3/plurality/plurality.c | 111 +++++++++ Lab3/runoff/runoff.c | 240 +++++++++++++++++++ Lab3/sort/answers.txt | 12 + Lab4/filter/helpers.c | 152 ++++++++++++ Lab4/recover/recover.c | 66 ++++++ Lab4/volume/volume.c | 52 +++++ Lab5/inheritance/inheritance.c | 127 +++++++++++ Lab5/speller/dictionary.c | 151 ++++++++++++ Lab6/dna/dna.py | 60 +++++ Lab6/sentimental/credit.py | 66 ++++++ Lab6/sentimental/hello.py | 5 + Lab6/sentimental/mario.py | 31 +++ Lab6/sentimental/readability.py | 33 +++ Lab6/worldcup/tournament.py | 72 ++++++ Lab7/fiftyville/answers.txt | 3 + Lab7/fiftyville/log.sql | 61 +++++ Lab7/movies/1.sql | 1 + Lab7/movies/10.sql | 3 + Lab7/movies/11.sql | 7 + Lab7/movies/12.sql | 7 + Lab7/movies/13.sql | 7 + Lab7/movies/2.sql | 1 + Lab7/movies/3.sql | 1 + Lab7/movies/4.sql | 1 + Lab7/movies/5.sql | 1 + Lab7/movies/6.sql | 3 + Lab7/movies/7.sql | 4 + Lab7/movies/8.sql | 3 + Lab7/movies/9.sql | 4 + Lab7/songs/1.sql | 1 + Lab7/songs/2.sql | 1 + Lab7/songs/3.sql | 1 + Lab7/songs/4.sql | 1 + Lab7/songs/5.sql | 1 + Lab7/songs/6.sql | 2 + Lab7/songs/7.sql | 1 + Lab7/songs/8.sql | 1 + Lab8/homepage/about.html | 71 ++++++ Lab8/homepage/contact.html | 84 +++++++ Lab8/homepage/index.html | 55 +++++ Lab8/homepage/interests.html | 68 ++++++ Lab8/homepage/styles.css | 28 +++ Lab8/trivia/index.html | 81 +++++++ Lab8/trivia/styles.css | 62 +++++ Lab9/birthdays/application.py | 33 +++ Lab9/birthdays/birthdays.db | Bin 0 -> 8192 bytes Lab9/birthdays/static/styles.css | 83 +++++++ Lab9/birthdays/templates/index.html | 50 ++++ Lab9/finance/application.py | 330 +++++++++++++++++++++++++++ Lab9/finance/finance.db | Bin 0 -> 24576 bytes Lab9/finance/helpers.py | 64 ++++++ Lab9/finance/requirements.txt | 4 + Lab9/finance/static/favicon.ico | Bin 0 -> 5558 bytes Lab9/finance/static/styles.css | 47 ++++ Lab9/finance/templates/apology.html | 9 + Lab9/finance/templates/buy.html | 17 ++ Lab9/finance/templates/history.html | 28 +++ Lab9/finance/templates/index.html | 39 ++++ Lab9/finance/templates/layout.html | 71 ++++++ Lab9/finance/templates/login.html | 17 ++ Lab9/finance/templates/quote.html | 14 ++ Lab9/finance/templates/quoted.html | 9 + Lab9/finance/templates/register.html | 20 ++ Lab9/finance/templates/sell.html | 22 ++ 72 files changed, 3034 insertions(+) create mode 100644 Lab0/scratch/Scratch Project.sb3 create mode 100644 Lab1/credit/credit.c create mode 100644 Lab1/hello/hello.c create mode 100644 Lab1/mario/mario.c create mode 100644 Lab1/population/population.c create mode 100644 Lab2/readability/readability.c create mode 100644 Lab2/scrabble/scrabble.c create mode 100644 Lab2/substitution/substitution.c create mode 100644 Lab3/plurality/plurality.c create mode 100644 Lab3/runoff/runoff.c create mode 100644 Lab3/sort/answers.txt create mode 100644 Lab4/filter/helpers.c create mode 100644 Lab4/recover/recover.c create mode 100644 Lab4/volume/volume.c create mode 100644 Lab5/inheritance/inheritance.c create mode 100644 Lab5/speller/dictionary.c create mode 100644 Lab6/dna/dna.py create mode 100644 Lab6/sentimental/credit.py create mode 100644 Lab6/sentimental/hello.py create mode 100644 Lab6/sentimental/mario.py create mode 100644 Lab6/sentimental/readability.py create mode 100644 Lab6/worldcup/tournament.py create mode 100644 Lab7/fiftyville/answers.txt create mode 100644 Lab7/fiftyville/log.sql create mode 100644 Lab7/movies/1.sql create mode 100644 Lab7/movies/10.sql create mode 100644 Lab7/movies/11.sql create mode 100644 Lab7/movies/12.sql create mode 100644 Lab7/movies/13.sql create mode 100644 Lab7/movies/2.sql create mode 100644 Lab7/movies/3.sql create mode 100644 Lab7/movies/4.sql create mode 100644 Lab7/movies/5.sql create mode 100644 Lab7/movies/6.sql create mode 100644 Lab7/movies/7.sql create mode 100644 Lab7/movies/8.sql create mode 100644 Lab7/movies/9.sql create mode 100644 Lab7/songs/1.sql create mode 100644 Lab7/songs/2.sql create mode 100644 Lab7/songs/3.sql create mode 100644 Lab7/songs/4.sql create mode 100644 Lab7/songs/5.sql create mode 100644 Lab7/songs/6.sql create mode 100644 Lab7/songs/7.sql create mode 100644 Lab7/songs/8.sql create mode 100644 Lab8/homepage/about.html create mode 100644 Lab8/homepage/contact.html create mode 100644 Lab8/homepage/index.html create mode 100644 Lab8/homepage/interests.html create mode 100644 Lab8/homepage/styles.css create mode 100644 Lab8/trivia/index.html create mode 100644 Lab8/trivia/styles.css create mode 100644 Lab9/birthdays/application.py create mode 100644 Lab9/birthdays/birthdays.db create mode 100644 Lab9/birthdays/static/styles.css create mode 100644 Lab9/birthdays/templates/index.html create mode 100644 Lab9/finance/application.py create mode 100644 Lab9/finance/finance.db create mode 100644 Lab9/finance/helpers.py create mode 100644 Lab9/finance/requirements.txt create mode 100644 Lab9/finance/static/favicon.ico create mode 100644 Lab9/finance/static/styles.css create mode 100644 Lab9/finance/templates/apology.html create mode 100644 Lab9/finance/templates/buy.html create mode 100644 Lab9/finance/templates/history.html create mode 100644 Lab9/finance/templates/index.html create mode 100644 Lab9/finance/templates/layout.html create mode 100644 Lab9/finance/templates/login.html create mode 100644 Lab9/finance/templates/quote.html create mode 100644 Lab9/finance/templates/quoted.html create mode 100644 Lab9/finance/templates/register.html create mode 100644 Lab9/finance/templates/sell.html diff --git a/Lab0/scratch/Scratch Project.sb3 b/Lab0/scratch/Scratch Project.sb3 new file mode 100644 index 0000000000000000000000000000000000000000..db14303003a43d6882c5f561456c06c06f128732 GIT binary patch literal 6034 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 literal 0 HcmV?d00001 diff --git a/Lab1/credit/credit.c b/Lab1/credit/credit.c new file mode 100644 index 0000000..9514cf9 --- /dev/null +++ b/Lab1/credit/credit.c @@ -0,0 +1,135 @@ +#include +#include +#include + +void invalid(void); +void card_check(long user_input, int nDigits); +int start_digits(long); +bool luhn_algo(long user_input, int nDigits); + +int main(void) +{ + //takes user input and check if the value is positive number + long user_input = get_long("Enter credit card number:"); + if (user_input < 1) + { + invalid(); + } + //calculates the lenght of input and if correct, continues with card_check + int nDigits = floor(log10(user_input)) + 1; + if (nDigits == 15 || nDigits == 13 || nDigits == 16) + { + card_check(user_input, nDigits); + } + else + { + invalid(); + } +} + +//gives invalid output message to user +void invalid(void) +{ + printf("INVALID\n"); +} + +int start_digits(long user_input) +{ + while (user_input >= 100) + { + user_input /= 10; + } + return user_input; +} + +//luhn algoritm to check validity of card number +bool luhn_algo(long user_input, int nDigits) +{ + //creates array and sets first value to last digit of user input number + int n[nDigits]; + n[0] = user_input % 10; + //loops through the remaining digits and stores them in the array as well (from back to the beginning) + int i = 1; + while (user_input >= 1) + { + user_input /= 10; + n[i] = user_input % 10; + i++; + } + //creates another array and fills it with every other digit multiplied by 2, starting at 2nd to last position + int check_sum = 0; + int check_digits[nDigits / 2]; + int j = 0; + for (i = 1; i < nDigits; i += 2) + { + check_digits[j] = n[i] * 2; + j++; + } + //creates sum of digits from array created above + for (i = 0; i < nDigits / 2; i++) + { + //neccessary check for values with more than 1 digit, to create sum of their digits + if (check_digits[i] > 9) + { + check_sum = check_sum + check_digits[i] % 10; + while (check_digits[i] > 9) + { + check_digits[i] /= 10; + } + check_sum = check_sum + check_digits[i]; + + } + else + { + check_sum = check_digits[i] + check_sum; + } + } + //adds sum of all digits that were not multiplied by 2 previously + for (i = 0; i < nDigits; i += 2) + { + check_sum = n[i] + check_sum; + } + //checks if the last number of final check_sum is 0 and returns true or false + if (check_sum % 10 == 0) + { + return true; + } + else + { + invalid(); + return false; + } + +} + +//checks for the beginning numbers and branches into correct card provider +void card_check(long user_input, int nDigits) +{ + int beginning = start_digits(user_input); + if (beginning == 34 || beginning == 37) + { + //check validity of card by using luhn alghoritm + if (luhn_algo(user_input, nDigits)) + { + printf("AMEX\n"); + } + } + else if (beginning > 39 && beginning < 50) + { + if (luhn_algo(user_input, nDigits)) + { + printf("VISA\n"); + } + } + else if (beginning > 50 && beginning < 56) + { + if (luhn_algo(user_input, nDigits)) + { + printf("MASTERCARD\n"); + } + } + else + { + invalid(); + } +} diff --git a/Lab1/hello/hello.c b/Lab1/hello/hello.c new file mode 100644 index 0000000..0b0a4d0 --- /dev/null +++ b/Lab1/hello/hello.c @@ -0,0 +1,9 @@ +#include +#include + +int main(void) +{ + //asks user for name and says Hello + his name + string name = get_string("What is your name?\n"); + printf("hello, %s\n", name); +} \ No newline at end of file diff --git a/Lab1/mario/mario.c b/Lab1/mario/mario.c new file mode 100644 index 0000000..96f52c6 --- /dev/null +++ b/Lab1/mario/mario.c @@ -0,0 +1,53 @@ +#include +#include + +//prototype declaration +int user_input(void); +void spacing(int height); + + +int main(void) +{ + int height = user_input() + 1; + //creates a pyramid + for (int i = 1; i < height; i++) + { + spacing(height - i); + //creates first left side, than space, than right side of pyramid + for (int k = 1; k < 3; k++) + { + for (int j = 1; j < i + 1; j++) + { + printf("#"); + } + if (k==1) + { + printf(" "); + } + } + printf("\n"); + } +} + +//get positive integer from user +int user_input(void) +{ + int height; + do + { + height = get_int("Height: "); + } + while (height < 1 || height > 8); + return height; + +} + +// creates spacing on the left side of the pyramid +void spacing(int height) +{ + for (int i = 1; i < height; i++) + { + printf(" "); + } + +} \ No newline at end of file diff --git a/Lab1/population/population.c b/Lab1/population/population.c new file mode 100644 index 0000000..9f9f46c --- /dev/null +++ b/Lab1/population/population.c @@ -0,0 +1,34 @@ +#include +#include + +int main(void) +{ + // TODO: Prompt for start size + int start_size = 0; + int end_size = 0; + while (start_size < 9) + { + start_size = get_int("Enter start size.\n"); + } + // TODO: Prompt for end size + while (end_size < start_size) + { + end_size = get_int("Enter end size.\n"); + } + // TODO: Calculate number of years until we reach threshold + int current_size = start_size; + int born = 0; + int died = 0; + int years = 0; + + while (current_size < end_size) + { + born = current_size / 3; + died = current_size / 4; + current_size = current_size + born - died; + years++; + } + // TODO: Print number of years + + printf("Years: %i\n", years); +} \ No newline at end of file diff --git a/Lab2/readability/readability.c b/Lab2/readability/readability.c new file mode 100644 index 0000000..fdafbb2 --- /dev/null +++ b/Lab2/readability/readability.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +int main(void) +{ + //setting initial counters, words start at 1 due to last word not having space behind. + long letters = 0; + long words = 1; + long sentences = 0; + + //getting string from user and looping through each character + string user_input = get_string("Text:"); + for (int i = 0, n = strlen(user_input); i < n; i++) + { + //counting letters based on ascii values from a-z & A-Z + int ascii_code = (int) user_input[i]; + if (ascii_code >= 65 && ascii_code <= 122) + { + letters++; + } + // counting words based on ascii value for space + else if (ascii_code == 32) + { + words++; + } + //coounting sentences based on ascii value for ".","!","?" + else if (ascii_code == 33 || ascii_code == 63 || ascii_code == 46) + { + sentences++; + } + } + + //calculating Coleman-Liau index + float l = (float)letters / words * 100; + float s = (float)sentences / words * 100; + long index = round(0.0588 * l - 0.296 * s - 15.8); + + //writing out readabality grade based on index value + if (index < 1) + { + printf("Before Grade 1\n"); + } + else if (index >= 16) + { + printf("Grade 16+\n"); + } + else + { + printf("Grade %li\n", index); + } + +} \ No newline at end of file diff --git a/Lab2/scrabble/scrabble.c b/Lab2/scrabble/scrabble.c new file mode 100644 index 0000000..4cd1a22 --- /dev/null +++ b/Lab2/scrabble/scrabble.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +// Points assigned to each letter of the alphabet +int POINTS[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10}; + +int compute_score(string word); + +int main(void) +{ + // Get input words from both players + string word1 = get_string("Player 1: "); + string word2 = get_string("Player 2: "); + + // Score both words + int score1 = compute_score(word1); + int score2 = compute_score(word2); + + // TODO: Print the winner + if (score1 > score2) + { + printf("Player 1 wins!\n"); + } + else if (score2 > score1) + { + printf("Player 2 wins!\n"); + } + else + { + printf("Tie!\n"); + } +} + +int compute_score(string word) +{ + // TODO: Compute and return score for string + int word_len = strlen(word); + int score = 0; + int pos = 0; + const int ASCII_A = 65; + for (int i = 0; i < word_len; i++) + { + word[i] = toupper(word[i]); + if (word[i] >= 'A' && word[i] <= 'Z') + { + pos = word[i] - ASCII_A; + score = score + POINTS[pos]; + } + } + return score; +} \ No newline at end of file diff --git a/Lab2/substitution/substitution.c b/Lab2/substitution/substitution.c new file mode 100644 index 0000000..522e78a --- /dev/null +++ b/Lab2/substitution/substitution.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include + +int wrong_key(void); +string key_check(string argv[], int n, string key); +string encrypt(string user_input, string key, int n); + + +int main(int argc, string argv[]) +{ + string key = NULL; + int n = 0; + //check if user used correct number of arguments + if (argc == 2) + { + key = argv[1]; + n = strlen(key); + //check correctness of key and returns it back in uppercase + key = key_check(argv, n, key); + } + else + { + wrong_key(); + } + string user_input = get_string("plaintext:"); + string encrypted_string = encrypt(user_input, key, n); + printf("ciphertext: %s\n", encrypted_string); +} + +//give user hint that he used wrong arguments,exit and return error code +int wrong_key(void) +{ + printf("Usage: ./substition key \n"); + printf("Key must containt 26 unique alphabetical characters. \n"); + exit(1); +} + + +string key_check(string argv[], int n, string key) +{ + //check if the key has 26 characters + if (n != 26) + { + wrong_key(); + } + //check if each character in key is alphabetical character and convert all to uppercase + for (int i = 0; i < n; i++) + { + if ((key[i] >= 'a' && key[i] <= 'z') || (key[i] >= 'A' && key[i] <= 'Z')) + { + key[i] = toupper(key[i]); + } + else + { + wrong_key(); + } + //check if character is not duplicated inside key + for (int j = 0; j < i; j++) + { + if (key[i] == key[j]) + { + wrong_key(); + } + } + + } + return key; +} + +string encrypt(string user_input, string key, int n) +{ + //check user input length, create encrypted_string and copy user input inside + int user_length = strlen(user_input); + string encrypted_string = user_input; + //iterate over each char in user input and check if it's a letter + for (int i = 0; i < user_length; i++) + { + //if letter is found, substract ascii value for "a" to get letter position in key, encrypt this letter in encrypted string + if (user_input[i] >= 'a' && user_input[i] <= 'z') + { + int j = user_input[i] - 97; + //we use tolower to keep correct uppercase and lowercase as inputed by user + encrypted_string[i] = tolower(key[j]); + } + //if letter is found, substract ascii value for "A" to get letter position in key, encrypt this letter in encrypted string + else if (user_input[i] >= 'A' && user_input[i] <= 'Z') + { + int j = user_input[i] - 65; + encrypted_string[i] = key[j]; + } + } + return encrypted_string; +} \ No newline at end of file diff --git a/Lab3/plurality/plurality.c b/Lab3/plurality/plurality.c new file mode 100644 index 0000000..f6017b9 --- /dev/null +++ b/Lab3/plurality/plurality.c @@ -0,0 +1,111 @@ +#include +#include +#include + +// Max number of candidates +#define MAX 9 + +// Candidates have name and vote count +typedef struct +{ + string name; + int votes; +} +candidate; + +// Array of candidates +candidate candidates[MAX]; + +// Number of candidates +int candidate_count; + +// Function prototypes +bool vote(string name); +void print_winner(void); + +int main(int argc, string argv[]) +{ + // Check for invalid usage + if (argc < 2) + { + printf("Usage: plurality [candidate ...]\n"); + return 1; + } + + // Populate array of candidates + candidate_count = argc - 1; + if (candidate_count > MAX) + { + printf("Maximum number of candidates is %i\n", MAX); + return 2; + } + for (int i = 0; i < candidate_count; i++) + { + candidates[i].name = argv[i + 1]; + candidates[i].votes = 0; + } + + int voter_count = get_int("Number of voters: "); + + // Loop over all voters + for (int i = 0; i < voter_count; i++) + { + string name = get_string("Vote: "); + + // Check for invalid vote + if (!vote(name)) + { + printf("Invalid vote.\n"); + } + } + + // Display winner of election + print_winner(); +} + +// Update vote totals given a new vote +bool vote(string name) +{ + for (int i = 0; i < candidate_count; i++) + { + if (strcmp(candidates[i].name, name) == 0) + { + candidates[i].votes += 1; + return true; + } + } + return false; +} + +// Print the winner (or winners) of the election +void print_winner(void) +{ + //array to store candidates with highest votes + int winner_index[candidate_count]; + winner_index[0] = 0; + int j = 0; + //check votes of all candidates + for (int i = 1; i < candidate_count; i++) + { + //store highest seen vote candidate index + if (candidates[i].votes > candidates[winner_index[j]].votes) + { + j = 0; + winner_index[j] = i; + } + //when more candidates have the smae amount of votes, save all of them + else if (candidates[i].votes == candidates[winner_index[j]].votes) + { + j++; + winner_index[j] = i; + } + } + //prints all winners, 1 per line + for (int i = 0; i <= j; i++) + { + printf("%s\n", candidates[winner_index[i]].name); + } + + return; +} + diff --git a/Lab3/runoff/runoff.c b/Lab3/runoff/runoff.c new file mode 100644 index 0000000..262271f --- /dev/null +++ b/Lab3/runoff/runoff.c @@ -0,0 +1,240 @@ +#include +#include +#include + +// Max voters and candidates +#define MAX_VOTERS 100 +#define MAX_CANDIDATES 9 + +// preferences[i][j] is jth preference for voter i +int preferences[MAX_VOTERS][MAX_CANDIDATES]; + +// Candidates have name, vote count, eliminated status +typedef struct +{ + string name; + int votes; + bool eliminated; +} +candidate; + +// Array of candidates +candidate candidates[MAX_CANDIDATES]; + +// Numbers of voters and candidates +int voter_count; +int candidate_count; + +// Function prototypes +bool vote(int voter, int rank, string name); +void tabulate(void); +bool print_winner(void); +int find_min(void); +bool is_tie(int min); +void eliminate(int min); + +int main(int argc, string argv[]) +{ + // Check for invalid usage + if (argc < 2) + { + printf("Usage: runoff [candidate ...]\n"); + return 1; + } + + // Populate array of candidates + candidate_count = argc - 1; + if (candidate_count > MAX_CANDIDATES) + { + printf("Maximum number of candidates is %i\n", MAX_CANDIDATES); + return 2; + } + for (int i = 0; i < candidate_count; i++) + { + candidates[i].name = argv[i + 1]; + candidates[i].votes = 0; + candidates[i].eliminated = false; + } + + voter_count = get_int("Number of voters: "); + if (voter_count > MAX_VOTERS) + { + printf("Maximum number of voters is %i\n", MAX_VOTERS); + return 3; + } + + // Keep querying for votes + for (int i = 0; i < voter_count; i++) + { + + // Query for each rank + for (int j = 0; j < candidate_count; j++) + { + string name = get_string("Rank %i: ", j + 1); + + // Record vote, unless it's invalid + if (!vote(i, j, name)) + { + printf("Invalid vote.\n"); + return 4; + } + } + + printf("\n"); + } + + // Keep holding runoffs until winner exists + while (true) + { + // Calculate votes given remaining candidates + tabulate(); + + // Check if election has been won + bool won = print_winner(); + if (won) + { + break; + } + + // Eliminate last-place candidates + int min = find_min(); + bool tie = is_tie(min); + + // If tie, everyone wins + if (tie) + { + for (int i = 0; i < candidate_count; i++) + { + if (!candidates[i].eliminated) + { + printf("%s\n", candidates[i].name); + } + } + break; + } + + // Eliminate anyone with minimum number of votes + eliminate(min); + + // Reset vote counts back to zero + for (int i = 0; i < candidate_count; i++) + { + candidates[i].votes = 0; + } + } + return 0; +} + +// Record preference if vote is valid +bool vote(int voter, int rank, string name) +{ + // TODO + for (int i = 0; i < candidate_count; i++) + { + if (strcmp(name, candidates[i].name) == 0) + { + preferences[voter][rank] = i; + return true; + } + } + return false; +} + +// Tabulate votes for non-eliminated candidates +void tabulate(void) +{ + // TODO + for (int j = 0; j < voter_count; j++) + { + for (int i = 0; i < candidate_count; i++) + { + if (candidates[preferences[j][i]].eliminated == false) + { + candidates[preferences[j][i]].votes++; + break; + } + } + } + + return; +} + +// Print the winner of the election, if there is one +bool print_winner(void) +{ + //TODO + //itera + int winner = -1; + bool tie = false; + for (int i = 0; i < candidate_count; i++) + { + if (candidates[i].eliminated == false && candidates[i].votes > voter_count / 2) + { + if (winner == -1) + { + winner = i; + } + else + { + tie = true; + } + } + } + + if (winner > -1 && tie == false) + { + printf("%s\n", candidates[winner].name); + return true; + } + return false; +} + +// Return the minimum number of votes any remaining candidate has +int find_min(void) +{ + // iterating over all candidate votes + int min_votes = -1; + for (int i = 0; i < candidate_count; i++) + { + //checking if this is the first not-eliminated candidate and setting initial lowest votes value + if (min_votes == -1 && candidates[i].eliminated == false) + { + min_votes = i; + } + //comparing previously seen min votes vs current candidate + if (candidates[i].votes < candidates[min_votes].votes && candidates[i].eliminated == false) + { + min_votes = i; + } + } + //returns minimum number of votes + return candidates[min_votes].votes; +} + +// Return true if the election is tied between all candidates, false otherwise +bool is_tie(int min) +{ + //iterating through candidate votes, when candidate votes are bigger than min return false, tie is not possible + for (int i = 0; i < candidate_count; i++) + { + if (candidates[i].votes > min) + { + return false; + } + } + return true; +} + +// Eliminate the candidate (or candidates) in last place +void eliminate(int min) +{ + // iterating over all candidates and comparing who has the min votes, than setting his eliminated state to true + for (int i = 0; i < candidate_count; i++) + { + if (candidates[i].votes == min) + { + candidates[i].eliminated = true; + } + } + return; +} diff --git a/Lab3/sort/answers.txt b/Lab3/sort/answers.txt new file mode 100644 index 0000000..223fac2 --- /dev/null +++ b/Lab3/sort/answers.txt @@ -0,0 +1,12 @@ +sort1 uses: bubble sort + +How do you know?: has shorter runtime for sorted list than sort3 and also longer for reversed + +sort2 uses: merge sort + +How do you know?: fastest for random list ... merge sort has the best O + +sort3 uses: selection sort + +How do you know?: the opposite behavior to explained in sort1 +submit50 cs50/labs/2021/x/sort \ No newline at end of file diff --git a/Lab4/filter/helpers.c b/Lab4/filter/helpers.c new file mode 100644 index 0000000..a24658c --- /dev/null +++ b/Lab4/filter/helpers.c @@ -0,0 +1,152 @@ +#include "helpers.h" +#include "math.h" +#include +#include + +int pix_round(double input); + +// Convert image to grayscale +void grayscale(int height, int width, RGBTRIPLE image[height][width]) +{ + double avg; + //loop through all rows + for (int i = 0; i < height; i++) + { + //loop through all columns + for (int j = 0; j < width; j++) + { + //calculate average from RGB and set RGB to it + avg = (image[i][j].rgbtBlue + image[i][j].rgbtGreen + image[i][j].rgbtRed) / 3.0; + avg = pix_round(round(avg)); + image[i][j].rgbtBlue = avg; + image[i][j].rgbtGreen = avg; + image[i][j].rgbtRed = avg; + } + } + return; +} + +// Convert image to sepia +void sepia(int height, int width, RGBTRIPLE image[height][width]) +{ + //loop through all rows + for (int i = 0; i < height; i++) + { + //loop through all columns + for (int j = 0; j < width; j++) + { + //save original RGB values + int originalBlue = image[i][j].rgbtBlue; + int originalGreen = image[i][j].rgbtGreen; + int originalRed = image[i][j].rgbtRed; + + //calculate sepia RGB values + double sepiaRed = 0.393 * originalRed + 0.769 * originalGreen + 0.189 * originalBlue; + double sepiaGreen = 0.349 * originalRed + 0.686 * originalGreen + 0.168 * originalBlue; + double sepiaBlue = 0.272 * originalRed + 0.534 * originalGreen + 0.131 * originalBlue; + + //round sepia values + sepiaBlue = pix_round(round(sepiaBlue)); + sepiaGreen = pix_round(round(sepiaGreen)); + sepiaRed = pix_round(round(sepiaRed)); + + //change image to sepia RGB + image[i][j].rgbtBlue = sepiaBlue; + image[i][j].rgbtGreen = sepiaGreen; + image[i][j].rgbtRed = sepiaRed; + } + } + return; +} + +// Reflect image horizontally +void reflect(int height, int width, RGBTRIPLE image[height][width]) +{ + //loop through all rows + for (int i = 0; i < height; i++) + { + //loop through columns to middle + for (int j = 0; j < (width / 2); j++) + { + //create buffer to as temp store for RGB value, switch from right to left + RGBTRIPLE buffer = image[i][j]; + image[i][j] = image[i][width - (j + 1)]; + image[i][width - (j + 1)] = buffer; + } + } + + return; +} + +// Blur image +void blur(int height, int width, RGBTRIPLE image[height][width]) +{ + RGBTRIPLE buffer[height][width]; + // loops through all rows + for (int i = 0; i < height; i++) + { + //loops through all columns + for (int j = 0; j < width; j++) + { + //sets initial variable values to zero + double avgGreen = 0; + double avgBlue = 0; + double avgRed = 0; + int counter = 0; + + //loop through all row offsets + for (int row_offset = -1; row_offset <= 1; row_offset++) + { + //loop through all col offsets + for (int col_offset = -1; col_offset <= 1; col_offset++) + { + int y = i + row_offset; + int x = j + col_offset; + // checks if offseted values are within the image coordinates + if (y >= 0 && y < height && x >= 0 && x < width) + { + // adds current RGB values to avgsum + increases counter + avgGreen = avgGreen + image[y][x].rgbtGreen; + avgBlue = avgBlue + image[y][x].rgbtBlue; + avgRed = avgRed + image[y][x].rgbtRed; + counter++; + } + } + } + // calculates and rounds avg RGB values + avgGreen = pix_round(round(avgGreen / counter)); + avgBlue = pix_round(round(avgBlue / counter)); + avgRed = pix_round(round(avgRed / counter)); + + //sets new RGB values to buffer + buffer[i][j].rgbtBlue = avgBlue; + buffer[i][j].rgbtGreen = avgGreen; + buffer[i][j].rgbtRed = avgRed; + } + + } + //copying data from buffer back to image + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + image[i][j].rgbtBlue = buffer[i][j].rgbtBlue; + image[i][j].rgbtGreen = buffer[i][j].rgbtGreen; + image[i][j].rgbtRed = buffer[i][j].rgbtRed; + } + } + return; +} + +int pix_round(double input) +{ + if (input >= 255) + { + input = 255; + } + else if (input <= 0) + { + input = 0; + } + return input; +} \ No newline at end of file diff --git a/Lab4/recover/recover.c b/Lab4/recover/recover.c new file mode 100644 index 0000000..8bd88d5 --- /dev/null +++ b/Lab4/recover/recover.c @@ -0,0 +1,66 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + //check if user used correct arguments + if (argc != 2) + { + printf("Usage: ./recover image\n"); + return 1; + } + + typedef uint8_t BYTE; + + //initialize variables + BYTE buffer[512]; + FILE *file_output = NULL; + char filename[8]; + int counter = 0; + int img_opened = 0; + //open file and read into file_input + FILE *file_input = fopen(argv[1], "r"); + + //read data from file input to buffer in blocks of 512 B + while (fread(&buffer, 512, 1, file_input)) + { + //check if first bytes match with jpg format + if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) + { + //check if image was already found in previous loop + if (img_opened == 1) + { + fclose(file_output); + } + else + { + img_opened = 1; + } + + //write in filename name based on counter with at least 3 position + .jpg + sprintf(filename, "%.3i.jpg", counter); + // initialize file output with correct name + file_output = fopen(filename, "w"); + counter++; + } + //if image is opened, write 512 B block of data from buffer to file_output + if (img_opened == 1) + { + fwrite(&buffer, 512, 1, file_output); + } + } + + //close both input & output files if not used anymore + if (file_input == NULL) + { + fclose(file_input); + } + if (file_output == NULL) + { + fclose(file_output); + } + + + +} \ No newline at end of file diff --git a/Lab4/volume/volume.c b/Lab4/volume/volume.c new file mode 100644 index 0000000..b01dbe7 --- /dev/null +++ b/Lab4/volume/volume.c @@ -0,0 +1,52 @@ +// Modifies the volume of an audio file + +#include +#include +#include + +// Number of bytes in .wav header +const int HEADER_SIZE = 44; + +int main(int argc, char *argv[]) +{ + // Check command-line arguments + if (argc != 4) + { + printf("Usage: ./volume input.wav output.wav factor\n"); + return 1; + } + + // Open files and determine scaling factor + FILE *input = fopen(argv[1], "r"); + if (input == NULL) + { + printf("Could not open file.\n"); + return 1; + } + + FILE *output = fopen(argv[2], "w"); + if (output == NULL) + { + printf("Could not open file.\n"); + return 1; + } + + float factor = atof(argv[3]); + + // TODO: Copy header from input file to output file + uint8_t header[HEADER_SIZE]; + fread(header, HEADER_SIZE, 1, input); + fwrite(header, HEADER_SIZE, 1, output); + + // TODO: Read samples from input file and write updated data to output file + int16_t buffer; + while (fread(&buffer, sizeof(int16_t), 1, input)) + { + buffer *= factor; + fwrite(&buffer, sizeof(int16_t), 1, output); + } + + // Close files + fclose(input); + fclose(output); +} diff --git a/Lab5/inheritance/inheritance.c b/Lab5/inheritance/inheritance.c new file mode 100644 index 0000000..69b62b5 --- /dev/null +++ b/Lab5/inheritance/inheritance.c @@ -0,0 +1,127 @@ +// Simulate genetic inheritance of blood type + +#include +#include +#include +#include + +// Each person has two parents and two alleles +typedef struct person +{ + struct person *parents[2]; + char alleles[2]; +} +person; + +const int GENERATIONS = 3; +const int INDENT_LENGTH = 4; + +person *create_family(int generations); +void print_family(person *p, int generation); +void free_family(person *p); +char random_allele(); + +int main(void) +{ + // Seed random number generator + srand(time(0)); + + // Create a new family with three generations + person *p = create_family(GENERATIONS); + + // Print family tree of blood types + print_family(p, 0); + + // Free memory + free_family(p); +} + +// Create a new individual with `generations` +person *create_family(int generations) +{ + // TODO: Allocate memory for new person + person *p = malloc(sizeof(person)); + + // Generation with parent data + if (generations > 1) + { + // TODO: Recursively create blood type histories for parents + p->parents[0] = create_family(generations - 1); + p->parents[1] = create_family(generations - 1); + // TODO: Randomly assign child alleles based on parents + p->alleles[0] = p->parents[0]->alleles[rand() % 2]; + p->alleles[1] = p->parents[1]->alleles[rand() % 2]; + } + + // Generation without parent data + else + { + // TODO: Set parent pointers to NULL + p->parents[0] = NULL; + p->parents[1] = NULL; + + // TODO: Randomly assign alleles + + p->alleles[0] = random_allele(); + p->alleles[1] = random_allele(); + } + + // TODO: Return newly created person + return p; +} + +// Free `p` and all ancestors of `p`. +void free_family(person *p) +{ + // TODO: Handle base case + if (p == NULL) + { + return; + } + + // TODO: Free parents + + free_family(p->parents[0]); + free_family(p->parents[1]); + + // TODO: Free child + free(p); +} +// Print each family member and their alleles. +void print_family(person *p, int generation) +{ + // Handle base case + if (p == NULL) + { + return; + } + + // Print indentation + for (int i = 0; i < generation * INDENT_LENGTH; i++) + { + printf(" "); + } + + // Print person + printf("Generation %i, blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); + print_family(p->parents[0], generation + 1); + print_family(p->parents[1], generation + 1); +} + +// Randomly chooses a blood type allele. +char random_allele() +{ + int r = rand() % 3; + if (r == 0) + { + return 'A'; + } + else if (r == 1) + { + return 'B'; + } + else + { + return 'O'; + } +} diff --git a/Lab5/speller/dictionary.c b/Lab5/speller/dictionary.c new file mode 100644 index 0000000..a333b23 --- /dev/null +++ b/Lab5/speller/dictionary.c @@ -0,0 +1,151 @@ +// Implements a dictionary's functionality + +#include +#include "dictionary.h" +#include +#include +#include +#include + +// Represents a node in a hash table +typedef struct node +{ + char word[LENGTH + 1]; + struct node *next; +} +node; + +//initialize dictionary size +int counter = 0; +// Number of buckets in hash table +const unsigned int N = 1560; + +// Hash table +node *table[N]; + +// Returns true if word is in dictionary, else false +bool check(const char *word) +{ + // TODO + int word_len = strlen(word) + 1; + // convert to lowercase + char word_low[word_len]; + for (int i = 0; i < word_len; i++) + { + word_low[i] = tolower(word[i]); + } + + // convert word to hash value + int hash_val = hash(word_low); + + // create node containing linked list from hash value position in table + node *n = table[hash_val]; + + //loop through linked list untill end + while (n != NULL) + { + // return true if word matches with current node from linked list, if not go next node + if (strcmp(word_low, n->word) == 0) + { + return true; + } + n = n->next; + } + + // if word was not found in the linked list, return true, words is not in dict + return false; +} + +// Hashes word to a number +unsigned int hash(const char *word) +{ + // TODO + long sum = 0; + // create ASCII sum of all letters in word converted to lowercase + for (int i = 0; i < strlen(word); i++) + { + sum += tolower(word[i]); + + } + // returns remainder of sum / bucket number + return sum % N; +} + +// Loads dictionary into memory, returning true if successful, else false +bool load(const char *dictionary) +{ + // TODO + // Open dictionary file + FILE *dict_file = fopen(dictionary, "r"); + + // Check if null + if (dictionary == NULL) + { + printf("Unable to open %s\n", dictionary); + return false; + } + + //array to store newly found words + char new_word[LENGTH + 1]; + + // read dictionary strings one at a time + while (fscanf(dict_file, "%s", new_word) != EOF) + { + // create node for every word + node *n = malloc(sizeof(node)); + + // check if malloc worked, if not free memory + if (n == NULL) + { + unload(); + return false; + } + + // copy word to node + strcpy(n->word, new_word); + + //obtain hash value + int hash_val = hash(new_word); + + // set node next to correct place in table and than set table place to node + n->next = table[hash_val]; + table[hash_val] = n; + + //increase dict size for each loop + counter++; + } + + // close the file + fclose(dict_file); + + return true; +} + +// Returns number of words in dictionary if loaded, else 0 if not yet loaded +unsigned int size(void) +{ + // returns dictionary size + return counter; +} + +// Unloads dictionary from memory, returning true if successful, else false +bool unload(void) +{ + // TODO + //loop through all buckets + for (int i = 0; i <= N; i++) + { + // check and do until table is empty + while (table[i] != NULL) + { + //create temp node to store pointer to next table + node *tmp = table[i] ->next; + //free memory, set tmp pointer back to table and repeat untill all is free + free(table[i]); + table[i] = tmp; + } + } + + return true; +} + diff --git a/Lab6/dna/dna.py b/Lab6/dna/dna.py new file mode 100644 index 0000000..70d5488 --- /dev/null +++ b/Lab6/dna/dna.py @@ -0,0 +1,60 @@ +import csv +import sys + +# Ensure correct usage +if len(sys.argv) != 3: + sys.exit("Usage: python dna.py database.csv sequence.txt") + +# setting array with search STRs +str_search_big = ["AGATC", "TTTTTTCT", "AATG", "TCTAG", "GATA", "TATC", "GAAA", "TCTG"] +str_search_small = ["AGATC", "AATG", "TATC"] + +if sys.argv[1].count("small") > 0: + str_search = str_search_small +else: + str_search = str_search_big + +search_len = len(str_search) + + +# searches for longest repeated STR sequence +def str_repeat(seq, dna_str, dbcount): + match_count = 0 + pattern = dna_str + while dna_str in seq: + match_count += 1 + dna_str += pattern + # if longest sequence doesn't match with DB, remove this person from match list + if match_count != int(dbcount): + try: + match.remove(key["name"]) + except: + return + + +# initialiaze variables +filename = sys.argv[1] +database = [] +match = [] + +# Read database into memory from file +with open(filename) as file: + reader = csv.DictReader(file) + for row in reader: + database.append(row) + # populate match list with all possible names + match.append(row["name"]) +# get sequence string from txt +sequence = open(sys.argv[2], "r") +sequence = sequence.read() +# loop through all searchable STRs +for i in range(search_len): + # loop through all database entries + for key in database: + str_repeat(sequence, str_search[i], key[str_search[i]]) + +# if only one person is left at the end, print his name +if len(match) == 1: + print(match[0]) +else: + print("No match") diff --git a/Lab6/sentimental/credit.py b/Lab6/sentimental/credit.py new file mode 100644 index 0000000..80965cd --- /dev/null +++ b/Lab6/sentimental/credit.py @@ -0,0 +1,66 @@ +from cs50 import get_string + + +def invalid(): + print("INVALID") + exit() + + +# check luhn alghorythm +def luhn_algo(): + nSum = 0 + isSecond = False + # iterate over all card numbers from back + for i in range(ndigits - 1, -1, -1): + d = int(user_input[i]) + + # check if number is every second + if isSecond: + d *= 2 + # check for double digit sums + if d >= 10: + nSum += int(d / 10) + nSum += int(d % 10) + else: + nSum += d + + if isSecond: + isSecond = False + else: + isSecond = True + if nSum % 10 == 0: + return True + else: + invalid() + + +# check validity of card by using luhn alghoritm +def card_check(): + beginning = int(user_input[0:2]) + if 39 < beginning < 50: + if luhn_algo(): + print("VISA") + elif beginning == 34 or beginning == 37: + if luhn_algo(): + print("AMEX") + elif 50 < beginning < 56: + if luhn_algo(): + print("MASTERCARD") + else: + invalid() + + +# takes user input and check if the value is positive number +user_input = get_string("Enter credit card number:") +try: + if int(user_input) < 1: + invalid() +except: + invalid() + +# calculates the length of input and if correct, continues with card_check +ndigits = len(user_input) +if ndigits == 15 or ndigits == 13 or ndigits == 16: + card_check() +else: + invalid() diff --git a/Lab6/sentimental/hello.py b/Lab6/sentimental/hello.py new file mode 100644 index 0000000..fe3ec01 --- /dev/null +++ b/Lab6/sentimental/hello.py @@ -0,0 +1,5 @@ +from cs50 import get_string + +# asks user for his name and says hello +answer = get_string("What's your name? ") +print("hello, " + answer) \ No newline at end of file diff --git a/Lab6/sentimental/mario.py b/Lab6/sentimental/mario.py new file mode 100644 index 0000000..eeb391b --- /dev/null +++ b/Lab6/sentimental/mario.py @@ -0,0 +1,31 @@ +from cs50 import get_int + + +# asks user for height input +def user_input(): + user_height = 0 + while user_height < 1 or user_height > 8: + user_height = get_int("Height: ") + if user_height < 1 or user_height > 8: + print("Input height from 1 to 8.") + + return user_height + + +# creates spacing in the pyramid +def spacing(offset): + for space in range(offset): + print(" ", end="") + + +# creates a pyramid +height = user_input() +for i in range(1, height + 1, 1): + spacing(height - i) + # creates first left side, than space, than right side of pyramid + for k in range(1, 3, 1): + for j in range(1, i + 1, 1): + print("#", end="") + if k == 1: + print(" ", end="") + print() diff --git a/Lab6/sentimental/readability.py b/Lab6/sentimental/readability.py new file mode 100644 index 0000000..85de37c --- /dev/null +++ b/Lab6/sentimental/readability.py @@ -0,0 +1,33 @@ +from cs50 import get_string + +# initializing default values for variables +letters = 0 +words = 1 +sentences = 0 + +# getting string from user and looping through each character +user_input = get_string("Text:") +n = len(user_input) + +for i in range(n): + ascii_code = ord(user_input[i]) + # counting letters based on ascii values from a-z & A-Z + if 65 <= ascii_code <= 122: + letters += 1 + # counting words based on ascii value for space + elif ascii_code == 32: + words += 1 + # counting sentences based on ascii value for ".","!","?" + elif ascii_code == 33 or ascii_code == 63 or ascii_code == 46: + sentences += 1 +# calculating Coleman-Liau index +let = letters / words * 100 +s = sentences / words * 100 +index = round(0.0588 * let - 0.296 * s - 15.8) + +if index < 1: + print("Before Grade 1") +elif index >= 16: + print("Grade 16+") +else: + print("Grade " + str(index)) diff --git a/Lab6/worldcup/tournament.py b/Lab6/worldcup/tournament.py new file mode 100644 index 0000000..af81189 --- /dev/null +++ b/Lab6/worldcup/tournament.py @@ -0,0 +1,72 @@ +# Simulate a sports tournament + +import csv +import sys +import random + +# Number of simluations to run +N = 1000 + + +def main(): + + # Ensure correct usage + if len(sys.argv) != 2: + sys.exit("Usage: python tournament.py FILENAME") + + teams = [] + filename = sys.argv[1] + # TODO: Read teams into memory from file + with open(filename) as file: + reader = csv.DictReader(file) + for row in reader: + row["rating"] = int(row["rating"]) + teams.append(row) + counts = {} + # TODO: Simulate N tournaments and keep track of win counts + + for i in range(N): + winner = simulate_tournament(teams) + if winner in counts: + counts[winner] += 1 + else: + counts[winner] = 1 + + # Print each team's chances of winning, according to simulation + for team in sorted(counts, key=lambda team: counts[team], reverse=True): + print(f"{team}: {counts[team] * 100 / N:.1f}% chance of winning") + + +def simulate_game(team1, team2): + """Simulate a game. Return True if team1 wins, False otherwise.""" + rating1 = team1["rating"] + rating2 = team2["rating"] + probability = 1 / (1 + 10 ** ((rating2 - rating1) / 600)) + return random.random() < probability + + +def simulate_round(teams): + """Simulate a round. Return a list of winning teams.""" + winners = [] + + # Simulate games for all pairs of teams + for i in range(0, len(teams), 2): + if simulate_game(teams[i], teams[i + 1]): + winners.append(teams[i]) + else: + winners.append(teams[i + 1]) + + return winners + + +def simulate_tournament(teams): + """Simulate a tournament. Return name of winning team.""" + # TODO + while len(teams) > 1: + teams = simulate_round(teams) + + return teams[0]["team"] + + +if __name__ == "__main__": + main() diff --git a/Lab7/fiftyville/answers.txt b/Lab7/fiftyville/answers.txt new file mode 100644 index 0000000..d956107 --- /dev/null +++ b/Lab7/fiftyville/answers.txt @@ -0,0 +1,3 @@ +The THIEF is: Ernest +The thief ESCAPED TO: London +The ACCOMPLICE is: Berthold diff --git a/Lab7/fiftyville/log.sql b/Lab7/fiftyville/log.sql new file mode 100644 index 0000000..a66569f --- /dev/null +++ b/Lab7/fiftyville/log.sql @@ -0,0 +1,61 @@ +-- Keep a log of any SQL queries you execute as you solve the mystery. + +-- frist query to get more info from crime scene reports based on the input we got with this tasks +select * from crime_scene_reports +where year = 2020 and month = 7 and day = 28 and street = "Chamberlin Street"; + +-- query to get transcripts from witnesses, we can filter it down based on the report mentioning that all witnesses mentioned courthouse +select * from interviews +where year = 2020 and month = 7 and day = 28 and transcript like "%courthouse%"; + +-- second query based on time of the crime + witness saying that thief left within 10 mins after the crime +select * from courthouse_security_logs +where year = 2020 and month = 7 and day = 28 and hour = 10 and minute >15 and minute <= 25; + +-- query based on witness stating that thief had call shorter than 1 min before the theft +select * from phone_calls +where year = 2020 and month = 7 and day = 28 and duration < 60; + +-- query based on witness stating that thief wanted to leave by earliest flight tomorrow +select * from flights +where year = 2020 and month = 7 and day = 29 +order by hour, minute; + +--query to get destination of earlies flight, so we can answer where the thief escaped to +select * from airports +where id = 4; + +--query to get list of passenger for the flight from the previous query +select * from passengers +where flight_id = 36; + +--getting more info about ppl on flight based on passport number +select * from people +where passport_number in (select passport_number from passengers +where flight_id = 36); + +-- narrowing the search down based on passport number, licence plate at crime scene and call number +select * from people +where passport_number in (select passport_number from passengers +where flight_id = 36) and license_plate in (select license_plate from courthouse_security_logs +where year = 2020 and month = 7 and day = 28 and hour = 10 and minute >15 and minute <= 25) and phone_number in (select caller from phone_calls +where year = 2020 and month = 7 and day = 28 and duration < 60); + +--query to follow lead on ATM +select person_id from bank_accounts +where account_number in (select account_number from atm_transactions +where year = 2020 and month = 7 and day = 28 and atm_location = "Fifer Street" and transaction_type = "withdraw"); + +-- combining all leads togethe we got out thief +select * from people +where passport_number in (select passport_number from passengers +where flight_id = 36) and license_plate in (select license_plate from courthouse_security_logs +where year = 2020 and month = 7 and day = 28 and hour = 10 and minute >15 and minute <= 25) and phone_number in (select caller from phone_calls +where year = 2020 and month = 7 and day = 28 and duration < 60) and id in (select person_id from bank_accounts +where account_number in (select account_number from atm_transactions +where year = 2020 and month = 7 and day = 28 and atm_location = "Fifer Street" and transaction_type = "withdraw")); + +-- final query to get accomplice based on the call he received from our thief +select name from people +where phone_number = (select receiver from phone_calls +where year = 2020 and month = 7 and day = 28 and duration < 60 and caller = "(367) 555-5533"); \ No newline at end of file diff --git a/Lab7/movies/1.sql b/Lab7/movies/1.sql new file mode 100644 index 0000000..b4a5eb2 --- /dev/null +++ b/Lab7/movies/1.sql @@ -0,0 +1 @@ +select title from movies where year = 2008; \ No newline at end of file diff --git a/Lab7/movies/10.sql b/Lab7/movies/10.sql new file mode 100644 index 0000000..d4c3ebd --- /dev/null +++ b/Lab7/movies/10.sql @@ -0,0 +1,3 @@ +select distinct name from people +join directors on people.id = directors.person_id +where movie_id in (select movie_id from ratings where rating >= 9.0); diff --git a/Lab7/movies/11.sql b/Lab7/movies/11.sql new file mode 100644 index 0000000..b1491b1 --- /dev/null +++ b/Lab7/movies/11.sql @@ -0,0 +1,7 @@ +select title from movies +join stars on people.id = stars.person_id +join people on stars.movie_id = movies.id +join ratings on movies.id = ratings.movie_id +where people.name = "Chadwick Boseman" +order by rating desc +limit 5; \ No newline at end of file diff --git a/Lab7/movies/12.sql b/Lab7/movies/12.sql new file mode 100644 index 0000000..ae6e664 --- /dev/null +++ b/Lab7/movies/12.sql @@ -0,0 +1,7 @@ +select title from movies +join stars on people.id = stars.person_id +join people on stars.movie_id = movies.id +where people.name = "Johnny Depp" and title in (select title from movies +join stars on people.id = stars.person_id +join people on stars.movie_id = movies.id +where people.name = "Helena Bonham Carter"); \ No newline at end of file diff --git a/Lab7/movies/13.sql b/Lab7/movies/13.sql new file mode 100644 index 0000000..53cf829 --- /dev/null +++ b/Lab7/movies/13.sql @@ -0,0 +1,7 @@ +select distinct people.name from movies +join stars on people.id = stars.person_id +join people on stars.movie_id = movies.id +where people.name != "Kevin Bacon" and title in (select title from movies +join stars on people.id = stars.person_id +join people on stars.movie_id = movies.id +where people.name = "Kevin Bacon" and people.birth = 1958); \ No newline at end of file diff --git a/Lab7/movies/2.sql b/Lab7/movies/2.sql new file mode 100644 index 0000000..70156e0 --- /dev/null +++ b/Lab7/movies/2.sql @@ -0,0 +1 @@ +select birth from people where name = "Emma Stone"; \ No newline at end of file diff --git a/Lab7/movies/3.sql b/Lab7/movies/3.sql new file mode 100644 index 0000000..09315bc --- /dev/null +++ b/Lab7/movies/3.sql @@ -0,0 +1 @@ +select title from movies where year >= 2018 order by title asc; \ No newline at end of file diff --git a/Lab7/movies/4.sql b/Lab7/movies/4.sql new file mode 100644 index 0000000..19634c9 --- /dev/null +++ b/Lab7/movies/4.sql @@ -0,0 +1 @@ +select count(movie_id) from ratings where rating = 10.0 \ No newline at end of file diff --git a/Lab7/movies/5.sql b/Lab7/movies/5.sql new file mode 100644 index 0000000..64fad98 --- /dev/null +++ b/Lab7/movies/5.sql @@ -0,0 +1 @@ +select title, year from movies where title like "Harry Potter%" order by year asc; \ No newline at end of file diff --git a/Lab7/movies/6.sql b/Lab7/movies/6.sql new file mode 100644 index 0000000..67d1dde --- /dev/null +++ b/Lab7/movies/6.sql @@ -0,0 +1,3 @@ +select avg(rating) from ratings +join movies on movies.id = ratings.movie_id +where year = 2012; \ No newline at end of file diff --git a/Lab7/movies/7.sql b/Lab7/movies/7.sql new file mode 100644 index 0000000..7d1f8df --- /dev/null +++ b/Lab7/movies/7.sql @@ -0,0 +1,4 @@ +select title, rating from movies +join ratings on movies.id = ratings.movie_id +where year = 2010 +order by rating desc, title asc; diff --git a/Lab7/movies/8.sql b/Lab7/movies/8.sql new file mode 100644 index 0000000..1a82e80 --- /dev/null +++ b/Lab7/movies/8.sql @@ -0,0 +1,3 @@ +select name from people +join stars on people.id = stars.person_id +where movie_id = (select id from movies where title = "Toy Story"); \ No newline at end of file diff --git a/Lab7/movies/9.sql b/Lab7/movies/9.sql new file mode 100644 index 0000000..6880f22 --- /dev/null +++ b/Lab7/movies/9.sql @@ -0,0 +1,4 @@ +select distinct name from people +join stars on people.id = stars.person_id +where movie_id in (select id from movies where year = 2004) +order by birth asc; \ No newline at end of file diff --git a/Lab7/songs/1.sql b/Lab7/songs/1.sql new file mode 100644 index 0000000..39d86bf --- /dev/null +++ b/Lab7/songs/1.sql @@ -0,0 +1 @@ +select name from songs; \ No newline at end of file diff --git a/Lab7/songs/2.sql b/Lab7/songs/2.sql new file mode 100644 index 0000000..889c182 --- /dev/null +++ b/Lab7/songs/2.sql @@ -0,0 +1 @@ +select name from songs order by tempo; \ No newline at end of file diff --git a/Lab7/songs/3.sql b/Lab7/songs/3.sql new file mode 100644 index 0000000..b357434 --- /dev/null +++ b/Lab7/songs/3.sql @@ -0,0 +1 @@ +select name from songs order by duration_ms desc limit 5; \ No newline at end of file diff --git a/Lab7/songs/4.sql b/Lab7/songs/4.sql new file mode 100644 index 0000000..f30b02f --- /dev/null +++ b/Lab7/songs/4.sql @@ -0,0 +1 @@ +select name from songs where danceability>0.75 and energy > 0.75 and valence >0.75; \ No newline at end of file diff --git a/Lab7/songs/5.sql b/Lab7/songs/5.sql new file mode 100644 index 0000000..545ecb5 --- /dev/null +++ b/Lab7/songs/5.sql @@ -0,0 +1 @@ +select avg(energy) from songs; \ No newline at end of file diff --git a/Lab7/songs/6.sql b/Lab7/songs/6.sql new file mode 100644 index 0000000..4e3fa3a --- /dev/null +++ b/Lab7/songs/6.sql @@ -0,0 +1,2 @@ + +select name from songs where artist_id = (select id from artists where name = "Post Malone"); \ No newline at end of file diff --git a/Lab7/songs/7.sql b/Lab7/songs/7.sql new file mode 100644 index 0000000..2834fb4 --- /dev/null +++ b/Lab7/songs/7.sql @@ -0,0 +1 @@ +select avg(energy) from songs where artist_id = (select id from artists where name = "Drake"); \ No newline at end of file diff --git a/Lab7/songs/8.sql b/Lab7/songs/8.sql new file mode 100644 index 0000000..a61c31a --- /dev/null +++ b/Lab7/songs/8.sql @@ -0,0 +1 @@ +select name from songs where name like "%feat.%"; \ No newline at end of file diff --git a/Lab8/homepage/about.html b/Lab8/homepage/about.html new file mode 100644 index 0000000..7577152 --- /dev/null +++ b/Lab8/homepage/about.html @@ -0,0 +1,71 @@ + + + + + + + + + + Jiri Karlik - About Me + + + +
+

About Me

+

Here is just example text for now.

+
+ +
+
+
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet mi ac ex cursus aliquet ac sed neque. Curabitur sollicitudin nisl et dolor suscipit lobortis. Suspendisse sit amet nibh elit. Nulla eu sem lectus. Nullam gravida urna in sem dictum, convallis aliquam enim euismod. Integer aliquam condimentum purus, non rutrum urna dignissim sed. Cras ut urna euismod, eleifend leo venenatis, volutpat nunc. Aliquam a consectetur ipsum. Nam sit amet ipsum nibh. Integer laoreet diam a ipsum bibendum, a molestie urna mollis. Donec elementum nibh nisi. Aenean massa erat, porta ac fermentum non, consectetur rutrum erat.

+ Sed sit amet turpis dignissim, interdum odio quis, fringilla erat. Sed ultricies lobortis egestas. Proin eu tincidunt risus. Suspendisse ultrices mauris ut orci hendrerit rhoncus. Morbi scelerisque gravida neque, vel dapibus urna tempus in. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed dignissim venenatis nunc, nec suscipit dui tristique vitae. Etiam ut viverra risus. +

+ In eleifend quis ipsum sit amet congue. Donec at nisi fermentum, ornare arcu id, lobortis justo. Curabitur felis orci, viverra ac enim ullamcorper, molestie sodales felis. Maecenas elementum diam at nibh ultrices, sed rhoncus ipsum malesuada. Fusce accumsan tincidunt libero, nec bibendum nunc placerat in. Suspendisse ex ex, finibus sit amet eros eu, suscipit scelerisque lectus. Maecenas sapien mauris, ultricies at metus ut, cursus varius lorem. Mauris efficitur mi a ligula ullamcorper, quis auctor mi malesuada. Aliquam congue quam sapien, ac commodo dui lobortis eget. Vivamus laoreet nec nisi vel vestibulum. Aliquam erat volutpat. Phasellus efficitur venenatis tellus, tincidunt gravida neque blandit et. Aliquam erat volutpat. Sed molestie odio congue nunc porttitor, vel consectetur mi molestie. Sed non placerat odio, id fermentum ante. +

+ Vestibulum dignissim rutrum justo ut imperdiet. In hac habitasse platea dictumst. Mauris at maximus felis. Nunc et viverra orci. Proin ullamcorper, urna a facilisis placerat, nisl quam pellentesque nisi, vel laoreet eros arcu eu nunc. Nullam blandit erat a dictum volutpat. Aliquam in tristique lectus, non finibus purus. Cras faucibus consectetur lacus. Sed quis rutrum est. Phasellus gravida rutrum ipsum, non posuere tellus sollicitudin non. Curabitur porta eros a nisi sodales, ac ornare lorem suscipit. Proin porta ac nulla sit amet auctor. Nunc id lorem vel sapien aliquet auctor. +

+ Maecenas efficitur tempor feugiat. Fusce blandit lorem pretium porta efficitur. Suspendisse sit amet augue a quam convallis interdum vel a metus. Praesent sed venenatis felis, ac pulvinar tortor. Nam dolor justo, tincidunt non felis maximus, molestie vestibulum urna. Maecenas ultricies sapien ut dui sollicitudin elementum. Mauris vestibulum lacus vitae pretium maximus. Nam eget enim sed odio semper pellentesque id sit amet nunc. Pellentesque efficitur tristique purus et vehicula. Maecenas sapien nisi, sollicitudin ac dapibus malesuada, pellentesque quis elit. Etiam pretium, ipsum eget ornare pharetra, lectus arcu sagittis sapien, in suscipit enim urna id felis. Aliquam maximus neque quis leo dapibus, ut congue eros viverra. Morbi id erat a libero malesuada posuere ut a diam. Phasellus congue neque id tortor pellentesque imperdiet. Cras id consequat risus. +

+
+
+
+ + + + +
+
+
+

+
+ + diff --git a/Lab8/homepage/contact.html b/Lab8/homepage/contact.html new file mode 100644 index 0000000..e195b0e --- /dev/null +++ b/Lab8/homepage/contact.html @@ -0,0 +1,84 @@ + + + + + + + + + + Jiri Karlik - Contact + + + +
+

Contact Me

+

If you want to contact me, you can use one of the following options.

+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + +
+
+
+

+
+ + diff --git a/Lab8/homepage/index.html b/Lab8/homepage/index.html new file mode 100644 index 0000000..a370555 --- /dev/null +++ b/Lab8/homepage/index.html @@ -0,0 +1,55 @@ + + + + + + + + + + Jiri Karlik - Homepage + + + +
+

Introduction

+

Hi, my name is Jiří Karlík and this is my homepage website for CS50 pset8.

+ Portrait of Jiri. +
+ +
+
+ + + +
+
+
+

+
+ + diff --git a/Lab8/homepage/interests.html b/Lab8/homepage/interests.html new file mode 100644 index 0000000..fa950a4 --- /dev/null +++ b/Lab8/homepage/interests.html @@ -0,0 +1,68 @@ + + + + + + + + + + Jiri Karlik - Interests + + + +
+

Interests

+

Here you can find list of my hobbies.

+
+ +
+
+
+
    +
  • Gaming
  • +
  • Computer Science
  • +
  • Books
  • +
  • Leatherworking
  • +
  • Cooking
  • +
+
+
+
+ + + + +
+
+
+

+
+ + diff --git a/Lab8/homepage/styles.css b/Lab8/homepage/styles.css new file mode 100644 index 0000000..bb5859a --- /dev/null +++ b/Lab8/homepage/styles.css @@ -0,0 +1,28 @@ +button{ + border-radius: 10px; + border-style: none; +} +.menu{ + text-align: center; + margin-bottom: 1%; +} +.contact{ + text-align: center; + margin: 2%; +} +.row_last{ + margin-bottom:5%; +} +.interests{ + text-align: center; +} +.interests > ul { + display: inline-block; +} + +footer p { + text-align: center; +} +.wrapper{ + text-align:center; +} diff --git a/Lab8/trivia/index.html b/Lab8/trivia/index.html new file mode 100644 index 0000000..7f323c0 --- /dev/null +++ b/Lab8/trivia/index.html @@ -0,0 +1,81 @@ + + + + + + + Trivia! + + + + + + +
+

Trivia!

+
+ +
+ +
+

Part 1: Multiple Choice

+
+ + +

What is the approximate ratio of people to sheep in New Zealand?

+ + + + + + +

+
+ +
+

Part 2: Free Response

+
+ + +

In which country is it illegal to own only one guinea pig, as alone guinea pig might get lonely.

+ + +

+
+ +
+ + diff --git a/Lab8/trivia/styles.css b/Lab8/trivia/styles.css new file mode 100644 index 0000000..a196217 --- /dev/null +++ b/Lab8/trivia/styles.css @@ -0,0 +1,62 @@ +body { + background-color: #fff; + color: #212529; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + margin: 0; + text-align: left; +} + +.container { + margin-left: auto; + margin-right: auto; + padding-left: 15px; + padding-right: 15px; +} + +.jumbotron { + background-color: #477bff; + color: #fff; + margin-bottom: 2rem; + padding: 2rem 1rem; + text-align: center; +} + +.section { + padding: 0.5rem 2rem 1rem 2rem; +} + +.section:hover { + background-color: #f5f5f5; + transition: color 2s ease-in-out, background-color 0.15s ease-in-out; +} + +h1 { + font-family: 'Montserrat', sans-serif; + font-size: 48px; +} + +button, input[type="submit"] { + background-color: #d9edff; + border: 1px solid transparent; + border-radius: 0.25rem; + font-size: 0.95rem; + font-weight: 400; + line-height: 1.5; + padding: 0.375rem 0.75rem; + text-align: center; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + vertical-align: middle; +} + + +input[type="text"] { + line-height: 1.8; + width: 25%; +} + +input[type="text"]:hover { + background-color: #f5f5f5; + transition: color 2s ease-in-out, background-color 0.15s ease-in-out; +} diff --git a/Lab9/birthdays/application.py b/Lab9/birthdays/application.py new file mode 100644 index 0000000..8b94bf7 --- /dev/null +++ b/Lab9/birthdays/application.py @@ -0,0 +1,33 @@ +import os + +from cs50 import SQL +from flask import Flask, flash, jsonify, redirect, render_template, request, session + +# Configure application +app = Flask(__name__) + +# Ensure templates are auto-reloaded +app.config["TEMPLATES_AUTO_RELOAD"] = True + +# Configure CS50 Library to use SQLite database +db = SQL("sqlite:///birthdays.db") + +@app.route("/", methods=["GET", "POST"]) +def index(): + if request.method == "POST": + + # TODO: Add the user's entry into the database + name = request.form.get("name") + month = request.form.get("month") + day = request.form.get("day") + + db.execute("insert into birthdays (name, month, day) values(?, ?, ?)", name, month, day) + + return redirect("/") + + else: + + # TODO: Display the entries in the database on index.html + return render_template("index.html", birthdays = db.execute("select * from birthdays")) + + diff --git a/Lab9/birthdays/birthdays.db b/Lab9/birthdays/birthdays.db new file mode 100644 index 0000000000000000000000000000000000000000..5915e5ecf9fff712825cc7faff5b1028059ac665 GIT binary patch literal 8192 zcmeI#K}y3w6b9h;(xfF(nL?4SB(rQm+;{+uGHA7m#w_eIC6Nx81ja1PvKR9J9zgH} z?mdAMrG>8Ciu^w_C(Z``;MJrQIK5-1Rwwb2tWV=5P$##AOHafK;ZuiEc@IWh9NJjI-Nh}b8YHHmNrl8 z!a0pqlqi`*CsQTY$8r=%8=c9?b)wExy#L*oX_3oB-6ub7QI+*#bHe_7^WY|)Tt)Fr zUaHwhXX9YpzRf-HLgG_=h&ScpeRyo98Up r3S5tN*}u?6yQ1UK9`ku_3SE`CKk%J)(2uLKv&|k2?Oke2(+j@ + + + + + + Birthdays + + +
+

Birthdays

+
+
+
+ +

Add a Birthday

+ +
+ + + + + +
+
+ +
+ +

All Birthdays

+ + + + + + + + + + {% for birthday in birthdays%} + + + + + {% endfor%} + +
NameBirthday
{{birthday.name}}{{birthday.day}}/{{birthday.month}}
+
+
+ + diff --git a/Lab9/finance/application.py b/Lab9/finance/application.py new file mode 100644 index 0000000..24adcf0 --- /dev/null +++ b/Lab9/finance/application.py @@ -0,0 +1,330 @@ +import os + +from cs50 import SQL +from flask import Flask, flash, redirect, render_template, request, session +from flask_session import Session +from tempfile import mkdtemp +from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError +from werkzeug.security import check_password_hash, generate_password_hash +from datetime import datetime + +from helpers import apology, login_required, lookup, usd + +# Configure application +app = Flask(__name__) + +# Ensure templates are auto-reloaded +app.config["TEMPLATES_AUTO_RELOAD"] = True + + +# Ensure responses aren't cached +@app.after_request +def after_request(response): + response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" + response.headers["Expires"] = 0 + response.headers["Pragma"] = "no-cache" + return response + + +# Custom filter +app.jinja_env.filters["usd"] = usd + +# Configure session to use filesystem (instead of signed cookies) +app.config["SESSION_FILE_DIR"] = mkdtemp() +app.config["SESSION_PERMANENT"] = False +app.config["SESSION_TYPE"] = "filesystem" +Session(app) + +# Configure CS50 Library to use SQLite database +db = SQL("sqlite:///finance.db") + +# Make sure API key is set +if not os.environ.get("API_KEY"): + raise RuntimeError("API_KEY not set") + + +@app.route("/") +@login_required +def index(): + """Show portfolio of stocks""" + # getting user info from DB + user_id = session["user_id"] + portfolio = db.execute("SELECT * FROM portfolio WHERE id = ?", user_id) + cash_list = db.execute("SELECT cash FROM users WHERE id = ?", user_id) + cash = cash_list[0]["cash"] + grand_total = cash + + # list throught user protfolio and all needed information to the portfolio list + for row in portfolio: + stock = lookup(row["symbol"]) + price = float(stock["price"]) + name = stock["name"] + amount = int(row["amount"]) + total = price * amount + + row["name"] = name + row["price"] = usd(price) + row["total"] = usd(total) + + grand_total += total + + # money formatting and returning html + cash = usd(cash) + grand_total = usd(grand_total) + return render_template("index.html", portfolio=portfolio, cash=cash, grand_total=grand_total) + + +@app.route("/buy", methods=["GET", "POST"]) +@login_required +def buy(): + """Buy shares of stock""" + # User reached route via POST (as by submitting a form via POST) + # get user inputs and check if they are valid + if request.method == "POST": + user_id = session["user_id"] + symbol = request.form.get("symbol") + shares = request.form.get("shares") + + if symbol == "": + return apology("Missing symbol") + + elif shares == "": + return apology("Missing number of shares") + + elif not shares.isdigit() or int(shares) < 1: + return apology("Number of shares must be bigger than 1.") + + # getting stock info from API + stock = lookup(symbol) + shares = int(shares) + symbol = symbol.upper() + + if not stock: + return apology("Not existing symbol") + + # compare total stock price vs funds + price = stock["price"] + total_price = price * shares + row = db.execute("SELECT * FROM users WHERE id = ?", user_id) + funds = float(row[0]["cash"]) + + if funds < total_price: + return apology("You don't have enough money") + + # update users cash, insert transcation to history table + now = datetime.now() + now = now.strftime("%Y-%m-%d %H:%M:%S") + db.execute("UPDATE users SET cash = cash - ? WHERE id = ?", total_price, user_id) + db.execute("INSERT INTO history (id, symbol, shares, price, transacted) VALUES (?, ?, ?, ?, ?)", user_id, + symbol, shares, total_price, now) + + # check if user already owns this stock, change portfolio + owned = db.execute("SELECT * FROM portfolio WHERE id = ? AND symbol = ?", user_id, symbol) + if len(owned) > 0: + db.execute("UPDATE portfolio SET amount = amount + ? WHERE id = ? AND symbol = ?", shares, user_id, symbol) + else: + db.execute("INSERT INTO portfolio (id, symbol, amount) VALUES (?, ?, ?)", user_id, symbol, shares) + + # Redirect user to home page + return redirect("/") + + else: + return render_template("buy.html") + + +@app.route("/history") +@login_required +def history(): + """Show history of transactions""" + # getting user history logs from DB + user_id = session["user_id"] + history = db.execute("SELECT * FROM history WHERE id = ?", user_id) + + return render_template("history.html", history=history) + + +@app.route("/login", methods=["GET", "POST"]) +def login(): + """Log user in""" + + # Forget any user_id + session.clear() + + # User reached route via POST (as by submitting a form via POST) + if request.method == "POST": + + # Ensure username was submitted + if not request.form.get("username"): + return apology("must provide username", 403) + + # Ensure password was submitted + elif not request.form.get("password"): + return apology("must provide password", 403) + + # Query database for username + rows = db.execute("SELECT * FROM users WHERE username = ?", request.form.get("username")) + + # Ensure username exists and password is correct + if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")): + return apology("invalid username and/or password", 403) + + # Remember which user has logged in + session["user_id"] = rows[0]["id"] + + # Redirect user to home page + return redirect("/") + + # User reached route via GET (as by clicking a link or via redirect) + else: + return render_template("login.html") + + +@app.route("/logout") +def logout(): + """Log user out""" + + # Forget any user_id + session.clear() + + # Redirect user to login form + return redirect("/") + + +@app.route("/quote", methods=["GET", "POST"]) +@login_required +def quote(): + """Get stock quote.""" + # User reached route via POST (as by submitting a form via POST) + if request.method == "POST": + # getting user input and checking if it's valid + symbol = request.form.get("symbol") + + if symbol == "": + return apology("Missing symbol") + + # getting stock info from API + stock = lookup(symbol) + + if not stock: + return apology("Not existing symbol") + + # creating html with info from API + return render_template("quoted.html", symbol=stock["symbol"], name=stock["name"], price=usd(stock["price"])) + + else: + return render_template("quote.html") + + +@app.route("/register", methods=["GET", "POST"]) +def register(): + """Register user""" + if request.method == "POST": + + # Getting user inputs and checking if he filled all + name = request.form.get("username") + password = request.form.get("password") + confirmation = request.form.get("confirmation") + + if name == "": + return apology("Missing username") + + elif password == "": + return apology("Missing password") + + elif confirmation == "": + return apology("Missing password confirmation") + + elif password != confirmation: + return apology("Passwords not matching") + + # personal touch - password strength check + upper = 0 + digits = 0 + symbols = 0 + for char in password: + if char.isupper(): + upper += 1 + elif char.isdigit(): + digits += 1 + elif not char.islower(): + symbols += 1 + + if upper < 1 or digits < 1 or symbols < 1: + return apology("Password must contain 1 uppercase, 1 number and 1 symbol") + + # Checking inputs against DB + rows = db.execute("SELECT * FROM users WHERE username == (?)", name) + if len(rows) > 0: + return apology("Username is already used") + + # convert password to hash and insert username + hash to db + hash_pw = generate_password_hash(password) + db.execute("INSERT INTO users (username, hash) VALUES (?, ?)", name, hash_pw) + + # remember which user is logged in and redirect to homepage + rows = db.execute("SELECT * FROM users WHERE username = (?)", name) + session["user_id"] = rows[0]["id"] + + return redirect("/") + + else: + return render_template("register.html") + + +@app.route("/sell", methods=["GET", "POST"]) +@login_required +def sell(): + """Sell shares of stock""" + # getting user portfolio from DB + user_id = session["user_id"] + portfolio = db.execute("SELECT * FROM portfolio WHERE id = ?", user_id) + + if request.method == "POST": + # get inputs from user and check if it's valid + symbol = request.form.get("symbol") + shares = int(request.form.get("shares")) + owned_shares = db.execute("SELECT * FROM portfolio WHERE id = ? AND symbol = ?", user_id, symbol) + stock = lookup(symbol) + + if shares < 1 or shares == "": + return apology("Invalid number of shares") + + # checking difference between owned and want to sell shares + difference = owned_shares[0]["amount"] - shares + + if difference < 0: + return apology("You don't own that many shares") + + # update user's cash + total_price = stock["price"] * shares + db.execute("UPDATE users SET cash = cash + ? WHERE id = ?", total_price, user_id) + + # create entry in history + now = datetime.now() + now = now.strftime("%Y-%m-%d %H:%M:%S") + db.execute("INSERT INTO history (id, symbol, shares, price, transacted) VALUES (?, ?, ?, ?, ?)", user_id, + symbol, shares * (-1), total_price, now) + + # if sold amount = owned amount, delete entry from portfolio + if difference == 0: + db.execute("DELETE FROM portfolio WHERE id = ? and symbol = ?", user_id, symbol) + else: + db.execute("UPDATE portfolio SET amount = ? WHERE id = ? and symbol = ?", difference, user_id, symbol) + + # Redirect user to home page + return redirect("/") + + else: + return render_template("sell.html", portfolio=portfolio) + + +def errorhandler(e): + """Handle error""" + if not isinstance(e, HTTPException): + e = InternalServerError() + return apology(e.name, e.code) + + +# Listen for errors +for code in default_exceptions: + app.errorhandler(code)(errorhandler) diff --git a/Lab9/finance/finance.db b/Lab9/finance/finance.db new file mode 100644 index 0000000000000000000000000000000000000000..6d95b9beb7474f5102cd01e7e0f0a1e3d4ec690f GIT binary patch literal 24576 zcmeI(Pi)&%90zbaag#Npaiy+`P!;wzs=1Zg$^YU%ktPy4GlixpZBw*PNXU+#Thrzb ziL16;P!QaALE_%yB#vkjH?F{yKiUE9u*(of5GUX{N?Y1hj0@6=zAt)y)-ONj_j{k) zi{!PHY8X)xw7X3=A{sZ&@jO=|gyXnHHdDjNv-Jv_0-Hx8jy-QIayMW5aV+~CCuFa4 zqL*!EuV)`+A3g6ed=CK#KmY;|fB*y_009U<;QuVZ4oRQAi2JJusa!tCH^Y`s_jh}= z+j5&UUV9@8t4_J@ko8(+W!)i_+HL19Im#f*wZVOl%p8SgHUi6JpcdIVT`d?z zr4S!=r>k$SZI*p=ZCdv2z}Ib4u`DZaZL83bT~{%^z%Te#!!;Y0Vp^)Dd75rpfv*^T zgMDmGQGMUEG_Cae{N>NDeDKqDGR5Wkl|+Yj!tHZQ-dT{@9|c>@X;mo%mSq$aQeTZ*N-c$LP1jA&3QWVJ zhBO|Z|1;V9ocLJ$N<0)l7T*yyF_V3qeaM0s5P$##AOHafKmY;|fB*y_0D=EV;6^4j z!KXF8R#_e^efV|eR_E{sRaTXGMV*%wBHKmPDyp_1jix5!yzq`?@ZKvASAPEFOrllPH9<;0KhZ1}OhHPWN<6o;9`|@-BsDoY?6LIV z**vxpqo|rfUWoIq4fgVEo{&$*B-dh+L}~5*;pv?U`NZ+pnbLmr4IAH{>`%z^|M=r$ z;;$SpKIO!x?1BLS2tWV=5P$##AOHafKmY;|fWQS5V2Ascj@lkg2orq#C&J6|OZ=CI z;S5`o;uB8%P5gx|7!ZH}1Rwwb2tWV=5P$##AOHafTvUN{a)M{?5+p7qC;9l531Kvu k;|FgtBrocg&^H7i009U<00Izz00bZa0SG_<0{>p%FZ{}C1ONa4 literal 0 HcmV?d00001 diff --git a/Lab9/finance/helpers.py b/Lab9/finance/helpers.py new file mode 100644 index 0000000..27a6caf --- /dev/null +++ b/Lab9/finance/helpers.py @@ -0,0 +1,64 @@ +import os +import requests +import urllib.parse + +from flask import redirect, render_template, request, session +from functools import wraps + + +def apology(message, code=400): + """Render message as an apology to user.""" + def escape(s): + """ + Escape special characters. + + https://github.com/jacebrowning/memegen#special-characters + """ + for old, new in [("-", "--"), (" ", "-"), ("_", "__"), ("?", "~q"), + ("%", "~p"), ("#", "~h"), ("/", "~s"), ("\"", "''")]: + s = s.replace(old, new) + return s + return render_template("apology.html", top=code, bottom=escape(message)), code + + +def login_required(f): + """ + Decorate routes to require login. + + https://flask.palletsprojects.com/en/1.1.x/patterns/viewdecorators/ + """ + @wraps(f) + def decorated_function(*args, **kwargs): + if session.get("user_id") is None: + return redirect("/login") + return f(*args, **kwargs) + return decorated_function + + +def lookup(symbol): + """Look up quote for symbol.""" + + # Contact API + try: + api_key = os.environ.get("API_KEY") + url = f"https://cloud.iexapis.com/stable/stock/{urllib.parse.quote_plus(symbol)}/quote?token={api_key}" + response = requests.get(url) + response.raise_for_status() + except requests.RequestException: + return None + + # Parse response + try: + quote = response.json() + return { + "name": quote["companyName"], + "price": float(quote["latestPrice"]), + "symbol": quote["symbol"] + } + except (KeyError, TypeError, ValueError): + return None + + +def usd(value): + """Format value as USD.""" + return f"${value:,.2f}" diff --git a/Lab9/finance/requirements.txt b/Lab9/finance/requirements.txt new file mode 100644 index 0000000..1ecea2e --- /dev/null +++ b/Lab9/finance/requirements.txt @@ -0,0 +1,4 @@ +cs50 +Flask +Flask-Session +requests diff --git a/Lab9/finance/static/favicon.ico b/Lab9/finance/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2dacfe5db808c787ef6ddebdd115e847af7f370b GIT binary patch literal 5558 zcmd^Cc}$c?6km_hNEH-gjEX7RN-(Cjiq)WP1r!SGQccr(p_ChID=G-as8G~+;1N+# zlwBxMJWyK|ENZ5Rnw}yIF$9*_lEsGzg@nic%=Vyli8W?UB5SP-pstw zXxeDnYC3n;Q17If+Fqk^)@U?NPEFq~T{N22L~|h;iI7ASow`>2bme$kThf?1Dr-Y^ z;MN3V$hL(>9&1aCsm!xx#J?1_{w3I?E5(x!bB|+6W-KaeF5}#-OZY?|1*S32zYLpL zR%wU7iFb;6a2uVq5nk(pF>Ch{RMlKTc-8_zllZzaAuHQpT!}X__Z9{(iNUA(8Mt!y z1`=}D!asE?T$j$q$OARPzK|t9*ax1I@QZLg58cBnAI(Jn*dTbU3B;j`r*Y<58GKX1 z1dVwt!}_cvVpWDz3A<;^W@x-3&^t01&a;Bx92Fs2znMXBj0hIIo-t{%585W(OOpP; zl#>{`wGtkAci?-rUY7GYQwxuScQ7=o3IjKslIf&ZO|4PV=U!XfNIu?G%80T1cek6- zNZzQ_XWc#tJ77Cu9+dL$q!pmO{|vZ(U1n*+NO6$;_bYfLd~{ivhrWr~vh1*J=i#>N zGVDKFEYnOrQ(irdAJe)^Bzek@cnZ;~X%pgWz%8-`#RfmNWT@!GS;lZivA4(p>ym{}*Z>)kA+aTlRrvBze{)KUPq0H80fsB6$~TmDFTgx}tiD zb+EwMRh|dq6C-k~jw7e?82GpL#Fi!>NQPz2bW2f1>(XBh%aX=beone?nfoQ*SZi~{Ny{d9n>&r z-3>JVe082`-l)z)O6YeA=>MrF#70&7G-7Z66^8jd3TzUXqL;4ap|gd z2kDET@s5;b+i9m`#O|xAvJy7OpPFj^u?(L9UBZ@Ajae+}_dZ|k5cbvTc$XCi;23A1 zdEXZ`vd!2SbdO4D5uY#$=sr;0f0B>fYYQJ^;KtK<_2XEy^_^x`gDd5D>~Zie9Oq;R zKVP4}_22OI*3KWv?y#)$uo)XI?AZk_!f<*oNIYe)EowyXxtT()o!^(}yKoo1mFiSw zB|WYueG6en_j0{Nv+OyJuT5Nl_rARj&P9%|r3`-$(iaMBKJWRhz`4kGr<$yZCeB~J z11JUtYjXTHvKbQ%XL|ea`=zb#7pgXg@4h1NyH8&ar}*vQ7+5=Z8H+H}8JmAx;}Wge z{mXKE-a3S@5Vku8Bw$Epxhg)(@;jB^gS-!TEm}A)jEpJ3O@HLia<-w?M&{f^8=ud` z8mRG=G|oMT@FZ0`k{s>1BqcVF-SW|a_*UyLN%tl6jM1$AVjukT;bN`+d +{% endblock %} diff --git a/Lab9/finance/templates/buy.html b/Lab9/finance/templates/buy.html new file mode 100644 index 0000000..f40d1c1 --- /dev/null +++ b/Lab9/finance/templates/buy.html @@ -0,0 +1,17 @@ +{% extends "layout.html" %} + +{% block title %} + Buy +{% endblock %} + +{% block main %} +
+
+ +
+
+ +
+ +
+{% endblock %} diff --git a/Lab9/finance/templates/history.html b/Lab9/finance/templates/history.html new file mode 100644 index 0000000..a50d0e0 --- /dev/null +++ b/Lab9/finance/templates/history.html @@ -0,0 +1,28 @@ +{% extends "layout.html" %} + +{% block title %} + History +{% endblock %} + +{% block main %} + + + + + + + + + + + {% for row in history %} + + + + + + + {% endfor %} + +
SymbolSharesPriceTransacted
{{ row.symbol }}{{ row.shares }}{{ row.price }}{{ row.transacted }}
+{% endblock %} diff --git a/Lab9/finance/templates/index.html b/Lab9/finance/templates/index.html new file mode 100644 index 0000000..bd054c9 --- /dev/null +++ b/Lab9/finance/templates/index.html @@ -0,0 +1,39 @@ +{% extends "layout.html" %} + +{% block title %} + Index +{% endblock %} + +{% block main %} + + + + + + + + + + + + {% for row in portfolio %} + + + + + + + + {% endfor %} + + + + + + + + + + +
SymbolNameSharesPriceTotal
{{ row.symbol }}{{ row.name }}{{ row.amount }}{{ row.price }}{{ row.total }}
Cash{{ cash }}
TOTAL{{ grand_total }}
+{% endblock %} diff --git a/Lab9/finance/templates/layout.html b/Lab9/finance/templates/layout.html new file mode 100644 index 0000000..a9a6677 --- /dev/null +++ b/Lab9/finance/templates/layout.html @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + C$50 Finance: {% block title %}{% endblock %} + + + + + + + + {% if get_flashed_messages() %} +
+ +
+ {% endif %} + +
+ {% block main %}{% endblock %} +
+ + + + + + diff --git a/Lab9/finance/templates/login.html b/Lab9/finance/templates/login.html new file mode 100644 index 0000000..0a2404b --- /dev/null +++ b/Lab9/finance/templates/login.html @@ -0,0 +1,17 @@ +{% extends "layout.html" %} + +{% block title %} + Log In +{% endblock %} + +{% block main %} +
+
+ +
+
+ +
+ +
+{% endblock %} diff --git a/Lab9/finance/templates/quote.html b/Lab9/finance/templates/quote.html new file mode 100644 index 0000000..7490ad7 --- /dev/null +++ b/Lab9/finance/templates/quote.html @@ -0,0 +1,14 @@ +{% extends "layout.html" %} + +{% block title %} + Quote +{% endblock %} + +{% block main %} +
+
+ +
+ +
+{% endblock %} diff --git a/Lab9/finance/templates/quoted.html b/Lab9/finance/templates/quoted.html new file mode 100644 index 0000000..84ec095 --- /dev/null +++ b/Lab9/finance/templates/quoted.html @@ -0,0 +1,9 @@ +{% extends "layout.html" %} + +{% block title %} + Quoted +{% endblock %} + +{% block main %} +

A share of {{name}} ({{symbol}}) costs {{price}}

+{% endblock %} diff --git a/Lab9/finance/templates/register.html b/Lab9/finance/templates/register.html new file mode 100644 index 0000000..3f4c044 --- /dev/null +++ b/Lab9/finance/templates/register.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} + +{% block title %} + Register +{% endblock %} + +{% block main %} +
+
+ +
+
+ +
+
+ +
+ +
+{% endblock %} diff --git a/Lab9/finance/templates/sell.html b/Lab9/finance/templates/sell.html new file mode 100644 index 0000000..78c9c3a --- /dev/null +++ b/Lab9/finance/templates/sell.html @@ -0,0 +1,22 @@ +{% extends "layout.html" %} + +{% block title %} + Buy +{% endblock %} + +{% block main %} +
+
+ +
+
+ +
+ +
+{% endblock %}