diff --git a/pythonTest/EmptySolution.py b/pythonTest/EmptySolution.py new file mode 100644 index 0000000..df6ff17 --- /dev/null +++ b/pythonTest/EmptySolution.py @@ -0,0 +1,163 @@ +import csv +import datetime as dt +from decimal import * +import math + +""" +Please write you name here: Salah Abdo +""" + + +def process_shifts(path_to_csv): + with open('work_shifts.csv') as file: + next(file, None) #skip the first line(Header) + reader = csv.reader(file, delimiter=',') + + shifts = {} + + for row in reader: + + startShift = row[3] + endShift = row[1] + + breakNotes = row[0] + + payRate = row[2] + + start_dt = dt.datetime.strptime(startShift, '%H:%M') # convert start time string to time using 24 hour format + end_dt = dt.datetime.strptime(endShift, '%H:%M') + + diff = (end_dt - start_dt) + shiftHours = int((diff.seconds/60)) # convert hour to minutes + + breakTime = breakNotes.split("-") #split each time a - is seen to separate the time + + breakTime0 = breakTime[0].strip() # remove all whitespaces + breakTime1 = breakTime[1].strip() + + if not breakTime0.isdigit() & breakTime1.isdigit(): + if breakTime0[-2:] == "AM": # check if letters AM is present + breakTime0 = breakTime0.replace("AM", "") #remove the letters AM and leave the number as it is + + elif breakTime0[-2:] == "PM": # check if letters PM is present + breakTime0 = breakTime0.replace("PM", "") #remove the letters PM + breakTime0 = float(breakTime0) + 12 # convert number to 24 hour time + + elif breakTime0.isdigit(): # for instances where the break start time and end time using different format ("4-4:10PM") + if breakTime1[-2:] == "AM": + breakTime0 = float(breakTime0) + else: + breakTime0 = float(breakTime0) +12 + + if breakTime1[-2:] == "AM": + breakTime1 = breakTime1.replace("AM", "") + + elif breakTime1 [-2:] == "PM": + breakTime1 = breakTime1.replace("PM", "") + breakTime1 = float(breakTime1) + 12 + + elif breakTime1.isdigit(): + if breakTime0[-2:] == "AM": + breakTime1 = float(breakTime0) + elif breakTime1.isdigit() & breakTime0[-2:] == "PM": + breakTime1 = float(breakTime0) +12 + + + + endBreak = str(round(Decimal(breakTime1),2)) #convert to decimal, rounded up to two decimal places to represent time + endBreak = endBreak.replace(".", ":") + endBreak = dt.datetime.strptime(endBreak, '%H:%M') + + startBreak = str(round(Decimal(breakTime0),2)) + startBreak = startBreak.replace(".", ":") + startBreak = dt.datetime.strptime(startBreak, '%H:%M') + + breakTime = (endBreak - startBreak) + breakHours = int((breakTime.seconds/60)) #calculate total break in minutes + + hoursWorked = shiftHours - breakHours + + labourCost = int((hoursWorked/60) * float(payRate)) + + if startShift in shifts: # if start time is already present then increase the labour cost for that specific time + shifts[startShift] += labourCost + else: + shifts[startShift] = labourCost + + return(shifts) + +def process_sales(path_to_csv): + + with open('transactions.csv') as file: + next(file, None) #skip the first line(Header) + reader = csv.reader(file, delimiter=',') + + sales = {} + + for row in reader: + sale = float(row[0]) + time = row[1][:2] + ':00' # time rounded up to every hour + + if time in sales: + sales[time] += int(sale) + else: + sales[time] = int(sale) + + + return(sales) + +def compute_percentage(shifts, sales): + + computePercentage = {} + + for time in sorted(shifts): # iterate over key only + labourCost = shifts[time] + try: + sale = sales[time] + percentage = round((labourCost / sale)*100,2) + except: + sale = None + percentage = labourCost * (-1) + computePercentage[time] = percentage + return(computePercentage) + + +def best_and_worst_hour(percentages): + + bestAndWorst = [] + + worstHour = min(percentages, key=percentages.get) # gets smallest value key in the dictionary + + for key, value in percentages.items(): + bestHourSales = math.inf #set to infinity + bestHour = "" + if value > 0: + if value < bestHourSales: + bestHourSales = value + bestHour = key + + bestAndWorst.append(bestHour) + bestAndWorst.append(worstHour) + + return(bestAndWorst) + +def main(path_to_shifts, path_to_sales): + """ + Do not touch this function, but you can look at it, to have an idea of + how your data should interact with each other + """ + + shifts_processed = process_shifts(path_to_shifts) + sales_processed = process_sales(path_to_sales) + percentages = compute_percentage(shifts_processed, sales_processed) + best_hour, worst_hour = best_and_worst_hour(percentages) + return best_hour, worst_hour + +if __name__ == '__main__': + # You can change this to test your code, it will not be used + path_to_sales = "transactions.csv" + path_to_shifts = "work_shifts.csv" + best_hour, worst_hour = main(path_to_shifts, path_to_sales) + + +# Please write you name here: Salah Abdo diff --git a/pythonTest/readme.txt b/pythonTest/readme.txt new file mode 100644 index 0000000..1113aba --- /dev/null +++ b/pythonTest/readme.txt @@ -0,0 +1,61 @@ +===Tenzo Coding Challenge=== + +Congratulations on making it to the first part of the Tenzo Interview process + +NOTE: This exercise is in Python 3 -- if you wish to change to a language of +your choice, that is completely fine. + +We want to understand the most and least profitable hour of the day for a given restaurant when looking at labour cost. + +You'll have two csvs, one describing the shifts, and one describing the hourly +sales. + + +==LABOUR DATA== +A shift will include the pay-rate (per hour), the start and end time, and a text + field where the manager will enter break info. This may vary depending on the individual manager. + +For example: + +{ + 'break_notes': '15-18', + 'start_time': '10:00', + 'end_time': '23:00', + 'pay_rate': 10.0 +} + +The data given shows a shift started at 10AM and ended at 11PM. However, the break_notes "15-18" indicates that the staff member took a 3 hour break in the middle of the day (when they would not be paid). The employee was paid £10 per hour. + + +==SALES DATA== +This shows you a set of transactions: + +For example + +[ + { + 'time' : '10:31, + 'amount' : 50.32 + } +] +We are hoping that you can compute different metrics for the different hours, +such as the total sales during this hour, the cost of labour for this hour, and +the cost of labour as percentage of sales. + +e.g., + +Hour Sales Labour % +7:00 100 30 30% +8:00 300 60 20% +Lastly, we are hoping that you can output which hour was the best and worst in terms of labour cost as a percentage of sales. + +The empty Solution.py file contains some function, where the output is well +defined. This will be used for our tests, so be sure to output right answers +(it is not that hard to compute the result by hand, and compare it to the +output of your program) in the right format. If you need to create other +functions, you're free to do so, just keep in mind that the functions that are +already defined need to work. Also , for the sake of testing, do not print any alert messages or anything to stdout. + +Please write your name at the top and the bottom of your solution. + +When you are done, please send your python file and your CV in separate file. \ No newline at end of file diff --git a/pythonTest/transactions.csv b/pythonTest/transactions.csv new file mode 100644 index 0000000..502dbe2 --- /dev/null +++ b/pythonTest/transactions.csv @@ -0,0 +1,21 @@ +amount,time +100.32,10:31 +30.56,10:56 +300.65,11:05 +20.0,11:31 +54.56,12:36 +220.09,12:45 +240.0,12:59 +270.43,13:10 +135.65,13:15 +15.43,14:04 +162.34,14:06 +63.43,15:04 +75.42,16:31 +142.34,17:31 +57.54,18:31 +450.54,18:31 +240.54,18:56 +240.54,19:15 +180.54,19:45 +240.54,21:45 \ No newline at end of file diff --git a/pythonTest/work_shifts.csv b/pythonTest/work_shifts.csv new file mode 100644 index 0000000..3e20dde --- /dev/null +++ b/pythonTest/work_shifts.csv @@ -0,0 +1,8 @@ +break_notes,end_time,pay_rate,start_time +15-18,23:00,10.0,10:00 +18.30-19.00,23:00,12.0,18:00 +4PM-5PM,22:30,14.0,12:00 +3-4,18:00,10.0,09:00 +4-4.10PM,23:00,20.0,09:00 +15 - 17,23:00,10.0,11:00 +11 - 13,16:00,10.0,10:00 \ No newline at end of file