From 1596e1a17f38d2ddf8d8dcf68e97776d20b50f10 Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Sun, 6 Jun 2021 03:05:18 +0700 Subject: [PATCH 1/7] Add all files at once (Forgot to add it feature by feature) --- .env | 2 + .gitignore | 1 + csv_reader.py | 10 ++ html_processing.py | 86 ++++++++++ main.py | 410 ++++++++++++++++++++++++++++++++++++++++++++ sorting.py | 99 +++++++++++ sorting_results.sql | 81 +++++++++ 7 files changed, 689 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 csv_reader.py create mode 100644 html_processing.py create mode 100644 main.py create mode 100644 sorting.py create mode 100644 sorting_results.sql diff --git a/.env b/.env new file mode 100644 index 0000000..f0f6f6c --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +DB_PASSWORD='Gaussian021001' +SECRET_KEY='8wFz1OCrsQT170Z95dTre0ken12B5Dz3' \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/csv_reader.py b/csv_reader.py new file mode 100644 index 0000000..d9b21e9 --- /dev/null +++ b/csv_reader.py @@ -0,0 +1,10 @@ +import csv + +# Read a csv file and get a column in it +def column_csv_reader(filename, column_no): + with open(filename, 'r') as csv_file: + reader = csv.reader(csv_file, delimiter=',') + list_of_row = [] + for row in reader: + list_of_row.append(row[column_no+1]) + return list_of_row diff --git a/html_processing.py b/html_processing.py new file mode 100644 index 0000000..93db4f9 --- /dev/null +++ b/html_processing.py @@ -0,0 +1,86 @@ +# Function to make an html page for the specified algorithm +def sorting_page(algoritma, token): + return f""" + + + + + {algoritma} Sort + + +
+ +

+ +

+ + + + +

+

+ Back to Main Menu +
+ + + """ + +def log_page(): + return """ + + + + + Login + + +
+ +

+ +

+

+ Back to Main Menu +
+ + + """ + +def sign_page(): + return """ + + + + + Signup + + +
+ +

+ +

+ +

+

+ Back to Main Menu +
+ + + """ + +# Function to turn a list into an html table +def list_to_table(l): + table_script = """ + + + + """ + for i in l: + table_script += f"\n" + table_script += """ + + +
{i}
+ """ + return table_script diff --git a/main.py b/main.py new file mode 100644 index 0000000..8ea5d12 --- /dev/null +++ b/main.py @@ -0,0 +1,410 @@ +import os +import time +import jwt +import uuid +import re +from dotenv import load_dotenv +from flask import Flask, request, session, jsonify, make_response +from flask_mysqldb import MySQL +from werkzeug.utils import secure_filename +from werkzeug.security import generate_password_hash, check_password_hash +from datetime import datetime, timedelta +from functools import wraps + +from csv_reader import * +from sorting import * +from html_processing import * + +app = Flask(__name__) +app.config['DEBUG'] = True + +load_dotenv() + +app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') + +app.config['MYSQL_HOST'] = 'localhost' +app.config['MYSQL_USER'] = 'root' +app.config['MYSQL_PASSWORD'] = os.getenv('DB_PASSWORD') +app.config['MYSQL_DB'] = 'sorting_results' + +mysql = MySQL(app) + +@app.route('/') +def home_page(): + return """ + + + + + Sorting API Homepage + + +

Sorting API

+
by : Daffa Ananda Pratama Resyaly -- 13519107
+ Login
+ Signup + + + """ + +# A function to process csv input from the user to the sorted one and can be used flexibly in this program +def csv_processing(algoritma, token): + # Initiate mysql connection & cursor + conn = mysql.connection + cursor = conn.cursor() + + # Start time of the algorithm + start_time = time.time() + + # Save the csv file from the user to 'csv_inputs' folder + try: + f = request.files['csv_file'] + file_path = os.path.join('csv_inputs', secure_filename(f.filename)) + f.save(file_path) + except FileNotFoundError: + w = algoritma.split() + print(w[0].lower()) + return f""" +

Please Input the CSV File!

+ Back to {algoritma} + """ + + # Get Column Number and Sorting Orientation (Ascending or Descending) + try: + column_no = int(request.form.get('column_no')) + except ValueError: + w = algoritma.split() + print(w[0].lower()) + return f""" +

Please Input the Column No.!

+ Back to {algoritma} + """ + + # try: + orientation = request.form.get('orientation') + # except ValueError: + # w = algoritma.split() + # print(w[0].lower()) + # return f""" + #

Please Input the Sorting Orientation (ASC/DESC)!

+ # Back to {algoritma} + # """ + + # Get list of row for the specified column + list_of_row = column_csv_reader(file_path, column_no) + + # Start sorting algorithm + sorted_list = [] + # Select which sort that the user wants to use + if algoritma == 'Selection Sort': + sorted_list = selection_sort(list_of_row, orientation) + elif algoritma == 'Bubble Sort': + sorted_list = bubble_sort(list_of_row, orientation) + elif algoritma == 'Insertion Sort': + sorted_list = insertion_sort(list_of_row, orientation) + elif algoritma == 'Merge Sort': + sorted_list = merge_sort(list_of_row, orientation) + + # Change the sorted_list to comma separated value + csv_result = ','.join(sorted_list) + + # Get the execution time (Time now - Start time) + execution_time = "{:.4f}".format(time.time() - start_time) + + # Insert the sorting result into table 'sorts' + insertion = f""" + INSERT INTO sorts (tanggal_waktu, algoritma, sorting_result, execution_time) + VALUES(%s, %s, %s, %s) + """ + cursor.execute(insertion, (datetime.now(), algoritma, csv_result, execution_time)) + conn.commit() + + # Get the sorting result's ID from the database + selection = """ + SELECT id + FROM sorts + ORDER BY id DESC + LIMIT 1 + """ + cursor.execute(selection) + sorting_id = cursor.fetchall()[0][0] + + # Close the cursor + cursor.close() + + # Return the HTML Table of the sorted column, along with the sorting result ID and execution time + table = list_to_table(sorted_list) + return f"""{table} +

THE SORTING RESULT HAS BEEN INSERTED INTO THE DATABASE

+

Execution Time : {execution_time}

+

ID : {sorting_id}

+ Back to Main Menu + """ + +def authenticate(f): + @wraps(f) + def decorated(*args, **kwargs): + + token = request.args.get('token') + # return 401 if token is not passed + if not token: + return "

401 Error

Token is Missing!

", 401 + + try: + # decoding the payload to fetch the stored details + data = jwt.decode(token, app.config['SECRET_KEY']) + except: + return "

401 Error

Token is Invalid!

", 401 + # returns the current logged in users contex to the routes + return f(*args, **kwargs) + + return decorated + +@app.route('/mainpage') +@authenticate +def mainpage(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return f""" + + + + + Sorting API Mainpage + + +

Sorting API

+
by : Daffa Ananda Pratama Resyaly -- 13519107
+ Selection Sort + Bubble Sort + Merge Sort

+ Sorting Result + + + """ + +@app.route('/login') +def login_page(): + return log_page() + +@app.route('/login', methods=['POST']) +def login(): + conn = mysql.connection + cursor = conn.cursor() + + # creates dictionary of form data + auth = request.form + + could_not_verify_message = """ +

Could not verify

+ Go to Login Page
+ Go to Homepage + """ + + if not auth or not auth.get('username') or not auth.get('password'): + # returns 401 if any username or / and password is missing + return make_response( + could_not_verify_message, + 401, + {'WWW-Authenticate' : 'Basic realm ="Login required !!"'} + ) + + check_username = f""" + SELECT * + FROM user + WHERE username='{auth.get('username')}' + """ + user = cursor.execute(check_username) + + if not user: + # returns 401 if user does not exist + return make_response( + could_not_verify_message, + 401, + {'WWW-Authenticate' : 'Basic realm ="User does not exist !!"'} + ) + + fetched = cursor.fetchall()[0] + public_id = fetched[1] + username = fetched[3] + password = fetched[4] + cursor.close() + + if check_password_hash(password, auth.get('password')): + # generates the JWT Token + token = jwt.encode({ + 'public_id': public_id, + 'exp' : datetime.utcnow() + timedelta(minutes = 30) + }, app.config['SECRET_KEY']) + + session['logged_in'] = True + return make_response(jsonify({'token' : token.decode('UTF-8')}), 201) + + # returns 403 if password is wrong + return make_response( + could_not_verify_message, + 403, + {'WWW-Authenticate' : 'Basic realm ="Wrong Password !!"'} + ) + +@app.route('/signup') +def signup_page(): + return sign_page() + +@app.route('/signup', methods=['POST']) +def signup(): + conn = mysql.connection + cursor = conn.cursor() + # creates a dictionary of the form data + data = request.form + + # gets name, username and password + name, username = data.get('name'), data.get('username') + password = data.get('password') + + # checking for existing user + select_user = f""" + SELECT * + FROM user + WHERE username='{username}' + """ + user = cursor.execute(select_user) + if not user: + # database ORM object + insert_user = f""" + INSERT INTO user (public_id, name, username, password) + VALUES ('{str(uuid.uuid4())}', '{name}', '{username}', '{generate_password_hash(password)}') + """ + # insert user + cursor.execute(insert_user) + conn.commit() + cursor.close() + + successful_message = """ +

Successfully registered.


+ Go to Login Page
+ Go to Homepage + """ + + return make_response(successful_message, 201) + else: + # returns 202 if user already exists + already_exist_message = """ +

User already exists. Please Log in.

+ Go to Login Page
+ Go to Homepage + """ + return make_response(already_exist_message, 202) + +@app.route('/sort/selection') +@authenticate +def selection_page(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return sorting_page('Selection', cleaned_token) + +@app.route('/sort/selection', methods=['POST']) +@authenticate +def selection(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return csv_processing("Selection Sort", cleaned_token) + +@app.route('/sort/bubble') +@authenticate +def bubble_page(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return sorting_page('Bubble', cleaned_token) + +@app.route('/sort/bubble', methods=['POST']) +@authenticate +def bubble(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return csv_processing("Bubble Sort", cleaned_token) + +@app.route('/sort/insertion') +@authenticate +def insertion_page(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return sorting_page('Insertion', cleaned_token) + +@app.route('/sort/insertion', methods=['POST']) +@authenticate +def insertion(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return csv_processing("Insertion Sort", cleaned_token) + +@app.route('/sort/merge') +@authenticate +def merge_page(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return sorting_page('Merge', cleaned_token) + +@app.route('/sort/merge', methods=['POST']) +@authenticate +def merge(): + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + return csv_processing("Merge Sort", cleaned_token) + +@app.route('/sort/result', methods=['GET']) +@authenticate +def result(): + conn = mysql.connection + cursor = conn.cursor() + token = str(request.get_json) + cleaned_token = re.search('\?token=(.*)\'', token).group(1) + if 'id' in request.args: + id = request.args['id'] + selection = f""" + SELECT * + FROM sorts + WHERE id={id} + """ + cursor.execute(selection) + result = cursor.fetchall() + cursor.close() + if result: + results = result[0] + table = list_to_table(results[3].split(',')) + return f"""

ID : {results[0]}

+

Date : {results[1]}

+

Algorithm : {results[2]}

+

Sorting Result : {results[3]}

+ {table} +

Execution Time : {results[4]}

+ Back to Main Menu + """ + else: + return f"

No Data Found with ID {id} in the Database!

Back to Main Menu" + else: + selection = """ + SELECT * + FROM sorts + ORDER BY id DESC + LIMIT 1 + """ + cursor.execute(selection) + result = cursor.fetchall() + cursor.close() + if result: + results = result[0] + table = list_to_table(results[3].split(',')) + return f"""

ID : {results[0]}

+

Date : {results[1]}

+

Algorithm : {results[2]}

+

Sorting Result :

+ {table} +

Execution Time : {results[4]}

+ Back to Main Menu + """ + else: + return f"

No Data Found in the Database!

Back to Main Menu" + +if __name__ == '__main__': + app.run() diff --git a/sorting.py b/sorting.py new file mode 100644 index 0000000..60b9837 --- /dev/null +++ b/sorting.py @@ -0,0 +1,99 @@ +def selection_sort(l, orientation): + if orientation == 'ascending': + for i in range (len(l)): + idx_min = i + for j in range (i+1, len(l)): + if l[j] < l[idx_min]: + idx_min = j + l[i], l[idx_min] = l[idx_min], l[i] + elif orientation == 'descending': + for i in range (len(l)): + idx_min = i + for j in range (i+1, len(l)): + if l[j] > l[idx_min]: + idx_min = j + l[i], l[idx_min] = l[idx_min], l[i] + return l + +def bubble_sort(l, orientation): + if orientation == 'ascending': + for i in range (len(l)): + for j in range (len(l)-i-1): + if l[j+1] < l[j]: + l[j], l[j+1] = l[j+1], l[j] + elif orientation == 'descending': + for i in range (len(l)): + for j in range (len(l)-i-1): + if l[j+1] > l[j]: + l[j], l[j+1] = l[j+1], l[j] + return l + +def insertion_sort(l, orientation): + if orientation == 'ascending': + for i in range (1, len(l)): + key = l[i] + j = i-1 + while j >= 0 and key < l[j]: + l[j+1] = l[j] + j -= 1 + l[j+1] = key + +def merge_sort(l, orientation): + if orientation == 'ascending': + if len(l) > 1: + mid = len(l)//2 + left = l[:mid] + right = l[mid:] + merge_sort(left, orientation) + merge_sort(right, orientation) + + i = j = k = 0 + + while i < len(left) and j < len(right): + if left[i] < right[j]: + l[k] = left[i] + i += 1 + else: + l[k] = right[j] + j += 1 + k += 1 + + while i < len(left): + l[k] = left[i] + i += 1 + k += 1 + + while j < len(right): + l[k] = right[j] + j += 1 + k += 1 + return l + elif orientation == 'descending': + if len(l) > 1: + mid = len(l)//2 + left = l[:mid] + right = l[mid:] + merge_sort(left, orientation) + merge_sort(right, orientation) + + i = j = k = 0 + + while i < len(left) and j < len(right): + if left[i] > right[j]: + l[k] = left[i] + i += 1 + else: + l[k] = right[j] + j += 1 + k += 1 + + while i < len(left): + l[k] = left[i] + i += 1 + k += 1 + + while j < len(right): + l[k] = right[j] + j += 1 + k += 1 + return l diff --git a/sorting_results.sql b/sorting_results.sql new file mode 100644 index 0000000..decdb6a --- /dev/null +++ b/sorting_results.sql @@ -0,0 +1,81 @@ +-- MariaDB dump 10.18 Distrib 10.5.8-MariaDB, for Win64 (AMD64) +-- +-- Host: localhost Database: sorting_results +-- ------------------------------------------------------ +-- Server version 10.5.8-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `sorts` +-- + +DROP TABLE IF EXISTS `sorts`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sorts` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `tanggal_waktu` date DEFAULT NULL, + `algoritma` varchar(255) DEFAULT NULL, + `sorting_result` varchar(255) DEFAULT NULL, + `execution_time` float DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `sorts` +-- + +LOCK TABLES `sorts` WRITE; +/*!40000 ALTER TABLE `sorts` DISABLE KEYS */; +/*!40000 ALTER TABLE `sorts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `public_id` varchar(50) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `username` varchar(50) DEFAULT NULL, + `password` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `public_id` (`public_id`), + UNIQUE KEY `username` (`username`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2021-06-06 3:04:30 From 2590477069849b8f54fac779cc0b47cebbc4fc3c Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Wed, 9 Jun 2021 15:15:19 +0700 Subject: [PATCH 2/7] Update HTML Table --- csv_reader.py | 2 +- html_processing.py | 15 ++++---- main.py | 18 +++++----- sorting.py | 90 +++++++++++++++++++++++++--------------------- 4 files changed, 69 insertions(+), 56 deletions(-) diff --git a/csv_reader.py b/csv_reader.py index d9b21e9..2d81d94 100644 --- a/csv_reader.py +++ b/csv_reader.py @@ -6,5 +6,5 @@ def column_csv_reader(filename, column_no): reader = csv.reader(csv_file, delimiter=',') list_of_row = [] for row in reader: - list_of_row.append(row[column_no+1]) + list_of_row.append(row[column_no-1]) return list_of_row diff --git a/html_processing.py b/html_processing.py index 93db4f9..95b8593 100644 --- a/html_processing.py +++ b/html_processing.py @@ -11,7 +11,7 @@ def sorting_page(algoritma, token):


- +

@@ -70,16 +70,19 @@ def sign_page(): """ # Function to turn a list into an html table -def list_to_table(l): - table_script = """ +def list_to_table(name, l): + table_script = f""" - + + + + """ for i in l: - table_script += f"\n" + table_script += f"\n" table_script += """ - +
{name}
{i}{i}
""" diff --git a/main.py b/main.py index 8ea5d12..859f08b 100644 --- a/main.py +++ b/main.py @@ -66,7 +66,7 @@ def csv_processing(algoritma, token): print(w[0].lower()) return f"""

Please Input the CSV File!

- Back to {algoritma} + Back to {algoritma} """ # Get Column Number and Sorting Orientation (Ascending or Descending) @@ -77,7 +77,7 @@ def csv_processing(algoritma, token): print(w[0].lower()) return f"""

Please Input the Column No.!

- Back to {algoritma} + Back to {algoritma} """ # try: @@ -133,10 +133,10 @@ def csv_processing(algoritma, token): cursor.close() # Return the HTML Table of the sorted column, along with the sorting result ID and execution time - table = list_to_table(sorted_list) + table = list_to_table(sorted_list[0], sorted_list[1:]) return f"""{table}

THE SORTING RESULT HAS BEEN INSERTED INTO THE DATABASE

-

Execution Time : {execution_time}

+

Execution Time : {execution_time} second(s)

ID : {sorting_id}

Back to Main Menu """ @@ -371,13 +371,14 @@ def result(): cursor.close() if result: results = result[0] - table = list_to_table(results[3].split(',')) + csv_list = results[3].split(',') + table = list_to_table(csv_list[0], csv_list[1:]) return f"""

ID : {results[0]}

Date : {results[1]}

Algorithm : {results[2]}

Sorting Result : {results[3]}

{table} -

Execution Time : {results[4]}

+

Execution Time : {results[4]} second(s)

Back to Main Menu """ else: @@ -394,13 +395,14 @@ def result(): cursor.close() if result: results = result[0] - table = list_to_table(results[3].split(',')) + csv_list = results[3].split(',') + table = list_to_table(csv_list[0], csv_list[1:]) return f"""

ID : {results[0]}

Date : {results[1]}

Algorithm : {results[2]}

Sorting Result :

{table} -

Execution Time : {results[4]}

+

Execution Time : {results[4]} second(s)

Back to Main Menu """ else: diff --git a/sorting.py b/sorting.py index 60b9837..5333224 100644 --- a/sorting.py +++ b/sorting.py @@ -1,49 +1,55 @@ def selection_sort(l, orientation): + l1 = l[1:] if orientation == 'ascending': - for i in range (len(l)): + for i in range (len(l1)): idx_min = i - for j in range (i+1, len(l)): - if l[j] < l[idx_min]: + for j in range (i+1, len(l1)): + if l1[j] < l1[idx_min]: idx_min = j - l[i], l[idx_min] = l[idx_min], l[i] + l1[i], l1[idx_min] = l1[idx_min], l1[i] elif orientation == 'descending': - for i in range (len(l)): + for i in range (len(l1)): idx_min = i - for j in range (i+1, len(l)): - if l[j] > l[idx_min]: + for j in range (i+1, len(l1)): + if l1[j] > l1[idx_min]: idx_min = j - l[i], l[idx_min] = l[idx_min], l[i] - return l + l1[i], l1[idx_min] = l1[idx_min], l1[i] + l1.insert(0,l[0]) + return l1 def bubble_sort(l, orientation): + l1 = l[1:] if orientation == 'ascending': - for i in range (len(l)): - for j in range (len(l)-i-1): - if l[j+1] < l[j]: - l[j], l[j+1] = l[j+1], l[j] + for i in range (len(l1)): + for j in range (len(l1)-i-1): + if l1[j+1] < l1[j]: + l1[j], l1[j+1] = l1[j+1], l1[j] elif orientation == 'descending': - for i in range (len(l)): - for j in range (len(l)-i-1): - if l[j+1] > l[j]: - l[j], l[j+1] = l[j+1], l[j] - return l + for i in range (len(l1)): + for j in range (len(l1)-i-1): + if l1[j+1] > l1[j]: + l1[j], l1[j+1] = l1[j+1], l1[j] + l1.insert(0,l[0]) + return l1 def insertion_sort(l, orientation): + l1 = l[1:] if orientation == 'ascending': - for i in range (1, len(l)): - key = l[i] + for i in range (1, len(l1)): + key = l1[i] j = i-1 - while j >= 0 and key < l[j]: - l[j+1] = l[j] + while j >= 0 and key < l1[j]: + l1[j+1] = l1[j] j -= 1 - l[j+1] = key + l1[j+1] = key def merge_sort(l, orientation): + l1 = l[1:] if orientation == 'ascending': - if len(l) > 1: - mid = len(l)//2 - left = l[:mid] - right = l[mid:] + if len(l1) > 1: + mid = len(l1)//2 + left = l1[:mid] + right = l1[mid:] merge_sort(left, orientation) merge_sort(right, orientation) @@ -51,28 +57,29 @@ def merge_sort(l, orientation): while i < len(left) and j < len(right): if left[i] < right[j]: - l[k] = left[i] + l1[k] = left[i] i += 1 else: - l[k] = right[j] + l1[k] = right[j] j += 1 k += 1 while i < len(left): - l[k] = left[i] + l1[k] = left[i] i += 1 k += 1 while j < len(right): - l[k] = right[j] + l1[k] = right[j] j += 1 k += 1 - return l + l1.insert(0,l[0]) + return l1 elif orientation == 'descending': - if len(l) > 1: - mid = len(l)//2 - left = l[:mid] - right = l[mid:] + if len(l1) > 1: + mid = len(l1)//2 + left = l1[:mid] + right = l1[mid:] merge_sort(left, orientation) merge_sort(right, orientation) @@ -80,20 +87,21 @@ def merge_sort(l, orientation): while i < len(left) and j < len(right): if left[i] > right[j]: - l[k] = left[i] + l1[k] = left[i] i += 1 else: - l[k] = right[j] + l1[k] = right[j] j += 1 k += 1 while i < len(left): - l[k] = left[i] + l1[k] = left[i] i += 1 k += 1 while j < len(right): - l[k] = right[j] + l1[k] = right[j] j += 1 k += 1 - return l + l1.insert(0,l[0]) + return l1 From 50fb9d96a524ed10c0bf54d0c9e185a47c5a5381 Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Wed, 9 Jun 2021 18:31:21 +0700 Subject: [PATCH 3/7] Update csv_reader function; Fix bugs; Add comments --- csv_reader.py | 22 ++++++++-- main.py | 57 ++++++++++++------------ sorting.py | 93 +++++++++++++++++----------------------- test/addresses.csv | 6 +++ test/airtravel.csv | 13 ++++++ test/crash_catalonia.csv | 9 ++++ test/hurricanes.csv | 10 +++++ 7 files changed, 123 insertions(+), 87 deletions(-) create mode 100644 test/addresses.csv create mode 100644 test/airtravel.csv create mode 100644 test/crash_catalonia.csv create mode 100644 test/hurricanes.csv diff --git a/csv_reader.py b/csv_reader.py index 2d81d94..6aa3b89 100644 --- a/csv_reader.py +++ b/csv_reader.py @@ -1,10 +1,26 @@ +import pandas as pd import csv # Read a csv file and get a column in it def column_csv_reader(filename, column_no): - with open(filename, 'r') as csv_file: + with open(filename) as csv_file: + # Use ',' delimiter for csv reader = csv.reader(csv_file, delimiter=',') + column_name = '' list_of_row = [] + i = 0 for row in reader: - list_of_row.append(row[column_no-1]) - return list_of_row + try: + # Column name must be on the first row + if i == 0: + column_name += row[column_no-1] + i += 1 + + # List of tuples + else: + list_of_row.append(row[column_no-1].strip()) + i += 1 + except IndexError: + pass + + return column_name, list_of_row diff --git a/main.py b/main.py index 859f08b..f628cc8 100644 --- a/main.py +++ b/main.py @@ -63,7 +63,6 @@ def csv_processing(algoritma, token): f.save(file_path) except FileNotFoundError: w = algoritma.split() - print(w[0].lower()) return f"""

Please Input the CSV File!

Back to {algoritma} @@ -74,7 +73,6 @@ def csv_processing(algoritma, token): column_no = int(request.form.get('column_no')) except ValueError: w = algoritma.split() - print(w[0].lower()) return f"""

Please Input the Column No.!

Back to {algoritma} @@ -91,7 +89,8 @@ def csv_processing(algoritma, token): # """ # Get list of row for the specified column - list_of_row = column_csv_reader(file_path, column_no) + column_name = column_csv_reader(file_path, column_no)[0] + list_of_row = column_csv_reader(file_path, column_no)[1] # Start sorting algorithm sorted_list = [] @@ -100,13 +99,11 @@ def csv_processing(algoritma, token): sorted_list = selection_sort(list_of_row, orientation) elif algoritma == 'Bubble Sort': sorted_list = bubble_sort(list_of_row, orientation) - elif algoritma == 'Insertion Sort': - sorted_list = insertion_sort(list_of_row, orientation) elif algoritma == 'Merge Sort': sorted_list = merge_sort(list_of_row, orientation) # Change the sorted_list to comma separated value - csv_result = ','.join(sorted_list) + csv_result = column_name + ',' + ','.join(sorted_list) # Get the execution time (Time now - Start time) execution_time = "{:.4f}".format(time.time() - start_time) @@ -192,7 +189,7 @@ def login(): conn = mysql.connection cursor = conn.cursor() - # creates dictionary of form data + # Creates dictionary of form data auth = request.form could_not_verify_message = """ @@ -202,7 +199,7 @@ def login(): """ if not auth or not auth.get('username') or not auth.get('password'): - # returns 401 if any username or / and password is missing + # Returns 401 if any username or / and password is missing return make_response( could_not_verify_message, 401, @@ -217,7 +214,7 @@ def login(): user = cursor.execute(check_username) if not user: - # returns 401 if user does not exist + # Returns 401 if user does not exist return make_response( could_not_verify_message, 401, @@ -231,7 +228,7 @@ def login(): cursor.close() if check_password_hash(password, auth.get('password')): - # generates the JWT Token + # Generates the JWT Token token = jwt.encode({ 'public_id': public_id, 'exp' : datetime.utcnow() + timedelta(minutes = 30) @@ -240,7 +237,7 @@ def login(): session['logged_in'] = True return make_response(jsonify({'token' : token.decode('UTF-8')}), 201) - # returns 403 if password is wrong + # Returns 403 if password is wrong return make_response( could_not_verify_message, 403, @@ -255,14 +252,14 @@ def signup_page(): def signup(): conn = mysql.connection cursor = conn.cursor() - # creates a dictionary of the form data + # Creates a dictionary of the form data data = request.form - # gets name, username and password + # Gets name, username and password name, username = data.get('name'), data.get('username') password = data.get('password') - # checking for existing user + # Checking for existing user select_user = f""" SELECT * FROM user @@ -270,7 +267,7 @@ def signup(): """ user = cursor.execute(select_user) if not user: - # database ORM object + # Database ORM object insert_user = f""" INSERT INTO user (public_id, name, username, password) VALUES ('{str(uuid.uuid4())}', '{name}', '{username}', '{generate_password_hash(password)}') @@ -288,7 +285,7 @@ def signup(): return make_response(successful_message, 201) else: - # returns 202 if user already exists + # Returns 202 if user already exists already_exist_message = """

User already exists. Please Log in.

Go to Login Page
@@ -324,20 +321,6 @@ def bubble(): cleaned_token = re.search('\?token=(.*)\'', token).group(1) return csv_processing("Bubble Sort", cleaned_token) -@app.route('/sort/insertion') -@authenticate -def insertion_page(): - token = str(request.get_json) - cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return sorting_page('Insertion', cleaned_token) - -@app.route('/sort/insertion', methods=['POST']) -@authenticate -def insertion(): - token = str(request.get_json) - cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return csv_processing("Insertion Sort", cleaned_token) - @app.route('/sort/merge') @authenticate def merge_page(): @@ -359,8 +342,12 @@ def result(): cursor = conn.cursor() token = str(request.get_json) cleaned_token = re.search('\?token=(.*)\'', token).group(1) + + # Get results if ID is present if 'id' in request.args: id = request.args['id'] + + # Search ID in the database selection = f""" SELECT * FROM sorts @@ -369,6 +356,8 @@ def result(): cursor.execute(selection) result = cursor.fetchall() cursor.close() + + # If the data of that ID is found, return that data if result: results = result[0] csv_list = results[3].split(',') @@ -381,8 +370,12 @@ def result():

Execution Time : {results[4]} second(s)

Back to Main Menu """ + + # If the data of that ID isn't found, return error message else: return f"

No Data Found with ID {id} in the Database!

Back to Main Menu" + + # Get result if ID is not present else: selection = """ SELECT * @@ -393,6 +386,8 @@ def result(): cursor.execute(selection) result = cursor.fetchall() cursor.close() + + # If there's any data in the database, return the last data if result: results = result[0] csv_list = results[3].split(',') @@ -405,6 +400,8 @@ def result():

Execution Time : {results[4]} second(s)

Back to Main Menu """ + + # If no data is found in the database, return error message else: return f"

No Data Found in the Database!

Back to Main Menu" diff --git a/sorting.py b/sorting.py index 5333224..858b211 100644 --- a/sorting.py +++ b/sorting.py @@ -1,55 +1,42 @@ +# There are two orientations of the sorting algorithm : Ascending and Descending +# The orientation of sorting is based on user's input + def selection_sort(l, orientation): - l1 = l[1:] if orientation == 'ascending': - for i in range (len(l1)): + for i in range (len(l)): idx_min = i - for j in range (i+1, len(l1)): - if l1[j] < l1[idx_min]: + for j in range (i+1, len(l)): + if l[j] < l[idx_min]: idx_min = j - l1[i], l1[idx_min] = l1[idx_min], l1[i] + l[i], l[idx_min] = l[idx_min], l[i] elif orientation == 'descending': - for i in range (len(l1)): + for i in range (len(l)): idx_min = i - for j in range (i+1, len(l1)): - if l1[j] > l1[idx_min]: + for j in range (i+1, len(l)): + if l[j] > l[idx_min]: idx_min = j - l1[i], l1[idx_min] = l1[idx_min], l1[i] - l1.insert(0,l[0]) - return l1 + l[i], l[idx_min] = l[idx_min], l[i] + return l def bubble_sort(l, orientation): - l1 = l[1:] if orientation == 'ascending': - for i in range (len(l1)): - for j in range (len(l1)-i-1): - if l1[j+1] < l1[j]: - l1[j], l1[j+1] = l1[j+1], l1[j] + for i in range (len(l)): + for j in range (len(l)-i-1): + if l[j+1] < l[j]: + l[j], l[j+1] = l[j+1], l[j] elif orientation == 'descending': - for i in range (len(l1)): - for j in range (len(l1)-i-1): - if l1[j+1] > l1[j]: - l1[j], l1[j+1] = l1[j+1], l1[j] - l1.insert(0,l[0]) - return l1 - -def insertion_sort(l, orientation): - l1 = l[1:] - if orientation == 'ascending': - for i in range (1, len(l1)): - key = l1[i] - j = i-1 - while j >= 0 and key < l1[j]: - l1[j+1] = l1[j] - j -= 1 - l1[j+1] = key + for i in range (len(l)): + for j in range (len(l)-i-1): + if l[j+1] > l[j]: + l[j], l[j+1] = l[j+1], l[j] + return l def merge_sort(l, orientation): - l1 = l[1:] if orientation == 'ascending': - if len(l1) > 1: - mid = len(l1)//2 - left = l1[:mid] - right = l1[mid:] + if len(l) > 1: + mid = len(l)//2 + left = l[:mid] + right = l[mid:] merge_sort(left, orientation) merge_sort(right, orientation) @@ -57,29 +44,28 @@ def merge_sort(l, orientation): while i < len(left) and j < len(right): if left[i] < right[j]: - l1[k] = left[i] + l[k] = left[i] i += 1 else: - l1[k] = right[j] + l[k] = right[j] j += 1 k += 1 while i < len(left): - l1[k] = left[i] + l[k] = left[i] i += 1 k += 1 while j < len(right): - l1[k] = right[j] + l[k] = right[j] j += 1 k += 1 - l1.insert(0,l[0]) - return l1 + return l elif orientation == 'descending': - if len(l1) > 1: - mid = len(l1)//2 - left = l1[:mid] - right = l1[mid:] + if len(l) > 1: + mid = len(l)//2 + left = l[:mid] + right = l[mid:] merge_sort(left, orientation) merge_sort(right, orientation) @@ -87,21 +73,20 @@ def merge_sort(l, orientation): while i < len(left) and j < len(right): if left[i] > right[j]: - l1[k] = left[i] + l[k] = left[i] i += 1 else: - l1[k] = right[j] + l[k] = right[j] j += 1 k += 1 while i < len(left): - l1[k] = left[i] + l[k] = left[i] i += 1 k += 1 while j < len(right): - l1[k] = right[j] + l[k] = right[j] j += 1 k += 1 - l1.insert(0,l[0]) - return l1 + return l diff --git a/test/addresses.csv b/test/addresses.csv new file mode 100644 index 0000000..1da8b07 --- /dev/null +++ b/test/addresses.csv @@ -0,0 +1,6 @@ +John,Doe,120 jefferson st.,Riverside, NJ, 08075 +Jack,McGinnis,220 hobo Av.,Phila, PA,09119 +John Da Man,Repici,120 Jefferson St.,Riverside, NJ,08075 +Stephen,Tyler,7452 Terrace At the Plaza road,SomeTown,SD, 91234 +,Blankman,,SomeTown, SD, 00298 +Joan the bone, Anne,Jet,9th, at Terrace plc,Desert City,CO,00123 diff --git a/test/airtravel.csv b/test/airtravel.csv new file mode 100644 index 0000000..97cad52 --- /dev/null +++ b/test/airtravel.csv @@ -0,0 +1,13 @@ +"Month, ""1958"", ""1959"", ""1960""" +JAN, 307, 360, 417 +FEB, 318, 342, 391 +MAR, 362, 406, 419 +APR, 348, 396, 461 +MAY, 363, 420, 472 +JUN, 435, 472, 535 +JUL, 491, 548, 622 +AUG, 505, 559, 606 +SEP, 404, 463, 508 +OCT, 359, 407, 461 +NOV, 310, 362, 390 +DEC, 337, 405, 432 diff --git a/test/crash_catalonia.csv b/test/crash_catalonia.csv new file mode 100644 index 0000000..7f63fee --- /dev/null +++ b/test/crash_catalonia.csv @@ -0,0 +1,9 @@ +"Day of Week", "Number of Crashes" +"Sunday", 13664 +"Monday", 17279 +"Tuesday", 17337 +"Wednesday", 17394 +"Thursday", 17954 +"Friday", 19147 +"Saturday", 15714 + diff --git a/test/hurricanes.csv b/test/hurricanes.csv new file mode 100644 index 0000000..1964c27 --- /dev/null +++ b/test/hurricanes.csv @@ -0,0 +1,10 @@ +"Month", "Average", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015" +"May", 0.1, 0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 0 +"Jun", 0.5, 2, 1, 1, 0, 0, 1, 1, 2, 2, 0, 1 +"Jul", 0.7, 5, 1, 1, 2, 0, 1, 3, 0, 2, 2, 1 +"Aug", 2.3, 6, 3, 2, 4, 4, 4, 7, 8, 2, 2, 3 +"Sep", 3.5, 6, 4, 7, 4, 2, 8, 5, 2, 5, 2, 5 +"Oct", 2.0, 8, 0, 1, 3, 2, 5, 1, 5, 2, 3, 0 +"Nov", 0.5, 3, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1 +"Dec", 0.0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 + From 8c101be1469e324c13f460c755d5e6c04c5ce223 Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Thu, 10 Jun 2021 00:41:23 +0700 Subject: [PATCH 4/7] Tidy up files; Change sorting_result to blob; Update features; Add test data --- csv_reader.py | 26 ---- .env => src/.env | 0 src/cleaning.py | 18 +++ src/csv_processing.py | 37 ++++++ html_processing.py => src/html_processing.py | 29 ++++- main.py => src/main.py | 122 ++++++++---------- src/other_util.py | 45 +++++++ sorting.py => src/sorting.py | 0 .../sorting_results.sql | 0 test/addresses.csv | 6 - 10 files changed, 177 insertions(+), 106 deletions(-) delete mode 100644 csv_reader.py rename .env => src/.env (100%) create mode 100644 src/cleaning.py create mode 100644 src/csv_processing.py rename html_processing.py => src/html_processing.py (87%) rename main.py => src/main.py (85%) create mode 100644 src/other_util.py rename sorting.py => src/sorting.py (100%) rename sorting_results.sql => src/sorting_results.sql (100%) delete mode 100644 test/addresses.csv diff --git a/csv_reader.py b/csv_reader.py deleted file mode 100644 index 6aa3b89..0000000 --- a/csv_reader.py +++ /dev/null @@ -1,26 +0,0 @@ -import pandas as pd -import csv - -# Read a csv file and get a column in it -def column_csv_reader(filename, column_no): - with open(filename) as csv_file: - # Use ',' delimiter for csv - reader = csv.reader(csv_file, delimiter=',') - column_name = '' - list_of_row = [] - i = 0 - for row in reader: - try: - # Column name must be on the first row - if i == 0: - column_name += row[column_no-1] - i += 1 - - # List of tuples - else: - list_of_row.append(row[column_no-1].strip()) - i += 1 - except IndexError: - pass - - return column_name, list_of_row diff --git a/.env b/src/.env similarity index 100% rename from .env rename to src/.env diff --git a/src/cleaning.py b/src/cleaning.py new file mode 100644 index 0000000..5322862 --- /dev/null +++ b/src/cleaning.py @@ -0,0 +1,18 @@ +from collections import Counter + +def data_cleaning(l): + data_types = [] + for i in l: + try: + data_types.append(type(i)) + except IndexError: + pass + print(data_types) + c = Counter(data_types) + count_type = [(i, c[i] / len(data_types) * 100.0) for i in c.most_common()] + most_common_type = count_type[0] + result = [] + for i in l: + if isinstance(i, most_common_type[0][0]): + result.append(i) + print(result) diff --git a/src/csv_processing.py b/src/csv_processing.py new file mode 100644 index 0000000..1b49420 --- /dev/null +++ b/src/csv_processing.py @@ -0,0 +1,37 @@ +import re +import pandas as pd +from collections import Counter + +def clean_strip(filename): + cleaned_filename = re.search('(.*)\.csv', filename).group(1) + with open(filename, 'r', newline='') as inf, open(f'{cleaned_filename}_cleaned.csv', 'w') as of: + for line in inf: + trimmed = (field.strip().strip('"') for field in line.split(',')) + of.write(','.join(trimmed)+'\n') + +def data_preprocess(filename): + cleaned_filename = re.search('(.*)\.csv', filename).group(1) + df = pd.read_csv(f'{cleaned_filename}_cleaned.csv') + to_be_parsed = [] + list_of_colname = df.columns.tolist() + to_be_parsed.append(list_of_colname) + for value in df.values.tolist(): + to_be_parsed.append(value) + list_of_column = [] + data_types = [] + for row in to_be_parsed[1:]: + for i in range (len(row)): + list_of_column.append([row[i] for row in to_be_parsed[1:]]) + data_types.append([type(row[i]) for row in to_be_parsed[1:]]) + break + i = 0 + result = [] + for data_type in data_types: + c = Counter(data_type) + count_type = [(i, c[i] / len(data_types) * 100.0) for i in c.most_common()] + most_common_type = count_type[0] + result.append([col for col in list_of_column[i] if isinstance(col, most_common_type[0][0])]) + i += 1 + result.insert(0, list_of_colname) + + return result diff --git a/html_processing.py b/src/html_processing.py similarity index 87% rename from html_processing.py rename to src/html_processing.py index 95b8593..72b5a7c 100644 --- a/html_processing.py +++ b/src/html_processing.py @@ -70,19 +70,36 @@ def sign_page(): """ # Function to turn a list into an html table -def list_to_table(name, l): +def list_to_table(l): + header = l[0] + body = l[1:] + table_script = f""" - - - """ - for i in l: - table_script += f"\n" + for colname in header: + table_script += f""" + + """ + table_script += """ + """ + + for row in body: + table_script += """ + + """ + for col in row: + table_script += f""" + + """ + table_script += """ + + """ + table_script += """
{name}
{i}{colname}
{col}
""" diff --git a/main.py b/src/main.py similarity index 85% rename from main.py rename to src/main.py index f628cc8..5b2dd69 100644 --- a/main.py +++ b/src/main.py @@ -11,9 +11,10 @@ from datetime import datetime, timedelta from functools import wraps -from csv_reader import * +from csv_processing import * from sorting import * from html_processing import * +from other_util import * app = Flask(__name__) app.config['DEBUG'] = True @@ -47,6 +48,25 @@ def home_page(): """ +def authenticate(f): + @wraps(f) + def decorated(*args, **kwargs): + + token = request.args.get('token') + # return 401 if token is not passed + if not token: + return "

401 Error

Token is Missing!

", 401 + + try: + # decoding the payload to fetch the stored details + data = jwt.decode(token, app.config['SECRET_KEY']) + except: + return "

401 Error

Token is Invalid!

", 401 + # returns the current logged in users contex to the routes + return f(*args, **kwargs) + + return decorated + # A function to process csv input from the user to the sorted one and can be used flexibly in this program def csv_processing(algoritma, token): # Initiate mysql connection & cursor @@ -59,7 +79,7 @@ def csv_processing(algoritma, token): # Save the csv file from the user to 'csv_inputs' folder try: f = request.files['csv_file'] - file_path = os.path.join('csv_inputs', secure_filename(f.filename)) + file_path = os.path.join('..', 'csv_inputs', secure_filename(f.filename)) f.save(file_path) except FileNotFoundError: w = algoritma.split() @@ -89,8 +109,12 @@ def csv_processing(algoritma, token): # """ # Get list of row for the specified column - column_name = column_csv_reader(file_path, column_no)[0] - list_of_row = column_csv_reader(file_path, column_no)[1] + clean_strip(file_path) + preprocessed_data = data_preprocess(file_path) + column_name = preprocessed_data[0][column_no-1] + + # User's input starts from 1 and the first element is the header + list_of_row = preprocessed_data[column_no] # Start sorting algorithm sorted_list = [] @@ -102,8 +126,11 @@ def csv_processing(algoritma, token): elif algoritma == 'Merge Sort': sorted_list = merge_sort(list_of_row, orientation) + preprocessed_data[column_no] = sorted_list # Change the sorted_list to comma separated value - csv_result = column_name + ',' + ','.join(sorted_list) + csv_result = list_to_csv(preprocessed_data) + + csv_binary = str_to_bin(csv_result) # Get the execution time (Time now - Start time) execution_time = "{:.4f}".format(time.time() - start_time) @@ -113,7 +140,7 @@ def csv_processing(algoritma, token): INSERT INTO sorts (tanggal_waktu, algoritma, sorting_result, execution_time) VALUES(%s, %s, %s, %s) """ - cursor.execute(insertion, (datetime.now(), algoritma, csv_result, execution_time)) + cursor.execute(insertion, (datetime.now(), algoritma, csv_binary, execution_time)) conn.commit() # Get the sorting result's ID from the database @@ -130,33 +157,16 @@ def csv_processing(algoritma, token): cursor.close() # Return the HTML Table of the sorted column, along with the sorting result ID and execution time - table = list_to_table(sorted_list[0], sorted_list[1:]) - return f"""{table} + table = list_to_table(col_to_row(preprocessed_data)) + return f"""

THE SORTING RESULT HAS BEEN INSERTED INTO THE DATABASE

+

Sorted Column : {column_name}

+ {table}

Execution Time : {execution_time} second(s)

ID : {sorting_id}

Back to Main Menu """ -def authenticate(f): - @wraps(f) - def decorated(*args, **kwargs): - - token = request.args.get('token') - # return 401 if token is not passed - if not token: - return "

401 Error

Token is Missing!

", 401 - - try: - # decoding the payload to fetch the stored details - data = jwt.decode(token, app.config['SECRET_KEY']) - except: - return "

401 Error

Token is Invalid!

", 401 - # returns the current logged in users contex to the routes - return f(*args, **kwargs) - - return decorated - @app.route('/mainpage') @authenticate def mainpage(): @@ -293,48 +303,20 @@ def signup(): """ return make_response(already_exist_message, 202) -@app.route('/sort/selection') -@authenticate -def selection_page(): - token = str(request.get_json) - cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return sorting_page('Selection', cleaned_token) - -@app.route('/sort/selection', methods=['POST']) +@app.route('/sort/') @authenticate -def selection(): +def selection_page(algorithm): token = str(request.get_json) cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return csv_processing("Selection Sort", cleaned_token) + return sorting_page(algorithm.capitalize(), cleaned_token) -@app.route('/sort/bubble') +@app.route('/sort/', methods=['POST']) @authenticate -def bubble_page(): +def selection(algorithm): token = str(request.get_json) cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return sorting_page('Bubble', cleaned_token) - -@app.route('/sort/bubble', methods=['POST']) -@authenticate -def bubble(): - token = str(request.get_json) - cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return csv_processing("Bubble Sort", cleaned_token) - -@app.route('/sort/merge') -@authenticate -def merge_page(): - token = str(request.get_json) - cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return sorting_page('Merge', cleaned_token) - -@app.route('/sort/merge', methods=['POST']) -@authenticate -def merge(): - token = str(request.get_json) - cleaned_token = re.search('\?token=(.*)\'', token).group(1) - return csv_processing("Merge Sort", cleaned_token) - + return csv_processing(f'{algorithm.capitalize()} Sort', cleaned_token) + @app.route('/sort/result', methods=['GET']) @authenticate def result(): @@ -360,10 +342,12 @@ def result(): # If the data of that ID is found, return that data if result: results = result[0] - csv_list = results[3].split(',') - table = list_to_table(csv_list[0], csv_list[1:]) + splitted_binary = split_string(results[3], 8) + csv_string = bin_to_str(splitted_binary) + csv_list = col_to_row(csv_to_list(csv_string)) + table = list_to_table(csv_list) return f"""

ID : {results[0]}

-

Date : {results[1]}

+

Date, Time : {results[1].strftime('%d %B %Y, %X')} WIB

Algorithm : {results[2]}

Sorting Result : {results[3]}

{table} @@ -390,10 +374,12 @@ def result(): # If there's any data in the database, return the last data if result: results = result[0] - csv_list = results[3].split(',') - table = list_to_table(csv_list[0], csv_list[1:]) + splitted_binary = split_string(results[3], 8) + csv_string = bin_to_str(splitted_binary) + csv_list = col_to_row(csv_to_list(csv_string)) + table = list_to_table(csv_list) return f"""

ID : {results[0]}

-

Date : {results[1]}

+

Date, Time : {results[1].strftime('%d %B %Y, %X')} WIB

Algorithm : {results[2]}

Sorting Result :

{table} diff --git a/src/other_util.py b/src/other_util.py new file mode 100644 index 0000000..eed01d7 --- /dev/null +++ b/src/other_util.py @@ -0,0 +1,45 @@ +def col_to_row(col_list): + list_of_colname = col_list[0] + list_of_row = [] + for col in col_list[1:]: + for i in range (len(col)): + list_of_row.append([col[i] for col in col_list[1:]]) + break + list_of_row.insert(0, list_of_colname) + + return list_of_row + +def list_to_csv(list_of_row): + csv_result = '' + for row in list_of_row: + str_col = [str(col) for col in row] + csv_result += ','.join(str_col) + '\n' + return csv_result + +def csv_to_list(csv_data): + all_elements = csv_data.split('\n') + result = [] + for element in all_elements: + if element.split(',') != ['']: + result.append(element.split(',')) + return result + +def str_to_bin(string): + result = ''.join(format(ord(char), '08b') for char in string) + + return result + +def bin_to_str(binary_values): + ascii_string = '' + + for binary_value in binary_values: + an_integer = int(binary_value, 2) + ascii_character = chr(an_integer) + ascii_string += ascii_character + + return ascii_string + +def split_string(string, n): + split_strings = [string[index : index + n] for index in range(0, len(string), n)] + + return split_strings diff --git a/sorting.py b/src/sorting.py similarity index 100% rename from sorting.py rename to src/sorting.py diff --git a/sorting_results.sql b/src/sorting_results.sql similarity index 100% rename from sorting_results.sql rename to src/sorting_results.sql diff --git a/test/addresses.csv b/test/addresses.csv deleted file mode 100644 index 1da8b07..0000000 --- a/test/addresses.csv +++ /dev/null @@ -1,6 +0,0 @@ -John,Doe,120 jefferson st.,Riverside, NJ, 08075 -Jack,McGinnis,220 hobo Av.,Phila, PA,09119 -John Da Man,Repici,120 Jefferson St.,Riverside, NJ,08075 -Stephen,Tyler,7452 Terrace At the Plaza road,SomeTown,SD, 91234 -,Blankman,,SomeTown, SD, 00298 -Joan the bone, Anne,Jet,9th, at Terrace plc,Desert City,CO,00123 From 43ee211c2a4ad7c4718ceeb2dcce37a07a9605cb Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Thu, 10 Jun 2021 01:30:17 +0700 Subject: [PATCH 5/7] Delete unused file; Rename the database; Add comments --- src/cleaning.py | 18 ---- src/csv_processing.py | 2 + .../sorts.sql} | 6 +- src/html_processing.py | 6 +- src/main.py | 83 ++++++++++++------- src/other_util.py | 6 ++ src/sorting.py | 1 - 7 files changed, 67 insertions(+), 55 deletions(-) delete mode 100644 src/cleaning.py rename src/{sorting_results.sql => database/sorts.sql} (95%) diff --git a/src/cleaning.py b/src/cleaning.py deleted file mode 100644 index 5322862..0000000 --- a/src/cleaning.py +++ /dev/null @@ -1,18 +0,0 @@ -from collections import Counter - -def data_cleaning(l): - data_types = [] - for i in l: - try: - data_types.append(type(i)) - except IndexError: - pass - print(data_types) - c = Counter(data_types) - count_type = [(i, c[i] / len(data_types) * 100.0) for i in c.most_common()] - most_common_type = count_type[0] - result = [] - for i in l: - if isinstance(i, most_common_type[0][0]): - result.append(i) - print(result) diff --git a/src/csv_processing.py b/src/csv_processing.py index 1b49420..f8fc24c 100644 --- a/src/csv_processing.py +++ b/src/csv_processing.py @@ -2,6 +2,7 @@ import pandas as pd from collections import Counter +# Strip the csv file (Removing trailing spaces) def clean_strip(filename): cleaned_filename = re.search('(.*)\.csv', filename).group(1) with open(filename, 'r', newline='') as inf, open(f'{cleaned_filename}_cleaned.csv', 'w') as of: @@ -9,6 +10,7 @@ def clean_strip(filename): trimmed = (field.strip().strip('"') for field in line.split(',')) of.write(','.join(trimmed)+'\n') +# Preprocess the data to delete inconsistent data def data_preprocess(filename): cleaned_filename = re.search('(.*)\.csv', filename).group(1) df = pd.read_csv(f'{cleaned_filename}_cleaned.csv') diff --git a/src/sorting_results.sql b/src/database/sorts.sql similarity index 95% rename from src/sorting_results.sql rename to src/database/sorts.sql index decdb6a..14fef0c 100644 --- a/src/sorting_results.sql +++ b/src/database/sorts.sql @@ -24,9 +24,9 @@ DROP TABLE IF EXISTS `sorts`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `sorts` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `tanggal_waktu` date DEFAULT NULL, + `tanggal_waktu` datetime DEFAULT NULL, `algoritma` varchar(255) DEFAULT NULL, - `sorting_result` varchar(255) DEFAULT NULL, + `sorting_result` blob DEFAULT NULL, `execution_time` float DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; @@ -78,4 +78,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2021-06-06 3:04:30 +-- Dump completed on 2021-06-10 1:27:14 diff --git a/src/html_processing.py b/src/html_processing.py index 72b5a7c..bfe0c5d 100644 --- a/src/html_processing.py +++ b/src/html_processing.py @@ -10,7 +10,7 @@ def sorting_page(algoritma, token): -

+



@@ -25,6 +25,7 @@ def sorting_page(algoritma, token): """ +# Login page in HTML def log_page(): return """ @@ -46,6 +47,7 @@ def log_page(): """ +# Signup page in HTML def sign_page(): return """ @@ -69,7 +71,7 @@ def sign_page(): """ -# Function to turn a list into an html table +# Function to turn a list into an html table (Should be list of row, not list column) def list_to_table(l): header = l[0] body = l[1:] diff --git a/src/main.py b/src/main.py index 5b2dd69..a7ce4b1 100644 --- a/src/main.py +++ b/src/main.py @@ -3,13 +3,13 @@ import jwt import uuid import re -from dotenv import load_dotenv from flask import Flask, request, session, jsonify, make_response from flask_mysqldb import MySQL +from dotenv import load_dotenv +from functools import wraps from werkzeug.utils import secure_filename from werkzeug.security import generate_password_hash, check_password_hash from datetime import datetime, timedelta -from functools import wraps from csv_processing import * from sorting import * @@ -21,48 +21,33 @@ load_dotenv() +# Set a secret key (private key) as an information used to decrypt or encrypt message app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') +# Set up MySql database app.config['MYSQL_HOST'] = 'localhost' app.config['MYSQL_USER'] = 'root' app.config['MYSQL_PASSWORD'] = os.getenv('DB_PASSWORD') -app.config['MYSQL_DB'] = 'sorting_results' +app.config['MYSQL_DB'] = 'sorts' mysql = MySQL(app) -@app.route('/') -def home_page(): - return """ - - - - - Sorting API Homepage - - -

Sorting API

-
by : Daffa Ananda Pratama Resyaly -- 13519107
- Login
- Signup - - - """ - +# Authenticate user via JSON Web Token (JWT) def authenticate(f): @wraps(f) def decorated(*args, **kwargs): token = request.args.get('token') - # return 401 if token is not passed + # Return 401 if token is not passed if not token: return "

401 Error

Token is Missing!

", 401 try: - # decoding the payload to fetch the stored details + # Decoding the payload to fetch the stored details data = jwt.decode(token, app.config['SECRET_KEY']) except: return "

401 Error

Token is Invalid!

", 401 - # returns the current logged in users contex to the routes + # Returns the current logged in users contex to the routes return f(*args, **kwargs) return decorated @@ -81,6 +66,8 @@ def csv_processing(algoritma, token): f = request.files['csv_file'] file_path = os.path.join('..', 'csv_inputs', secure_filename(f.filename)) f.save(file_path) + + # Error handling if the user doesn't input any file except FileNotFoundError: w = algoritma.split() return f""" @@ -88,9 +75,11 @@ def csv_processing(algoritma, token): Back to {algoritma} """ - # Get Column Number and Sorting Orientation (Ascending or Descending) + # Get Column Number try: column_no = int(request.form.get('column_no')) + + # Error handling if the user doesn't input any column number except ValueError: w = algoritma.split() return f""" @@ -98,6 +87,7 @@ def csv_processing(algoritma, token): Back to {algoritma} """ + # Get Sorting Orientation (Ascending or Descending) # try: orientation = request.form.get('orientation') # except ValueError: @@ -108,12 +98,14 @@ def csv_processing(algoritma, token): # Back to {algoritma} # """ - # Get list of row for the specified column + # Preprocess the csv file clean_strip(file_path) preprocessed_data = data_preprocess(file_path) + + # Get the column names column_name = preprocessed_data[0][column_no-1] - # User's input starts from 1 and the first element is the header + # Get list of row for the specified column list_of_row = preprocessed_data[column_no] # Start sorting algorithm @@ -126,10 +118,13 @@ def csv_processing(algoritma, token): elif algoritma == 'Merge Sort': sorted_list = merge_sort(list_of_row, orientation) + # Change the specified column of data that the user changes preprocessed_data[column_no] = sorted_list + # Change the sorted_list to comma separated value csv_result = list_to_csv(preprocessed_data) + # Change the csv file into binary (blob) to be saved into the database csv_binary = str_to_bin(csv_result) # Get the execution time (Time now - Start time) @@ -156,7 +151,7 @@ def csv_processing(algoritma, token): # Close the cursor cursor.close() - # Return the HTML Table of the sorted column, along with the sorting result ID and execution time + # Return the HTML Table of the sorted column, along with the sorting result's ID and execution time table = list_to_table(col_to_row(preprocessed_data)) return f"""

THE SORTING RESULT HAS BEEN INSERTED INTO THE DATABASE

@@ -167,6 +162,28 @@ def csv_processing(algoritma, token): Back to Main Menu """ +# Homepage +# Contains login and signup button +@app.route('/') +def home_page(): + return """ + + + + + Sorting API Homepage + + +

Sorting API

+
by : Daffa Ananda Pratama Resyaly -- 13519107
+ Login
+ Signup + + + """ + +# Mainpage for user +# Contains the sorting algorithm choices and result viewer @app.route('/mainpage') @authenticate def mainpage(): @@ -190,6 +207,7 @@ def mainpage(): """ +# Login page and method @app.route('/login') def login_page(): return log_page() @@ -254,6 +272,7 @@ def login(): {'WWW-Authenticate' : 'Basic realm ="Wrong Password !!"'} ) +# Signup page and method @app.route('/signup') def signup_page(): return sign_page() @@ -303,20 +322,22 @@ def signup(): """ return make_response(already_exist_message, 202) +# Sorting algorithm page and method based on the url that user goes to @app.route('/sort/') @authenticate -def selection_page(algorithm): +def algorithm_page(algorithm): token = str(request.get_json) cleaned_token = re.search('\?token=(.*)\'', token).group(1) return sorting_page(algorithm.capitalize(), cleaned_token) @app.route('/sort/', methods=['POST']) @authenticate -def selection(algorithm): +def algorithm_process(algorithm): token = str(request.get_json) cleaned_token = re.search('\?token=(.*)\'', token).group(1) return csv_processing(f'{algorithm.capitalize()} Sort', cleaned_token) - + +# Result of the sorting @app.route('/sort/result', methods=['GET']) @authenticate def result(): diff --git a/src/other_util.py b/src/other_util.py index eed01d7..8a8e79a 100644 --- a/src/other_util.py +++ b/src/other_util.py @@ -1,3 +1,4 @@ +# Change list of column to list of row def col_to_row(col_list): list_of_colname = col_list[0] list_of_row = [] @@ -9,6 +10,7 @@ def col_to_row(col_list): return list_of_row +# Change list to csv def list_to_csv(list_of_row): csv_result = '' for row in list_of_row: @@ -16,6 +18,7 @@ def list_to_csv(list_of_row): csv_result += ','.join(str_col) + '\n' return csv_result +# Change csv to list def csv_to_list(csv_data): all_elements = csv_data.split('\n') result = [] @@ -24,11 +27,13 @@ def csv_to_list(csv_data): result.append(element.split(',')) return result +# Change string to binary def str_to_bin(string): result = ''.join(format(ord(char), '08b') for char in string) return result +# Change binary to string def bin_to_str(binary_values): ascii_string = '' @@ -39,6 +44,7 @@ def bin_to_str(binary_values): return ascii_string +# Split the string every nth number def split_string(string, n): split_strings = [string[index : index + n] for index in range(0, len(string), n)] diff --git a/src/sorting.py b/src/sorting.py index 858b211..3ae90bb 100644 --- a/src/sorting.py +++ b/src/sorting.py @@ -1,6 +1,5 @@ # There are two orientations of the sorting algorithm : Ascending and Descending # The orientation of sorting is based on user's input - def selection_sort(l, orientation): if orientation == 'ascending': for i in range (len(l)): From f4a848ef8e14ae283496524b6f2a950b56e213e1 Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Thu, 10 Jun 2021 01:43:10 +0700 Subject: [PATCH 6/7] Fix bugs; Add error handling --- src/html_processing.py | 2 +- src/main.py | 143 ++++++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 68 deletions(-) diff --git a/src/html_processing.py b/src/html_processing.py index bfe0c5d..a9f5664 100644 --- a/src/html_processing.py +++ b/src/html_processing.py @@ -10,7 +10,7 @@ def sorting_page(algoritma, token): -

+



diff --git a/src/main.py b/src/main.py index a7ce4b1..83c615f 100644 --- a/src/main.py +++ b/src/main.py @@ -79,7 +79,7 @@ def csv_processing(algoritma, token): try: column_no = int(request.form.get('column_no')) - # Error handling if the user doesn't input any column number + # Error handling if the user doesn't input any column number or the right type of column number except ValueError: w = algoritma.split() return f""" @@ -88,79 +88,88 @@ def csv_processing(algoritma, token): """ # Get Sorting Orientation (Ascending or Descending) - # try: orientation = request.form.get('orientation') - # except ValueError: - # w = algoritma.split() - # print(w[0].lower()) - # return f""" - #

Please Input the Sorting Orientation (ASC/DESC)!

- # Back to {algoritma} - # """ - - # Preprocess the csv file - clean_strip(file_path) - preprocessed_data = data_preprocess(file_path) - - # Get the column names - column_name = preprocessed_data[0][column_no-1] - - # Get list of row for the specified column - list_of_row = preprocessed_data[column_no] - - # Start sorting algorithm - sorted_list = [] - # Select which sort that the user wants to use - if algoritma == 'Selection Sort': - sorted_list = selection_sort(list_of_row, orientation) - elif algoritma == 'Bubble Sort': - sorted_list = bubble_sort(list_of_row, orientation) - elif algoritma == 'Merge Sort': - sorted_list = merge_sort(list_of_row, orientation) - - # Change the specified column of data that the user changes - preprocessed_data[column_no] = sorted_list - # Change the sorted_list to comma separated value - csv_result = list_to_csv(preprocessed_data) + if (orientation): + # Preprocess the csv file + clean_strip(file_path) + preprocessed_data = data_preprocess(file_path) - # Change the csv file into binary (blob) to be saved into the database - csv_binary = str_to_bin(csv_result) + # Get the column names + try: + column_name = preprocessed_data[0][column_no-1] + + # Handling for index out of range error + except IndexError: + w = algoritma.split() + return f""" +

Index out of range!

+

Please input the right index number!

+ Back to {algoritma} + """ - # Get the execution time (Time now - Start time) - execution_time = "{:.4f}".format(time.time() - start_time) + # Get list of row for the specified column + list_of_row = preprocessed_data[column_no] + + # Start sorting algorithm + sorted_list = [] + # Select which sort that the user wants to use + if algoritma == 'Selection Sort': + sorted_list = selection_sort(list_of_row, orientation) + elif algoritma == 'Bubble Sort': + sorted_list = bubble_sort(list_of_row, orientation) + elif algoritma == 'Merge Sort': + sorted_list = merge_sort(list_of_row, orientation) + + # Change the specified column of data that the user changes + preprocessed_data[column_no] = sorted_list - # Insert the sorting result into table 'sorts' - insertion = f""" - INSERT INTO sorts (tanggal_waktu, algoritma, sorting_result, execution_time) - VALUES(%s, %s, %s, %s) - """ - cursor.execute(insertion, (datetime.now(), algoritma, csv_binary, execution_time)) - conn.commit() - - # Get the sorting result's ID from the database - selection = """ - SELECT id - FROM sorts - ORDER BY id DESC - LIMIT 1 - """ - cursor.execute(selection) - sorting_id = cursor.fetchall()[0][0] + # Change the sorted_list to comma separated value + csv_result = list_to_csv(preprocessed_data) - # Close the cursor - cursor.close() + # Change the csv file into binary (blob) to be saved into the database + csv_binary = str_to_bin(csv_result) - # Return the HTML Table of the sorted column, along with the sorting result's ID and execution time - table = list_to_table(col_to_row(preprocessed_data)) - return f""" -

THE SORTING RESULT HAS BEEN INSERTED INTO THE DATABASE

-

Sorted Column : {column_name}

- {table} -

Execution Time : {execution_time} second(s)

-

ID : {sorting_id}

- Back to Main Menu - """ + # Get the execution time (Time now - Start time) + execution_time = "{:.4f}".format(time.time() - start_time) + + # Insert the sorting result into table 'sorts' + insertion = f""" + INSERT INTO sorts (tanggal_waktu, algoritma, sorting_result, execution_time) + VALUES(%s, %s, %s, %s) + """ + cursor.execute(insertion, (datetime.now(), algoritma, csv_binary, execution_time)) + conn.commit() + + # Get the sorting result's ID from the database + selection = """ + SELECT id + FROM sorts + ORDER BY id DESC + LIMIT 1 + """ + cursor.execute(selection) + sorting_id = cursor.fetchall()[0][0] + + # Close the cursor + cursor.close() + + # Return the HTML Table of the sorted column, along with the sorting result's ID and execution time + table = list_to_table(col_to_row(preprocessed_data)) + return f""" +

THE SORTING RESULT HAS BEEN INSERTED INTO THE DATABASE

+

Sorted Column : {column_name}

+ {table} +

Execution Time : {execution_time} second(s)

+

ID : {sorting_id}

+ Back to Main Menu + """ + else: + w = algoritma.split() + return f""" +

Please Select the Sorting Orientation (Ascending/Descending)!

+ Back to {algoritma} + """ # Homepage # Contains login and signup button From 683522e177f5f92c80dd94d33a35243d99a5edbb Mon Sep 17 00:00:00 2001 From: slarkdarr Date: Fri, 11 Jun 2021 19:24:26 +0700 Subject: [PATCH 7/7] Add csv_inputs folder --- csv_inputs/airtravel.csv | 13 +++++++++++++ csv_inputs/airtravel_cleaned.csv | 13 +++++++++++++ csv_inputs/crash_catalonia.csv | 9 +++++++++ csv_inputs/crash_catalonia_cleaned.csv | 9 +++++++++ csv_inputs/hurricanes.csv | 10 ++++++++++ csv_inputs/hurricanes_cleaned.csv | 10 ++++++++++ 6 files changed, 64 insertions(+) create mode 100644 csv_inputs/airtravel.csv create mode 100644 csv_inputs/airtravel_cleaned.csv create mode 100644 csv_inputs/crash_catalonia.csv create mode 100644 csv_inputs/crash_catalonia_cleaned.csv create mode 100644 csv_inputs/hurricanes.csv create mode 100644 csv_inputs/hurricanes_cleaned.csv diff --git a/csv_inputs/airtravel.csv b/csv_inputs/airtravel.csv new file mode 100644 index 0000000..97cad52 --- /dev/null +++ b/csv_inputs/airtravel.csv @@ -0,0 +1,13 @@ +"Month, ""1958"", ""1959"", ""1960""" +JAN, 307, 360, 417 +FEB, 318, 342, 391 +MAR, 362, 406, 419 +APR, 348, 396, 461 +MAY, 363, 420, 472 +JUN, 435, 472, 535 +JUL, 491, 548, 622 +AUG, 505, 559, 606 +SEP, 404, 463, 508 +OCT, 359, 407, 461 +NOV, 310, 362, 390 +DEC, 337, 405, 432 diff --git a/csv_inputs/airtravel_cleaned.csv b/csv_inputs/airtravel_cleaned.csv new file mode 100644 index 0000000..b4ec913 --- /dev/null +++ b/csv_inputs/airtravel_cleaned.csv @@ -0,0 +1,13 @@ +Month,1958,1959,1960 +JAN,307,360,417 +FEB,318,342,391 +MAR,362,406,419 +APR,348,396,461 +MAY,363,420,472 +JUN,435,472,535 +JUL,491,548,622 +AUG,505,559,606 +SEP,404,463,508 +OCT,359,407,461 +NOV,310,362,390 +DEC,337,405,432 diff --git a/csv_inputs/crash_catalonia.csv b/csv_inputs/crash_catalonia.csv new file mode 100644 index 0000000..7f63fee --- /dev/null +++ b/csv_inputs/crash_catalonia.csv @@ -0,0 +1,9 @@ +"Day of Week", "Number of Crashes" +"Sunday", 13664 +"Monday", 17279 +"Tuesday", 17337 +"Wednesday", 17394 +"Thursday", 17954 +"Friday", 19147 +"Saturday", 15714 + diff --git a/csv_inputs/crash_catalonia_cleaned.csv b/csv_inputs/crash_catalonia_cleaned.csv new file mode 100644 index 0000000..9f2488c --- /dev/null +++ b/csv_inputs/crash_catalonia_cleaned.csv @@ -0,0 +1,9 @@ +Day of Week,Number of Crashes +Sunday,13664 +Monday,17279 +Tuesday,17337 +Wednesday,17394 +Thursday,17954 +Friday,19147 +Saturday,15714 + diff --git a/csv_inputs/hurricanes.csv b/csv_inputs/hurricanes.csv new file mode 100644 index 0000000..1964c27 --- /dev/null +++ b/csv_inputs/hurricanes.csv @@ -0,0 +1,10 @@ +"Month", "Average", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015" +"May", 0.1, 0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 0 +"Jun", 0.5, 2, 1, 1, 0, 0, 1, 1, 2, 2, 0, 1 +"Jul", 0.7, 5, 1, 1, 2, 0, 1, 3, 0, 2, 2, 1 +"Aug", 2.3, 6, 3, 2, 4, 4, 4, 7, 8, 2, 2, 3 +"Sep", 3.5, 6, 4, 7, 4, 2, 8, 5, 2, 5, 2, 5 +"Oct", 2.0, 8, 0, 1, 3, 2, 5, 1, 5, 2, 3, 0 +"Nov", 0.5, 3, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1 +"Dec", 0.0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 + diff --git a/csv_inputs/hurricanes_cleaned.csv b/csv_inputs/hurricanes_cleaned.csv new file mode 100644 index 0000000..0139c86 --- /dev/null +++ b/csv_inputs/hurricanes_cleaned.csv @@ -0,0 +1,10 @@ +Month,Average,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015 +May,0.1,0,0,1,1,0,0,0,2,0,0,0 +Jun,0.5,2,1,1,0,0,1,1,2,2,0,1 +Jul,0.7,5,1,1,2,0,1,3,0,2,2,1 +Aug,2.3,6,3,2,4,4,4,7,8,2,2,3 +Sep,3.5,6,4,7,4,2,8,5,2,5,2,5 +Oct,2.0,8,0,1,3,2,5,1,5,2,3,0 +Nov,0.5,3,0,0,1,1,0,1,0,1,0,1 +Dec,0.0,1,0,1,0,0,0,0,0,0,0,1 +