Skip to content

Instantly share code, notes, and snippets.

@zeitan
Created September 21, 2012 12:52
Show Gist options
  • Save zeitan/3761286 to your computer and use it in GitHub Desktop.
Save zeitan/3761286 to your computer and use it in GitHub Desktop.
module ManejoMateriales
class Sistema
def self.disponibilidad
fecha_hoy_disponibilidad = Date.current + 6.hours + 30.minutes
inicio_mes_disponibilidad = fecha_hoy_disponibilidad.beginning_of_month-1.day-17.hour-30.minutes+1.seconds
circuito_operativo = Equipo.linea_principal.find(:all,:select=>:id).map(&:id)
eventos = Evento.find(:all,:select=>"fecha_fin,fecha_inicio",:conditions=>{:fecha_ocurrencia => (inicio_mes_disponibilidad..fecha_hoy_disponibilidad), :operativo => true, :equipo_id => circuito_operativo}, :order=>:fecha_inicio)
range_disponibilidad_eventos = []
eventos.each{|evento| range_disponibilidad_eventos = range_disponibilidad_eventos | genera_rangos(evento)}
crea_tiempo_parada(range_disponibilidad_eventos)
end
private
@@horas = lambda {|tiempo_parada| (tiempo_parada * 24).to_i}
@@minutos = lambda {|tiempo_parada| (tiempo_parada * 24 * 60).to_i-@@horas.call(tiempo_parada)*60}
#disponibilidad=((24-TiempoParada)/24)*100
#TiempoParada= HorasParada+Minutosparadas/60.00
@@porc_tiempo_parada = lambda { |tiempo_parada| ((24-(@@horas.call(tiempo_parada) + (@@minutos.call(tiempo_parada)/60.00)))/24)*100 }
@@calcula_tiempo_parada = lambda { |eventos| (eventos.length== 1) ? 0 : @@porc_tiempo_parada.call(eventos.max-eventos.min)}
@@rango_por_dias = lambda{|rango,filtro| rango.select{ |evento| evento[:dia] == filtro }.map{|dia| dia[:evento]} }
def self.genera_rangos(evento)
range_disponibilidad = []
range_standar = evento.fecha_inicio..evento.fecha_fin
min_date_disponibilidad = DateTime.new(range_standar.min.year,range_standar.min.month,range_standar.min.day, 6, 30 , 1)
range_disponibilidad << {:dia=>dia_disponibilidad(range_standar.min), :evento=>range_standar.min, :f_fin=>evento.fecha_fin} if range_standar.min < min_date_disponibilidad
#Se generan rangos entre la fecha inicio y fin del evento para tener valores a calcular disponibilidad
range_standar.entries.each do |x|
fecha_disponibilidad = DateTime.parse(x.strftime("%Y-%m-%d")) + 6.hours + 30.minutes + 1.seconds
if x != range_standar.min && x!=evento.fecha_fin then
range_disponibilidad << {:dia=>Date.parse(fecha_disponibilidad.tomorrow.strftime("%Y-%m-%d")) , :evento=>fecha_disponibilidad}
else
if x != range_standar.min then
if evento.fecha_fin > fecha_disponibilidad then
range_disponibilidad << {:dia=>dia_disponibilidad(fecha_disponibilidad), :evento=>fecha_disponibilidad}
end
else
range_disponibilidad << ((range_standar.min < min_date_disponibilidad) ? {:dia=>dia_disponibilidad(min_date_disponibilidad), :evento=>min_date_disponibilidad} : {:dia=>dia_disponibilidad(range_standar.min), :evento=>range_standar.min} )
end
end
end
range_disponibilidad << {:dia=>dia_disponibilidad(evento.fecha_fin), :evento=>evento.fecha_fin} #Se agrega la fecha_fin del rango correcta ya que el range en Ruby agrega de 24.hours desde la fecha_inicio
end
def self.crea_tiempo_parada(range_disponibilidad_eventos)
#tiempo_parada.round=>Numero de días
paradas =[]
dias = range_disponibilidad_eventos.map{|evento| evento[:dia]}.uniq
dias.each do |disponibilidad|
if disponibilidad!=dias.min && disponibilidad!=dias.max then
paradas << {:x=>disponibilidad.day, :y=>@@calcula_tiempo_parada.call(range_disponibilidad_eventos.select{ |evento| evento[:dia] == disponibilidad }.map{|dia| dia[:evento]})}
else
if disponibilidad!=dias.min then
max_dia = @@rango_por_dias.call(range_disponibilidad_eventos,dias.max).max
tiempo_parada=max_dia - DateTime.parse(disponibilidad.yesterday.strftime("%Y-%m-%d")) + 6.hours + 30.minutes + 1.seconds
else
min_dia = @@rango_por_dias.call(range_disponibilidad_eventos,dias.min).min
tiempo_parada=(DateTime.parse(disponibilidad.strftime("%Y-%m-%d")) + 6.hours + 30.minutes) - min_dia
end
paradas << {:x=>disponibilidad.day, :y=>@@porc_tiempo_parada.call(tiempo_parada)}
end
end
if paradas == []
paradas << {:x=>0, :y=>0}
end
paradas
end
#Este metodo se puede colocar en T-SQL con un CASE WHEN (que se realizo anteriormente) pero decidi dejar toda la logica en un solo sitio.
def self.dia_disponibilidad(dia_parada)
dia = dia_parada.yesterday
min_dia = DateTime.parse(dia.strftime("%Y-%m-%d")) + 6.hours + 30.minutes + 1.seconds
dia = DateTime.parse(dia_parada.strftime("%Y-%m-%d")) + 6.hours + 30.minutes
dia_parada += ( (dia_parada < min_dia) ? -1.day : 1.day) if dia_parada <= min_dia or dia_parada >= dia
return Date.parse(dia_parada.strftime("%Y-%m-%d"))
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment