Transfer to Gitea
This commit is contained in:
commit
5928464304
Binary file not shown.
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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';
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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")
|
|
@ -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()
|
|
@ -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)
|
|
@ -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()
|
|
@ -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))
|
|
@ -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()
|
|
@ -0,0 +1,3 @@
|
||||||
|
The THIEF is: Ernest
|
||||||
|
The thief ESCAPED TO: London
|
||||||
|
The ACCOMPLICE is: Berthold
|
|
@ -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");
|
|
@ -0,0 +1 @@
|
||||||
|
select title from movies where year = 2008;
|
|
@ -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);
|
|
@ -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;
|
|
@ -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");
|
|
@ -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);
|
|
@ -0,0 +1 @@
|
||||||
|
select birth from people where name = "Emma Stone";
|
|
@ -0,0 +1 @@
|
||||||
|
select title from movies where year >= 2018 order by title asc;
|
|
@ -0,0 +1 @@
|
||||||
|
select count(movie_id) from ratings where rating = 10.0
|
|
@ -0,0 +1 @@
|
||||||
|
select title, year from movies where title like "Harry Potter%" order by year asc;
|
|
@ -0,0 +1,3 @@
|
||||||
|
select avg(rating) from ratings
|
||||||
|
join movies on movies.id = ratings.movie_id
|
||||||
|
where year = 2012;
|
|
@ -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;
|
|
@ -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");
|
|
@ -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;
|
|
@ -0,0 +1 @@
|
||||||
|
select name from songs;
|
|
@ -0,0 +1 @@
|
||||||
|
select name from songs order by tempo;
|
|
@ -0,0 +1 @@
|
||||||
|
select name from songs order by duration_ms desc limit 5;
|
|
@ -0,0 +1 @@
|
||||||
|
select name from songs where danceability>0.75 and energy > 0.75 and valence >0.75;
|
|
@ -0,0 +1 @@
|
||||||
|
select avg(energy) from songs;
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
select name from songs where artist_id = (select id from artists where name = "Post Malone");
|
|
@ -0,0 +1 @@
|
||||||
|
select avg(energy) from songs where artist_id = (select id from artists where name = "Drake");
|
|
@ -0,0 +1 @@
|
||||||
|
select name from songs where name like "%feat.%";
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||||
|
}
|
|
@ -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>
|
|
@ -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;
|
||||||
|
}
|
|
@ -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"))
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
|
@ -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)
|
Binary file not shown.
|
@ -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}"
|
|
@ -0,0 +1,4 @@
|
||||||
|
cs50
|
||||||
|
Flask
|
||||||
|
Flask-Session
|
||||||
|
requests
|
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
|
@ -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%;
|
||||||
|
}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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/">IEX’s Terms of Use</a>.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Quoted
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<p> A share of {{name}} ({{symbol}}) costs {{price}} </p>
|
||||||
|
{% endblock %}
|
|
@ -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 %}
|
|
@ -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 %}
|
Loading…
Reference in New Issue