Grouping array by sequencial date - ruby-on-rails

This is more of a brains storm question
I would like to run something like
Student Model
id
name
age
so on...
GameStatus Model
id
game_id
student_id
status
created_at
Student has many game_statuses.
so every time a student opens a game it is added to the game_status model
I want to send little messages like... Congratulation! You have completed 5 challenges in a row.
So the marks are 5, 10, 15, 20 and 30.
It's pretty simple till here. I just loop through students and then loop through their game_statuses and if the count comes up to one of those marks I'll send a message.
But I want to make sure they hit those marks in a row.
As in 5 in the last five days or 10 in the last 10 days not broken.
So 3 times the week after last 1 time last week and 1 time this week will return 5 but it should not trigger the reward.
I was thinking of looking into the created_at date and check if they are in a array of dates such as [today, today -1, today -2, today -3, today -4]
#student = Student.find(param[:id])
#games = #student.game_statuses
total_games = []
for game in #games do
if game.status = 'completed'
total_games += game.id
end
end
return total_games.count
Would it be possible to achieve this in a more elegant way?

Related

Is there a more efficient way to store a shop's hours?

I have a model Shop and I want to store every shop's opening and closing hours. If their hours were the same every day, it would be easy, just two attributes: opening_time and closing_time. But most businesses have different times on different days, plus holidays.
So as it stands, I would have to add two attributes for each weekday for a total of fourteen attributes, plus probably create an entirely new model Holiday, because it's unpredictable how many holidays any given business will take off.
It can be done, it just seems unnecessarily complicated for recording a businesses' hours, and I don't want to bloat my schema. Does anyone know of a better way?
You should have 3 Models :
Shop - Business Entity
Slot - containing start_time, end_time, weekly_exception which belongs to shop
Here, weekly_exception is an integer in range(0..127) which takes care for which weekday this slot is valid
For Instance: 127 means (1111111) in base-2 representation => slot valid for all 7 weekdays
SlotException - containing blocked_start_time, blocked_end_time, exception_day, is_on_leave which belongs to shop
Here, exception_day is date for which slot is blocked between blocked_start_time and blocked_end_time timings only.
and is_on_leave is boolean take care for slot holiday.
Ruby code to get weekdays out of weekly_exception:
def get_weekdays(weekly_exception)
i, count = 1, 0
map, weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], []
while count < 7
weekdays.push(map[count]) if (weekly_exception & i) > 0
i = i << 1
count += 1
end
return weekdays
end

Show objects based on selected week

I have an active relation Bar object with an attribute shift_date. shift_date represents each day between March and June. March and June comes from Foo which has attributes start_month and end_month:
f = Foo.find(1)
days = (f.end_month - f.start_month).to_i
weeks = (days * 0.142857).round(2)
f.bars will give me days objects. Where days is the total amount of objetcs.
My trouble is to get Bars objects, objects for week 1, 2 or 3 etc:
f.bars.where('shift_date >= ?', (weeks/7.days)).group_by{ |result| result }
operator does not exist: timestamp without time zone >= numeric
So what am I saying? Give me all objects on week 1 or week 5, if any. How do I go about this, please?
Im on to something but not right:
f.bars.where('shift_date >= ?', Date.today).group_by{ |result| result}
Edit:
Im almost there. I could splat out the days with:
days_array = *(f.start_month..f.end_month)
then
f.bars.where(shift_date: days_array[0]..days_array[7])
That would be the answer! But...not really. For my views, I need to group the splatted days in a 7 days interval as week, so days_array[0] to days_array[7] would be week 1 and days_array[8] to days_array[14] would be week 2 etc. How to show that in the view? This will give me everything I need.

Rails get equal segments in between a date range

I have a product model and orders associated to the product. I wanted to analyze all orders from creation of product to current time. I was thinking to optimize, I would take products created at day, and current time as start and end points. The next step would be to automatically pull 10 equally spaced times between start and current time and place them in an array. For each one of these dates, query orders for the 10 dates provided.
Question is, is this the best approach to analyzing order data / performance on the query? If so, how do you pull the 10 dates in between the created at and current time range in Rails.
I have the following pseudocode --
Products.where(event_id: event)[Products.where(event_id: event).first.created_at.to_i..Time.now.to_i)].each_slide(10) do |p|
# Loop through orders of the 10 pulled days
Orders.where(product_id: p.id).each do |o|
# Add products to one of the 10 pulled days
end
end
Example Pseudocode:
1st Getting the last Product's created_at value
require 'date'
prod_date = Products.where(event_id: event).last.created_at
prod_date = prod_date.to_time.strftime("%Y-%m-%d %H:%M:%S")
2nd Getting last 10 records in products table based on prod_date & date_today.
date_today = DateTime.now.strftime("%Y-%m-%d %H:%M:%S")
Products.where('event_id ? AND (created_at BETWEEN ? AND ?)', event, prod_date, date_today).limit(10)
You can also arrange it if you want by adding e.g. .order("created_at DESC")
3rd Start to iterate with you orders data from the result above.
Orders.where(product_id: p.id).each do |o|
# Add products to one of the 10 pulled days
end
====================================
I understand want you plan to do. Honestly I haven't tried that.
But, my idea for that is, for ex. you have 10 data & you want to get 3 equally spaced values.
Why not try to iterate it by 3 (but get the first value).
Imagine this is your data: 1 2 3 4 5 6 7 8 9 10
get the first = 1
iterate the next by (3) = 4, 7, 10
Result = 1, 4, 7, 10
You may need to get the first & last data, depends on how many
3 equally spaced values
you want to get from total result count.

Rails - grouping by day for the last week

I'm trying to create an array that has the total of all sales a company does for each day of the week. Right now I have something similar to this
#sales = Sale.all
#sales_total = #sales.map{|sale|sale.total.to_i}
Which returns an array of each total for every single sale.
Before turning it into an array, how can I group Sale by day, and adding total together?
I'm a fan of groupdate gem.
You ca do something like:
#sales_total = Sale.group_by_day(:created_at).order("day asc").sum(:total)
Assuming total is the column you want to sum up.
EDIT - To add a interval of time condition you can use where, for example:
#sales_total = Sale.where('created_at between ? and ?', Date.today, 1.week.ago).group_by_day(:created_at).order("day asc").sum(:total)

Getting list of available dates from rental app

I am creating a ROR app for an e-commerce site which handles the management of renting items for a period of time. The items will be physically delivered and picked-up. Item are always rented for 30 days.
So the problem I am facing, is I need to somehow get which days an item can be rented and is available for at least 30 days from that point. (for example, a customer couldn't rent an item today if it is reserved to be rented 10 days from now)
In my database I have a rentals table that stores the pickup and delivery date.
I will be using a jQuery datepicker, and just need to load available dates 1 month at a time (I can redo the query each time the next month button is pressed to hide unavailable dates)
What would be the best approach to performing this type of query and getting all the days in a month in which an item is available for 30 days? I could always iterate through every single day in the month and check if there are any other records within 30 days, but that seems like a surplus of queries.
Any help would be greatly appreciated.
Thanks,
Tyler
How do you know the day an item is reserved to be picked up? Make a query based on that. Perhaps your Rental model has a reserved_on attribute?
class Rental < ActiveRecord::Base
scope :available, where('rented = ? AND reserved_on > ?', false, 30.days.from_now)
end
EDIT in response to comments
If are looking at a single object you could create methods on it something like this:
def last_available_day
delivery_date && delivery_date - rental_period # 30 days
end
def is_available_on?(date)
return true unless last_available_day
date <= last_available_day
end

Resources