Last active
July 9, 2016 22:04
-
-
Save christiangenco/31cea53929d74642e50b to your computer and use it in GitHub Desktop.
process EMC timecards
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'time' | |
class Float | |
def round_to(x) | |
(self * 10**x).round.to_f / 10**x | |
end | |
def ceil_to(x) | |
(self * 10**x).ceil.to_f / 10**x | |
end | |
def floor_to(x) | |
(self * 10**x).floor.to_f / 10**x | |
end | |
end | |
class Timeset | |
attr_accessor :timein, :timeout, :truncate | |
def initialize(timein="0:00", timeout="0:00", truncate=false) | |
self.timein = timein | |
self.timeout = timeout | |
self.truncate = truncate | |
end | |
def timein=(t) | |
#puts "parsing: #{t}" | |
@timein = Time.parse(t) | |
@timein = to_pm(@timein) if(@timein < Time.parse("9:00")) | |
end | |
def timeout=(t) | |
@timeout = Time.parse(t) | |
@timeout = to_pm(@timeout) if(@timeout < Time.parse("9:40")) | |
end | |
def to_pm(t) | |
t + 12 * 60 * 60 | |
end | |
def truncate(t) | |
return t if !@truncate || t==nil | |
if t>Time.parse('3:00pm') && t<Time.parse('3:12pm') | |
t = Time.parse('3:00pm') | |
end | |
if t>Time.parse('8:00pm') && t<Time.parse('8:12pm') | |
t = Time.parse('8:00pm') | |
end | |
return t | |
end | |
def hours | |
timein, timeout = @timein, @timeout | |
timeout = truncate(timeout) | |
(timeout - timein)/3600.0 | |
end | |
def total | |
hours | |
end | |
def timestring_helper(t) | |
t.strftime("%I:%M %p").to_s.downcase | |
end | |
def timestring(t) #time to string | |
return '' if t==nil | |
output = timestring_helper(t) | |
if(t != truncate(t)) | |
output += '=>' + timestring_helper(truncate(t)) | |
end | |
output | |
end | |
def to_s | |
"#{timestring(@timein)} to #{timestring(@timeout)} = %.2f" %hours | |
end | |
def to_html | |
"<tr style='color:blue;background-color:#BBF'><td align='right'>#{timestring(self.timein)}</td></tr><tr><td align='right' style='color:blue;background-color:#EED'>#{timestring(self.timeout)}</td><td style='color:black'><i>#{self.total.round_to(2)}</i></td></tr>" | |
end | |
end | |
class Day | |
attr_accessor :times | |
def initialize(times = []) | |
@times = times | |
end | |
def << timeset | |
times << Timeset.new(timeset[0],timeset[1]) | |
end | |
def lunch | |
return 0.0 if times.size < 2 | |
(@times[1].timein - @times[0].timeout)/3600 | |
end | |
def total | |
t = 0.0 | |
self.times.each do |ts| | |
t+=ts.total | |
end | |
t | |
end | |
def to_html | |
output = "" | |
self.times.each_with_index do |ts, i| | |
output += ts.to_html | |
end | |
output+="<tr><td style='background-color:#FCC'>Break<0.5hrs</td><td style='background-color:#FCC'><u>#{lunch.round_to(2)}</u></td></tr>" if lunch < 0.5 && lunch != 0.0 | |
output+="<tr><td>Day total</td><td style='background-color:#CFC'><u>#{total.round_to(2)}</u></td></tr>" | |
output += "" | |
output | |
end | |
end | |
class Employee | |
attr_accessor :name, :weeks | |
def initialize(name="Employee",weeks=[[]]) | |
self.name = name | |
self.weeks = weeks | |
end | |
def <<(day, week=1) | |
#puts "adding day: #{day}" | |
weeks[week] = [] unless weeks[week] #instantiate it if it's null | |
weeks[week] << day | |
end | |
def total(week) | |
t = 0.0 | |
overtime = 0 | |
self.weeks[week].each do |d| | |
t += d.total | |
end | |
overtime += t-40 if t>40 | |
[t.to_f, overtime.to_f] | |
end | |
def employee_total | |
t = 0 | |
overtime = 0 | |
weeks.each_with_index{|w,i| | |
marginal_time, marginal_overtime = total(i) | |
t += marginal_time | |
overtime += marginal_overtime | |
} | |
return [t.to_f, overtime.to_f] | |
end | |
def to_html | |
output = "<h3>#{self.name}</h3>\n<table border='1px' width='210px' cellpadding='0' cellspacing='0'>\n" | |
self.weeks.each_with_index do |w, i| | |
w.each do |d| | |
output += "<tr>\n" + d.to_html + "\n</tr>\n" | |
end | |
total, overtime = total(i) | |
output += "<tr><td><b>Week Total</b></td><td style='background-color:#9F9'>#{total.round_to(2)}</td></tr>" | |
output += "<tr><td><b>Week Overtime</b></td><td style='background-color:#9F9'>#{overtime.round_to(2)}</td></tr>" unless overtime == 0.0 | |
end | |
total, overtime = employee_total | |
output+="<tr><td><h4>#{self.name.to_s} Net Time</h4></td><td style='background-color:#9F9'><h3><b><u>#{total.round_to(2)} hrs.</u></b></h3></td></tr>" | |
output+="<tr><td><h4>#{self.name.to_s} Net Overtime</h4></td><td style='background-color:#F99'><h3><b><u>#{overtime.round_to(2)} hrs.</u></b></h3></td></tr>" unless overtime == 0.0 | |
#output+="<tr><td><h4>@ $#{@@payrate[self.name]}/hr</h4></td><td><h4><b>$%.2f</b></h4></td></tr>" % (@@payrate[self.name] * total) unless @@payrate[self.name] == nil | |
output+="</table>" | |
output | |
end | |
end | |
def clean_time(t) | |
if t.index(':') == nil | |
if t.length <= 2 #time with no minutes. ie: 10, 8, 3 | |
t = t.to_s + ':00' | |
elsif t.length >= 3 #time with no : character. ie: 1013, 805, 304 | |
t = t.insert(-3, ':') #1003 => 10:03 | |
end | |
end | |
t | |
end | |
#read timecard file | |
def extract_data(content) | |
employees = [] | |
lines = content.split(/\r?\n/) | |
while(name = lines.shift) | |
e = Employee.new(name.chomp) | |
week = 0 | |
# print "Processing #{e.name}..." | |
while(line=lines.shift ) | |
next if line.index('#') | |
break if(line.chomp=='') | |
if line.index('week') | |
week += 1 | |
# print "processing #{e.name}'s week ##{week+1}..." | |
# line = lines.shift | |
next | |
end | |
begin | |
line=line.split(/[\s\.+-]/) #\s = space, \. = period. [\s\.+-] = space, period, -, or + | |
break if(line.size % 2 == 1) | |
d = Day.new | |
line.each_with_index{|t,i| line[i] = clean_time(t)} #correct for single-digit times. ie: 10, 3, 8 | |
d<<[line[0],line[1]] #add to the day the first timepair | |
d<<[line[2],line[3]] unless line.size < 3 #add to the day the second timepair (unless there isn't a second timepair) | |
e.<<(d, week) #add the day to the employee at the correct week | |
rescue | |
if require 'pry' | |
binding.pry | |
end | |
end | |
end | |
employees << e | |
# puts | |
end | |
employees | |
end | |
# puts Hook['params'] | |
content = if defined? Hook | |
Hook['params']["file"]["_readableState"]["buffer"].map{|b| b["data"]}.flatten.pack("c*") | |
else | |
ARGF.read | |
end | |
# puts content | |
employees = extract_data(content) | |
# p employees | |
#Write File | |
title = "{{title}}" | |
result = "" | |
result<<("<html>\n\t<head>\n\t\t<title>#{title}</title>\n\t</head>\n\t<body>\n\t\t<center>\n<h1>#{title}</h1><table cellpadding='5px'><tr valign='top' height='1000px'>") | |
employees.each_with_index{|e,i| | |
result<< "<td>" + e.to_html + "</td>" | |
result<< "\n</tr>\n<tr valign='top' height='1050px'>" if (i+1)%4==0 && employees[i+1] != nil | |
} | |
result<<("\n</tr></table>\t\t</center>\n\t</body>\n</html>") | |
puts result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment