Transfer to Gitea

This commit is contained in:
Jiri Karlik 2024-08-09 19:43:54 +02:00
commit 5928464304
72 changed files with 3034 additions and 0 deletions

Binary file not shown.

135
Lab1/credit/credit.c Normal file
View File

@ -0,0 +1,135 @@
#include <cs50.h>
#include <stdio.h>
#include <math.h>
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();
}
}

9
Lab1/hello/hello.c Normal file
View File

@ -0,0 +1,9 @@
#include <cs50.h>
#include <stdio.h>
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);
}

53
Lab1/mario/mario.c Normal file
View File

@ -0,0 +1,53 @@
#include <cs50.h>
#include <stdio.h>
//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(" ");
}
}

View File

@ -0,0 +1,34 @@
#include <cs50.h>
#include <stdio.h>
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);
}

View File

@ -0,0 +1,54 @@
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
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);
}
}

53
Lab2/scrabble/scrabble.c Normal file
View File

@ -0,0 +1,53 @@
#include <ctype.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// 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;
}

View File

@ -0,0 +1,96 @@
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
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;
}

111
Lab3/plurality/plurality.c Normal file
View File

@ -0,0 +1,111 @@
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// 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;
}

240
Lab3/runoff/runoff.c Normal file
View File

@ -0,0 +1,240 @@
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// 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;
}

12
Lab3/sort/answers.txt Normal file
View File

@ -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

152
Lab4/filter/helpers.c Normal file
View File

@ -0,0 +1,152 @@
#include "helpers.h"
#include "math.h"
#include <stdlib.h>
#include <stdio.h>
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;
}

66
Lab4/recover/recover.c Normal file
View File

@ -0,0 +1,66 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
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);
}
}

52
Lab4/volume/volume.c Normal file
View File

@ -0,0 +1,52 @@
// Modifies the volume of an audio file
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
// 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);
}

View File

@ -0,0 +1,127 @@
// Simulate genetic inheritance of blood type
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 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';
}
}

151
Lab5/speller/dictionary.c Normal file
View File

@ -0,0 +1,151 @@
// Implements a dictionary's functionality
#include <stdbool.h>
#include "dictionary.h"
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
// 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;
}

60
Lab6/dna/dna.py Normal file
View File

@ -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")

View File

@ -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()

View File

@ -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)

31
Lab6/sentimental/mario.py Normal file
View File

@ -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()

View File

@ -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))

View File

@ -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()

View File

@ -0,0 +1,3 @@
The THIEF is: Ernest
The thief ESCAPED TO: London
The ACCOMPLICE is: Berthold

61
Lab7/fiftyville/log.sql Normal file
View File

@ -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");

1
Lab7/movies/1.sql Normal file
View File

@ -0,0 +1 @@
select title from movies where year = 2008;

3
Lab7/movies/10.sql Normal file
View File

@ -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);

7
Lab7/movies/11.sql Normal file
View File

@ -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;

7
Lab7/movies/12.sql Normal file
View File

@ -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");

7
Lab7/movies/13.sql Normal file
View File

@ -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);

1
Lab7/movies/2.sql Normal file
View File

@ -0,0 +1 @@
select birth from people where name = "Emma Stone";

1
Lab7/movies/3.sql Normal file
View File

@ -0,0 +1 @@
select title from movies where year >= 2018 order by title asc;

1
Lab7/movies/4.sql Normal file
View File

@ -0,0 +1 @@
select count(movie_id) from ratings where rating = 10.0

1
Lab7/movies/5.sql Normal file
View File

@ -0,0 +1 @@
select title, year from movies where title like "Harry Potter%" order by year asc;

3
Lab7/movies/6.sql Normal file
View File

@ -0,0 +1,3 @@
select avg(rating) from ratings
join movies on movies.id = ratings.movie_id
where year = 2012;

4
Lab7/movies/7.sql Normal file
View File

@ -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;

3
Lab7/movies/8.sql Normal file
View File

@ -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");

4
Lab7/movies/9.sql Normal file
View File

@ -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;

1
Lab7/songs/1.sql Normal file
View File

@ -0,0 +1 @@
select name from songs;

1
Lab7/songs/2.sql Normal file
View File

@ -0,0 +1 @@
select name from songs order by tempo;

1
Lab7/songs/3.sql Normal file
View File

@ -0,0 +1 @@
select name from songs order by duration_ms desc limit 5;

1
Lab7/songs/4.sql Normal file
View File

@ -0,0 +1 @@
select name from songs where danceability>0.75 and energy > 0.75 and valence >0.75;

1
Lab7/songs/5.sql Normal file
View File

@ -0,0 +1 @@
select avg(energy) from songs;

2
Lab7/songs/6.sql Normal file
View File

@ -0,0 +1,2 @@
select name from songs where artist_id = (select id from artists where name = "Post Malone");

1
Lab7/songs/7.sql Normal file
View File

@ -0,0 +1 @@
select avg(energy) from songs where artist_id = (select id from artists where name = "Drake");

1
Lab7/songs/8.sql Normal file
View File

@ -0,0 +1 @@
select name from songs where name like "%feat.%";

71
Lab8/homepage/about.html Normal file
View File

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
document.addEventListener('DOMContentLoaded', async function() {
while (true){
// get date
var date = new Date();
// convert date to string
var n = date.toDateString();
// get time as string
var time = date.toLocaleTimeString();
document.getElementById('time').innerHTML = n + ' ' + time;
await sleep(999)
};
});
</script>
<link href="styles.css" rel="stylesheet">
<title>Jiri Karlik - About Me</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron text-center">
<h1>About Me</h1>
<p>Here is just example text for now.</p>
</div>
<div class="container">
<div class="row row_last">
<div class="col-sm-12 wrapper">
<p>
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.</p><p>
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.
</p><p>
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.
</p><p>
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.
</p><p>
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.
</p>
</div>
</div>
<div class="row">
<div class="col-sm-3 menu">
<h3><button onclick="location.href='index.html'" type="button">Home</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='about.html'" type="button">About Me</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='interests.html'" type="button">Interests</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='contact.html'" type="button">Contact</button></h3>
</div>
</div>
</div>
<footer>
<p id="time"></p>
</footer>
</body>
</html>

View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
document.addEventListener('DOMContentLoaded', async function() {
while (true){
// get date
var date = new Date();
// convert date to string
var n = date.toDateString();
// get time as string
var time = date.toLocaleTimeString();
document.getElementById('time').innerHTML = n + ' ' + time;
await sleep(999)
};
});
</script>
<link href="styles.css" rel="stylesheet">
<title>Jiri Karlik - Contact</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron text-center">
<h1>Contact Me</h1>
<p>If you want to contact me, you can use one of the following options.</p>
</div>
<div class="container">
<div class="row">
<div class="col-sm-12">
<a href="mailto:karlikjirka@gmail.com"><div class="contact">
<svg width="10%" height="10%" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 12.5H87.5C92.1023 12.5 95.8333 16.231 95.8333 20.8333V79.1667C95.8333 83.769 92.1023 87.5 87.5 87.5H12.5C7.89759 87.5 4.16663 83.769 4.16663 79.1667V20.8333C4.16663 16.231 7.89759 12.5 12.5 12.5ZM12.5 40.0754V79.1666H87.5V40.0771L49.9999 58.8272L12.5 40.0754ZM12.5 30.7583L50 49.5102L87.5 30.7602V20.8333H12.5V30.7583Z" fill="black"/>
</svg>
</div></a>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<a href="https://www.linkedin.com/in/jiri-karlik/"><div class="contact">
<svg width="10%" height="10%" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 0H90C95.5229 0 100 4.47715 100 10V90C100 95.5229 95.5229 100 90 100H10C4.47715 100 0 95.5229 0 90V10C0 4.47715 4.47715 0 10 0ZM10 10V90H90V10H10ZM55 35C52.4113 35 49.6763 35.7913 47.2607 37.2607L45 35H40V70H50V50C50 47.1213 52.9698 45 55 45H60C62.0302 45 65 47.1213 65 50V70H75V50C75 40.7359 66.9698 35 60 35H55ZM30 30C32.7614 30 35 27.7614 35 25C35 22.2386 32.7614 20 30 20C27.2386 20 25 22.2386 25 25C25 27.7614 27.2386 30 30 30ZM25 35V70H35V35H25Z" fill="black"/>
</svg>
</div></a>
</div>
</div>
<div class="row row_last">
<div class="col-sm-12">
<a href="https://github.com/karlji"><div class="contact">
<svg width="10%" height="10%" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M41.7385 83.3484C41.7601 83.8603 41.7049 84.3597 41.5971 84.8653C41.4077 85.7537 41.042 86.6937 40.5242 87.5622C39.0525 90.0313 36.5523 91.6788 33.3333 91.6788C25.7504 91.6788 22.7743 87.9587 19.048 78.6429C16.5243 72.3337 15.3337 70.8455 12.5 70.8455L12.5 62.5121C20.0829 62.5121 23.059 66.2322 26.7853 75.548C29.309 81.8572 30.4996 83.3455 33.3333 83.3455C33.3333 82.1364 33.3168 81.0655 33.2819 79.6152C33.2003 76.2161 33.1909 75.5221 33.3392 74.6134C33.3984 72.6297 33.9106 71.2222 34.9375 69.8251C25.6383 67.8008 19.3663 63.6201 15.7666 56.8391L14.4181 53.6679C13.1044 49.8924 12.5 45.6146 12.5 40.6742C12.5 34.9844 14.2348 29.897 17.4751 25.6444C16.4643 21.6021 16.6027 16.6633 18.8346 11.0858L19.5639 9.26324L21.4336 8.66517C21.6839 8.58509 21.9883 8.51277 22.3458 8.45666C25.9865 7.88524 31.1671 9.24858 37.9398 13.5868C41.9324 12.6613 46.1369 12.194 50.3699 12.194C54.1526 12.194 57.9144 12.5753 61.5068 13.3272C68.0961 9.20078 73.1343 7.90658 76.6771 8.45739C77.0305 8.51234 77.3317 8.58327 77.58 8.662L79.4613 9.25861L80.1915 11.0922C82.144 15.9953 82.4791 20.5139 81.7686 24.4678C85.4936 28.9374 87.5 34.4323 87.5 40.6742C87.5 45.9364 87.123 49.8934 86.0393 53.7428L84.8954 56.8818C81.9012 63.6556 75.2978 67.8832 65.1147 69.8968C66.1731 71.3623 66.6667 72.85 66.6667 75.0121V79.1788C66.6667 81.198 66.6667 81.2602 66.6621 83.3455C66.6715 83.4952 66.684 83.5685 66.6977 83.6142C66.6943 83.6154 66.6667 91.6788 66.6667 91.6788C63.1175 91.6788 60.4786 89.948 59.1807 87.2177C58.5078 85.8021 58.3068 84.4504 58.3333 83.2863V75.0121C58.3333 74.6628 58.3212 74.6426 57.4704 73.7917C55.1962 71.5176 54.1667 69.8017 54.1667 66.6788V62.9096L57.917 62.533C69.0806 61.4118 75.1522 58.3116 77.1653 53.7826L78.1061 51.2108C78.8547 48.5217 79.1667 45.2468 79.1667 40.6742C79.1667 35.8155 77.4704 31.8019 74.2625 28.5952L72.4992 26.8326L73.2189 24.4456C73.8582 22.325 74.0101 19.8157 73.3338 16.9537C73.2214 16.9821 73.1045 17.0132 72.9833 17.0469C70.7523 17.668 67.9668 19.0008 64.6102 21.2445L63.0792 22.2678L61.2919 21.8246C57.8349 20.9674 54.1202 20.5273 50.3699 20.5273C46.1994 20.5273 42.0769 21.0579 38.2686 22.0962L36.41 22.6028L34.8201 21.5152C31.3484 19.1402 28.4644 17.7279 26.1518 17.0681C25.9866 17.021 25.8293 16.9788 25.6799 16.9413C24.873 20.2537 25.1921 22.9752 26.0093 25.0173L26.9891 27.4658L25.1954 29.3992C22.3371 32.4799 20.8333 36.229 20.8333 40.6742C20.8333 44.744 21.3098 48.1164 22.1828 50.6567L23.2732 53.2377C25.9989 58.3523 31.7884 61.4294 42.1107 62.5359L45.8333 62.9349V66.6788C45.8333 69.8017 44.8038 71.5176 42.5296 73.7917C41.6788 74.6426 41.6667 74.6628 41.6667 75.0121L41.5948 75.7824C41.5473 76.035 41.5473 76.6874 41.6129 79.415C41.643 80.6695 41.6602 81.6625 41.6651 82.7001C41.7149 82.9149 41.7225 83.0534 41.7385 83.3484Z" fill="black"/>
</svg>
</div></a>
</div>
</div>
<div class="row">
<div class="col-sm-3 menu">
<h3><button onclick="location.href='index.html'" type="button">Home</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='about.html'" type="button">About Me</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='interests.html'" type="button">Interests</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='contact.html'" type="button">Contact</button></h3>
</div>
</div>
</div>
<footer>
<p id="time"></p>
</footer>
</body>
</html>

55
Lab8/homepage/index.html Normal file
View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
document.addEventListener('DOMContentLoaded', async function() {
while (true){
// get date
var date = new Date();
// convert date to string
var n = date.toDateString();
// get time as string
var time = date.toLocaleTimeString();
document.getElementById('time').innerHTML = n + ' ' + time;
await sleep(999)
};
});
</script>
<link href="styles.css" rel="stylesheet">
<title>Jiri Karlik - Homepage</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron text-center">
<h1>Introduction</h1>
<p>Hi, my name is Jiří Karlík and this is my homepage website for CS50 pset8.</p>
<img class="portrait" src="media/portrait.png" alt="Portrait of Jiri.">
</div>
<div class="container">
<div class="row">
<div class="col-sm-4 menu">
<h3><button onclick="location.href='about.html'" type="button">About Me</button></h3>
</div>
<div class="col-sm-4 menu">
<h3><button onclick="location.href='interests.html'" type="button">Interests</button></h3>
</div>
<div class="col-sm-4 menu">
<h3><button onclick="location.href='contact.html'" type="button">Contact</button></h3>
</div>
</div>
</div>
<footer>
<p id="time"></p>
</footer>
</body>
</html>

View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
document.addEventListener('DOMContentLoaded', async function() {
while (true){
// get date
var date = new Date();
// convert date to string
var n = date.toDateString();
// get time as string
var time = date.toLocaleTimeString();
document.getElementById('time').innerHTML = n + ' ' + time;
await sleep(999)
};
});
</script>
<link href="styles.css" rel="stylesheet">
<title>Jiri Karlik - Interests</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron text-center">
<h1>Interests</h1>
<p>Here you can find list of my hobbies.</p>
</div>
<div class="container">
<div class="row row_last">
<div class="col-sm-12 interests">
<ul>
<li>Gaming</li>
<li>Computer Science</li>
<li>Books</li>
<li>Leatherworking</li>
<li>Cooking</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-sm-3 menu">
<h3><button onclick="location.href='index.html'" type="button">Home</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='about.html'" type="button">About Me</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='interests.html'" type="button">Interests</button></h3>
</div>
<div class="col-sm-3 menu">
<h3><button onclick="location.href='contact.html'" type="button">Contact</button></h3>
</div>
</div>
</div>
<footer>
<p id="time"></p>
</footer>
</body>
</html>

28
Lab8/homepage/styles.css Normal file
View File

@ -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;
}

81
Lab8/trivia/index.html Normal file
View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500&display=swap" rel="stylesheet">
<link href="styles.css" rel="stylesheet">
<title>Trivia!</title>
<script>
// TODO: Add code to check answers to questions
document.addEventListener('DOMContentLoaded', function() {
// check for red/green buttons
let ok = document.querySelector('.ok')
document.querySelector('.ok').onclick = function() {
ok.style.backgroundColor = 'green';
document.querySelector("#feedback1").innerHTML = "Correct";
};
let noks = document.querySelectorAll('.nok')
for(let i = 0; i < noks.length; i++){
noks[i].addEventListener("click",function(){
noks[i].style.backgroundColor = 'red';
document.querySelector("#feedback1").innerHTML = "Incorrect";
});
};
// check for text field
document.querySelector("#check").addEventListener("click",function(){
let input = document.querySelector("input");
if (input.value === "Switzerland"){
input.style.backgroundColor = "green";
document.querySelector("#feedback2").innerHTML = "Correct";
} else {
input.style.backgroundColor = "red";
document.querySelector("#feedback2").innerHTML = "Incorrect";
}
});
});
</script>
</head>
<body>
<div class="jumbotron">
<h1>Trivia!</h1>
</div>
<div class="container">
<div class="section">
<h2>Part 1: Multiple Choice </h2>
<hr>
<!-- TODO: Add multiple choice question here -->
<h3>What is the approximate ratio of people to sheep in New Zealand?</h3>
<button class = "nok">6 poeple per 1 sheep</button>
<button class = "ok">1 person per 6 sheeps</button>
<button class = "nok">3 poeple per 1 sheep</button>
<button class = "nok">1 person per 1 sheep</button>
<button class = "nok">1 person per 3 sheeps</button>
<p id="feedback1"></p>
</div>
<div class="section">
<h2>Part 2: Free Response</h2>
<hr>
<!-- TODO: Add free response question here -->
<h3>In which country is it illegal to own only one guinea pig, as alone guinea pig might get lonely.</h3>
<input type="text"></input>
<button id="check">Check Answer</button>
<p id="feedback2"></p>
</div>
</div>
</body>
</html>

62
Lab8/trivia/styles.css Normal file
View File

@ -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;
}

View File

@ -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"))

BIN
Lab9/birthdays/birthdays.db Normal file

Binary file not shown.

View File

@ -0,0 +1,83 @@
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;
text-align: center;
width: 90%;
}
.jumbotron {
background-color: #477bff;
color: #fff;
margin-bottom: 2rem;
padding: 2rem 1rem;
text-align: center;
}
.section {
padding-bottom: 1rem;
padding-left: 2rem;
padding-right: 2rem;
padding-top: 0.5rem;
}
.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"], input[type="number"] {
line-height: 1.8;
width: 25%;
}
input[type="text"]:hover, input[type="number"]:hover {
background-color: #f5f5f5;
transition: color 2s ease-in-out, background-color 0.15s ease-in-out;
}
table {
background-color: transparent;
margin-bottom: 1rem;
width: 100%;
}
table th,
table td {
padding: 0.75rem;
vertical-align: middle;
}
tbody tr:nth-of-type(odd) {
background-color: rgb(179, 208, 255, 0.3)
}

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500&display=swap" rel="stylesheet">
<link href="/static/styles.css" rel="stylesheet">
<title>Birthdays</title>
</head>
<body>
<div class="jumbotron">
<h1>Birthdays</h1>
</div>
<div class="container">
<div class="section">
<h2>Add a Birthday</h2>
<!-- TODO: Create a form for users to submit a name, a month, and a day -->
<form action = "/" method ="post">
<input type=text name="name" placeholder="Name">
<input type=number name="month" placeholder="Month" min="1" max="12">
<input type=number name="day" placeholder="Day" min="1" max="31">
<input type=submit value="Add birthday">
</form>
</div>
<div class="section">
<h2>All Birthdays</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Birthday</th>
</tr>
</thead>
<tbody>
<!-- TODO: Loop through the database entries to display them in this table -->
{% for birthday in birthdays%}
<tr>
<td>{{birthday.name}}</td>
<td>{{birthday.day}}/{{birthday.month}}</td>
</tr>
{% endfor%}
</tbody>
</table>
</div>
</div>
</body>
</html>

330
Lab9/finance/application.py Normal file
View File

@ -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)

BIN
Lab9/finance/finance.db Normal file

Binary file not shown.

64
Lab9/finance/helpers.py Normal file
View File

@ -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}"

View File

@ -0,0 +1,4 @@
cs50
Flask
Flask-Session
requests

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,47 @@
nav .navbar-brand
{
/* size for brand */
font-size: xx-large;
}
/* Colors for brand */
nav .navbar-brand .blue
{
color: #537fbe;
}
nav .navbar-brand .red
{
color: #ea433b;
}
nav .navbar-brand .yellow
{
color: #f5b82e;
}
nav .navbar-brand .green
{
color: #2e944b;
}
main .form-control
{
/* Center form controls */
display: inline-block;
/* Override Bootstrap's 100% width for form controls */
width: auto;
}
main
{
/* Scroll horizontally as needed */
overflow-x: auto;
/* Center contents */
text-align: center;
}
main img
{
/* Constrain images on small screens */
max-width: 100%;
}

View File

@ -0,0 +1,9 @@
{% extends "layout.html" %}
{% block title %}
Apology
{% endblock %}
{% block main %}
<img alt="{{ top }}" class="border" src="http://memegen.link/custom/{{ top | urlencode }}/{{ bottom | urlencode }}.jpg?alt=https://i.imgur.com/CsCgN7Ll.png" title="{{ top }}">
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "layout.html" %}
{% block title %}
Buy
{% endblock %}
{% block main %}
<form action="/buy" method="post">
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" name="symbol" placeholder="Symbol" type="text">
</div>
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" name="shares" placeholder="Shares" type="number" min="1">
</div>
<button class="btn btn-primary" type="submit">Buy</button>
</form>
{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends "layout.html" %}
{% block title %}
History
{% endblock %}
{% block main %}
<table class="table">
<thead>
<tr>
<th class="text-start">Symbol</th>
<th class="text-end">Shares</th>
<th class="text-end">Price</th>
<th class="text-end">Transacted</th>
</tr>
</thead>
<tbody>
{% for row in history %}
<tr>
<td>{{ row.symbol }}</td>
<td>{{ row.shares }}</td>
<td>{{ row.price }}</td>
<td>{{ row.transacted }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -0,0 +1,39 @@
{% extends "layout.html" %}
{% block title %}
Index
{% endblock %}
{% block main %}
<table class="table">
<thead>
<tr>
<th class="text-start">Symbol</th>
<th class="text-end">Name</th>
<th class="text-end">Shares</th>
<th class="text-end">Price</th>
<th class="text-end">Total</th>
</tr>
</thead>
<tbody>
{% for row in portfolio %}
<tr>
<td>{{ row.symbol }}</td>
<td>{{ row.name }}</td>
<td>{{ row.amount }}</td>
<td>{{ row.price }}</td>
<td>{{ row.total }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="border-0 fw-bold text-end" colspan="4">Cash</td>
<td class="border-0 text-end">{{ cash }}</td>
</tr>
<tr>
<td class="border-0 fw-bold text-end" colspan="4">TOTAL</td>
<td class="border-0 w-bold text-end">{{ grand_total }}</td>
</tfoot>
</table>
{% endblock %}

View File

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, width=device-width">
<!-- http://getbootstrap.com/docs/4.5/ -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<!-- https://favicon.io/emoji-favicons/money-mouth-face/ -->
<link href="/static/favicon.ico" rel="icon">
<link href="/static/styles.css" rel="stylesheet">
<!-- http://getbootstrap.com/docs/4.5/ -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<title>C$50 Finance: {% block title %}{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light border">
<a class="navbar-brand" href="/"><span class="blue">C</span><span class="red">$</span><span class="yellow">5</span><span class="green">0</span> <span class="red">Finance</span></a>
<button aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#navbar" data-toggle="collapse" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
{% if session.user_id %}
<ul class="navbar-nav mr-auto mt-2">
<li class="nav-item"><a class="nav-link" href="/quote">Quote</a></li>
<li class="nav-item"><a class="nav-link" href="/buy">Buy</a></li>
<li class="nav-item"><a class="nav-link" href="/sell">Sell</a></li>
<li class="nav-item"><a class="nav-link" href="/history">History</a></li>
</ul>
<ul class="navbar-nav ml-auto mt-2">
<li class="nav-item"><a class="nav-link" href="/logout">Log Out</a></li>
</ul>
{% else %}
<ul class="navbar-nav ml-auto mt-2">
<li class="nav-item"><a class="nav-link" href="/register">Register</a></li>
<li class="nav-item"><a class="nav-link" href="/login">Log In</a></li>
</ul>
{% endif %}
</div>
</nav>
{% if get_flashed_messages() %}
<header>
<div class="alert alert-primary border text-center" role="alert">
{{ get_flashed_messages() | join(" ") }}
</div>
</header>
{% endif %}
<main class="container p-5">
{% block main %}{% endblock %}
</main>
<footer class="small text-center text-muted">
Data provided for free by <a href="https://iextrading.com/developer">IEX</a>. View <a href="https://iextrading.com/api-exhibit-a/">IEXs Terms of Use</a>.
</footer>
</body>
</html>

View File

@ -0,0 +1,17 @@
{% extends "layout.html" %}
{% block title %}
Log In
{% endblock %}
{% block main %}
<form action="/login" method="post">
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" type="text">
</div>
<div class="form-group">
<input class="form-control" name="password" placeholder="Password" type="password">
</div>
<button class="btn btn-primary" type="submit">Log In</button>
</form>
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends "layout.html" %}
{% block title %}
Quote
{% endblock %}
{% block main %}
<form action="/quote" method="post">
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" name="symbol" placeholder="Symbol" type="text">
</div>
<button class="btn btn-primary" type="submit">Quote</button>
</form>
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "layout.html" %}
{% block title %}
Quoted
{% endblock %}
{% block main %}
<p> A share of {{name}} ({{symbol}}) costs {{price}} </p>
{% endblock %}

View File

@ -0,0 +1,20 @@
{% extends "layout.html" %}
{% block title %}
Register
{% endblock %}
{% block main %}
<form action="/register" method="post">
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" name="username" placeholder="Username" type="text">
</div>
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" name="password" placeholder="Password" type="password">
</div>
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" name="confirmation" placeholder="Password (again)" type="password">
</div>
<button class="btn btn-primary" type="submit">Register</button>
</form>
{% endblock %}

View File

@ -0,0 +1,22 @@
{% extends "layout.html" %}
{% block title %}
Buy
{% endblock %}
{% block main %}
<form action="/sell" method="post">
<div class="mb-3">
<select class="form-select mx-auto w-auto" name="symbol">
<option disabled="" selected="">Symbol</option>
{% for row in portfolio %}
<option value="{{ row.symbol }}">{{ row.symbol }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<input autocomplete="off" class="form-control mx-auto w-auto" min="0" name="shares" placeholder="Shares" type="number">
</div>
<button class="btn btn-primary" type="submit">Sell</button>
</form>
{% endblock %}