ruby on rails average per day - ruby-on-rails

Referencing this post:
ruby on rails average per day
I'm getting the average per day, which works fine. Until now that the month switched over...
I have this code
score = (7.days.ago.to_date.to_s(:db)..Date.today.tomorrow.to_s(:db)).map{|dt| [dt, ave_score[dt] || 0]}
Which works, but now that the month switches over, it comes back with dates that don't exist, like 2009-08-32 to 2009-08-99 and 2009-09-00. All in the array. How can I delete dates that don't actually exist.

Try waiting to make the call to to_s:
score = (7.days.ago.to_date..Date.today.tomorrow).map{ |dt| d = dt.to_s(:db); [d, ave_score[d] || 0] }

I figured it out, I'm not sure if this is the best way of doing it so if anybody else would like to add something go for it:
arr_count = 0
length = score.length
while arr_count < length
begin
score[arr_count][0].to_date
arr_count = arr_count + 1
rescue
#score.delete_at(arr_count)
length = length - 1
end
end

Related

Check if a time range is between another time range and how many hours Ruby on Rails

So I have a start_time and end_time. Which is maximum 24 hours.
I guess I firstly need to check if this timerange is within another timerange say 21:00-01:00. If it is I need to know how many of the hours is within the timerange.
Any ideas?
Use ((two- one) / 3600).round
for example
one=Time.now #=>2019-01-23 21:19:19 +0530
two=Time.now + 1*60*60 #=>2019-01-23 22:19:27 +0530
((two- one) / 3600).round #=>1
difference is 1 hour for two different Time instance.
What do you mean by "within"? Do you mean that you want to test if there's any overlap between the ranges, or if the first range is fully contained within another?
You can use Time objects in ranges and exploit #cover? to check for overlap
start_time = 5.hours.ago
end_time = 4.hours.ago
check_range_start = (4.5).hours.ago
check_range_end = (3.5).hours.ago
check_range = (check_range_start..check_range_end)
check_range.cover?(end_time) # => true
check_range.cover?(start_time) # =>false
If both ends of the range is covered by your check range, then your range is fully covered. If only one end is covered, then you have overlap. If neither end is covered, then the ranges do not intersect.
Once you know if there's intersection, then you can trivially compute the distance from one end of the time range to one end of your check range; if you want to know how much time between your check range start and your input start time, simply subtract start_time - check_range_start.
I assume the four arguments of the method below are strings of the form "HH:MM" or "HH:MM:SS". I have provided a pure-Ruby solution that makes string comparisons only (for example: "17:26" < "18:00" #=> true). That is, I do not convert the strings to Time objects.
def time_within_ref?(time_start, time_end, ref_start, ref_end)
(time_start >= ref_start) &&
(adj_hour(time_start, time_end) <= adj_hour(ref_start, ref_end))
end
def adj_hour(start_str, end_str)
end_str[0,2] = (end_str[0,2].to_i + 24).to_s if end_str < start_str
end_str
end
Here are a few examples.
time_within_ref?("19:00", "02:00", "18:00", "03:00")
#=> true
time_within_ref?("19:00", "04:00", "18:00", "03:00")
#=> false
time_within_ref?("17:00", "02:00", "18:00", "03:00")
#=> false
time_within_ref?("18:00", "02:00", "18:00", "03:00")
#=> true
There are several ways to perform this in the database which are far more performant than loading a bunch of records into Rails.
While "pure ruby" solutions are a quick fix they will exhaust the available memory and crash your server given a non-trivial amount of records.
You can use a range together with .where to create a WHERE start_time BETWEEN a AND b clause that ensures that a time is within A and B.
starts_today = Model.where(
start_time: Time.current.beginning_of_day..Time.current.end_of_day
)
If you want to ensure that the entire span between start_time and end_time is within a set of bounds you can write you own where clause:
Model.where(
"start_time > :a AND end_time < :b",
a: Time.current.beginning_of_day,
b: Time.current.end_of_day
)
I need to know how many of the hours is within the timerange.
You can do this with the time/date functions in your database.
On postgres for example you can do:
bounds = Time.current.beginning_of_day..Time.current.end_of_day
Model.select(
"models.*, (EXTRACT(HOUR FROM end_time - start_time ) - EXTRACT(HOUR FROM end_time - '#{ bounds.end.iso8601 }')) AS number_of_hours"
)
Again calculating this in the DB is vital if you for example want to use this in a WHERE clause.
I think I figured it out.
Shift.start_time.strftime("%H:%M") => '20:00' && Shift.end_time.strftime("%H:%M") <= '01:00'
The .to_time was messing with me and also the ordering.

Ruby, difference between time an array was created and the current time

I am trying to get the difference between the hours in the time an array was created and the current time, i cant seem to get my head around it, I did this, which seems perfectly logical, but it doesnt seem to ever work.
mergelisting = MergeList.Pluck(:created_at, :partner, :gambler, :amount)
(mergelisting).each do |i|
t = Time.now
nowtime = t.strftime("%I")
nowtime.to_i
mergetime = i[1].strftime("%I")
mergetime.to_i
if nowtime - mergetime == 6
do some stuff...
end
end
My real question is the difference in hours between 24 and 6 is 6 hours, but 24-6 would not give 6. What can i do here
I'm assuming MergeList.Pluck returns an Array, and the first item in this array will be a Rails created_at column from the database. Then:
mergelisting = MergeList.Pluck(:created_at, :partner, :gambler, :amount)
mergetime = mergelisting.first # Time from DB (created_at)
nowtime = Time.now # Current time
timediff_s = nowtime - mergetime # Difference in seconds
timediff_h = timediff_s / (60 * 60).to_f # Difference in hours as a floating point number
#
# Not exactly sure if this is what you wanted, but you now
# have the time difference as a floating point number expressed
# in hours. So you can do whatever you want with it
#
if (timediff_h.to_i == 6)
...the difference is anywhere between 6.0 and 7.0 hours...
...do whatever you need to do...
end

Ruby Rails Average two attributes in a query returning multiple objects

I've got two attributes I'm trying to average, but it's only averaging the second field here. is there a way to do this?
e = TiEntry.where('ext_trlid = ? AND mat_pidtc = ?', a.trlid, a.pidtc).average(:mat_mppss_rprcp && :mat_fppss_rprcp)
e = TiEntry.where('ext_trlid = ? AND mat_pidtc = ?', a.trlid, a.pidtc).select("AVG(mat_mppss_rprcp) AS avg1, AVG(mat_fppss_rprcp) AS avg2").map { |i| [i.avg1, i.avg2] }
Is this working for you? it works as the average method does, but you can support as may values as you want
The advantage between this and the other queries here is this only uses one simple SQL query. The others fetch with an SQL everything in your table(can take some time if table is big) and then computes the average in ruby language
I am sure that you have all ready looked at http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-average
But you cant get the average of 2 things.
what you can do not to repeat your query is:
entries = TiEntry.where('ext_trlid = ? AND mat_pidtc = ?', a.trlid, a.pidtc)
average_mppss = entries.average(:mat_mppss_rprcp)
average_fppss = entries.average(:mat_fppss_rprcp)
this will only execute your query one time
I hope that this works for you

Rails: Count specific records then do calculation

I am attempting to do a rails record count then do a calculation from those records to give me a final number:
Example
100 Records = A
30 Records = B
Total Records = C
A+(-B)=C
I am not even going to show you what I tried... in retrospect I am very new to rails and it made no logical sense!
UPDATE:
To further expand:
When implementing this I realized that there might be some slight difference from what it solves above.
I have a MVC called "POST" It was some records within the table one specifically is called "VOTE" the vote integer will consist of 1 or (-1). Each post will have a VOTE column that represent a value of 1 or (-1). I am trying to create an analytic metric that consists of the following:
TOTAL = (Total posts with Value 1) + (Total posts with Value -1)
Example
1234 = 2000 + (-776)
Thank you in advance!
In general,
C = A.count + B.count
If you want C to be the union of A and B, then do
C = A & B
C.count # Number of elements in C
For your specific case:
yes_votes = POST.where('VOTE = ?', 1)
no_votes = POST.where('VOTE = ?', -1)
total = yes_votes.count - no_votes.count

Rails 3.1, Ruby 1.9.2, Mongoid 2.3.3 - the poltergeist is in my datetimez

I just spent a considerable amount of time trying to get this issue fixed, and although I did fix it (sort of) I'm nowhere near understanding what's going on.
Take a Mongoid model:
class Game
include Mongoid::Document
include Mongoid::Timestamps
field :start, type: DateTime
index :start
def process(attrs = nil, role = :default, guard_protected_attributes = true)
if attrs.keys.include?('start(1i)')
now = DateTime.now
year = attrs.delete('start(1i)').to_i || now.year
month = attrs.delete('start(2i)').to_i || now.month
day = attrs.delete('start(3i)').to_i || now.day
hour = attrs.delete('start(4i)').to_i || now.hour
min = attrs.delete('start(5i)').to_i || now.minute
sec = attrs.delete('start(6i)').to_i || 0 # seconds
zone = attrs.delete('start(7i)').to_i || 0 # UTC
# I'm not sure what is happening here, but we need to adjust the hour
# otherwise Rails/Mongoid will mangle the time...
start = DateTime.new(year, month, day, hour, min, sec, zone)
# First we set the time and self.start will be wrong by 6 hours (my timezone)
self.start = start
# We do this and the time will change by several hours!!!
self.start -= 0.seconds
# Can't make a simple substraction as we'll get a Rational? The WTFs just keep piling up...
diff = (self.start.to_i - start.to_i).seconds
self.start -= diff
self.start -= diff # Yeah, twice?
end
super(attrs, role, guard_protected_attributes)
end
end
Why the process method? Well, I can't let the start attribute be handled by Mongoid::MultiParameterAttributes, as "something" will "fix" it by adjusting it using my local time zone (haven't figured out which brilliant code is doing this).
In that code, the start variable will always have the correct time, but as you saw, self.start has to be beaten with a mallet until the time is correct too.
Weird? Man don't get me started. This is related to Rails multi-parameter attributes, which allows me to use several select tags for setting a date/time (the start(1i) stuff).
Time.zone is UTC, so I don't know why it's using my local time zone to mangle the time.
But the weirdest stuff is why do I have to make so many adjustments...
I'm not expecting to find a real solution anytime soon, but I wanted to know your thoughts.
PS: Awww, SO didn't let me add the poltergeist tag.
Turns out I just had to:
Mongoid::Config.use_utc = true
Mongoid::Config.use_activesupport_time_zone = true
That still doesn't explain the weird behavior do. Or maybe it does and I'm not seeing it :)

Resources