LifePex/src/systems/pex.rb

333 lines
11 KiB
Ruby

require "date"
require "active_support/all"
require_relative "./auth.rb"
require_relative "./csrf.rb"
require_relative "../utils/users.rb"
class LifePex::Systems::PexSystem < LifePex::Systems::AuthSystem
include LifePex::Systems::CrlfHelper
get "/today", auth: [] do
cookies.set "date", { value: "now", httponly: false }
redirect "/"
end
get "/yesterday", auth: [] do
cookies.set "date", { value: "yesterday", httponly: false }
redirect "/"
end
def pex_by_models(params, filter_hidden: true)
user_pexs = my_user_pexs(cookies, get_user_date)
user_pexs_amounts = user_pexs.group_by { |user_pex| user_pex[:pex_id] }
pexs = LifePex::Pex.where(user_id: current_user_id)
pexs = pexs.where(hidden: false) if filter_hidden
pexs = pexs.all
user_pexs_last_inserted_at = LifePex::UserPex.last_inserted_at(current_user_id).all
pex_by_models = pexs.map do |pex|
{
pex: pex,
user_pexs: {
at_date: (user_pexs_amounts[pex[:id]] || []).length,
last_inserted_at: (user_pexs_last_inserted_at.find{ |up| up[:pex_id] == pex[:id] } || {})[:last_inserted_at],
},
}
end
pex_by_models
end
get "/", auth: [], provides: 'html' do
pex_by_models = pex_by_models(params, filter_hidden: params['filter_hidden'] != 'false')
slim :index, locals: { pex_by_models: pex_by_models }
end
post "/", auth: [] do
user_id = user_id_decoded(cookies)
pex_id = params["id"]
if params["type"] == "+"
LifePex::UserPex.new(user_id: user_id, pex_id: pex_id, created_at: get_user_date).save
elsif params["type"] == "-"
user_pex = LifePex::UserPex.where(user_id: user_id, pex_id: pex_id, created_at: get_user_date).select(:id).first
halt 400, "No user pex can be found" if user_pex.nil?
LifePex::UserPex.where(id: user_pex[:id]).delete
end
redirect "/"
end
get "/pexs", auth: [] do
categories = LifePex::Pex
.select(:category)
.where(user_id: current_user_id)
.distinct
.pluck(:category)
slim :pex_form, locals: { categories: categories }
end
get "/pexs/update", auth: [] do
pex = LifePex::Pex.where(id: params["id"]).first
categories = LifePex::Pex
.select(:category)
.where(user_id: current_user_id)
.distinct
.pluck(:category)
slim :pex_form, locals: { pex: pex, categories: categories, submit_name: "update" }
end
post "/pexs", auth: [] do
pex_id = if params["id"]
LifePex::Pex.where(id: params["id"]).update(name: params['name'], category: params['category'].to_s.downcase, amount: params['amount'])
else
LifePex::Pex.new(name: params['name'], category: params['category'], amount: params['amount'], user_id: current_user.id).save
end
if pex_id
redirect "/"
else
slim :register, locals: { flash: { danger: "Failed to add #{params['name']}" } }
end
end
post "/pexs/delete", auth: [] do
removed = LifePex::Pex.where(id: params['id']).delete
links_removed = LifePex::UserPex.where(pex_id: params['id']).delete
slim :pex_removed, locals: { flash: { success: "#{removed} model and #{links_removed} marks removed" } }
end
post "/pexs/hide", auth: [] do
pex = LifePex::Pex.find(id: params['id'])
pex.set(hidden: !pex.hidden).save
redirect '/'
end
post "/pexs/bookmark", auth: [] do
pex = LifePex::Pex.find(id: params['id'])
set_flag = pex.bookmarked? ? "" : "bookmarked"
pex.set(flag: set_flag).save
redirect '/'
end
def compute_highchart_cumul(pex_data)
total = 0
pex_data.map do |v|
total += v
end
end
def get_recap_infos(params, cookies)
user_pexs = my_user_pexs(cookies)
pexs = LifePex::Pex.setup_user_pexs(user_id: current_user_id, user_pexs: user_pexs)
total_xp = pexs.values.sum { |up| up[:total_by_date].values.sum }
level = LifePex::Level.new total_xp
all_category = pexs.values.map(&:category).uniq
start_date = 60.days.ago.to_date
if params["days_ago"]
start_date = params["days_ago"].to_i.days.ago.to_date
elsif params["since_first_jan"]
year = Date.today.year
first_jan = Date.new(year, 1, 1)
start_date = first_jan
end
all_dates = (start_date..(Date.today)).to_a
pex_table_by_date = all_dates.map { |date| [date, 0] }.to_h
pexs.values.each do |pex|
pex[:total_by_date].each do |date, total|
# pex_table_by_date[date] ||= 0
pex_table_by_date[date] += total if pex_table_by_date[date]
end
end
pex_table_by_category_and_date = all_category.map do |category|
[
category,
all_dates.map { |date| [date, 0] }.to_h,
]
end.to_h
pexs.values.each do |pex|
pex[:total_by_date].each do |date, total|
category = pex[:category]
# pex_table_by_category_and_date[category] ||= {}
# pex_table_by_category_and_date[category][date] ||= 0
pex_table_by_category_and_date[category][date] += total if pex_table_by_category_and_date[category][date]
end
end
highchart_total = {
name: 'total',
data: compute_highchart_cumul(pex_table_by_date.values),
}
highchart_tables = pex_table_by_category_and_date.map do |category, total_by_date|
{
name: category,
data: compute_highchart_cumul(total_by_date.values),
}
end.unshift(highchart_total)
recalls = LifePex::Recall.where(user_id: current_user_id).all
recalls_not_validated = recalls.filter do |recall|
pex = pexs[recall[:pex_id]]
validated = pex[:count_by_date].filter do |date, _|
date >= Date.today - recall[:span_duration]
end.values.sum
validated < recall[:repeated]
end
all_setup = LifePex::Achievement.where(user_id: current_user_id).map(&:to_dsl_setup)
medals = all_setup.filter do |success|
success.call(user_pexs, pexs.values)
end
{
pex_tables: highchart_tables,
start_date: start_date,
all_dates: all_dates,
level: level,
medals: medals,
recalls_not_validated: recalls_not_validated,
}
end
get "/recap", auth: [], provides: 'html' do
recap_infos = get_recap_infos(params, cookies)
slim :recap, locals: recap_infos
end
extend DocMyRoutes::Annotatable
register Sinatra::Namespace
namespace '/api/pex/v1' do
summary 'Get a dataset by category of the total point by time'
produces 'application/json'
status_codes [200]
get "/recap", auth: [], provides: 'json' do
recap_infos = get_recap_infos(params, cookies)
{
pex_tables: recap_infos[:pex_tables],
all_dates: recap_infos[:all_dates],
level: recap_infos[:level].to_h,
}.to_json
end
summary 'The the list of the pex and user pex for eahc model'
produces 'application/json'
status_codes [200]
get "/pex_by_models", auth: [], provides: 'json' do
pex_by_models = pex_by_models(json_params)
pex_by_models.to_json
end
namespace "/pex" do
summary 'Get a list of all pex'
produces 'application/json'
status_codes [200]
get "/", auth: [], provides: 'json' do
current_user.pexs.to_json
end
summary 'Create a new pex'
produces 'application/json'
status_codes [200]
parameter :name, required: true, type: 'string', in: 'body'
parameter :category, required: true, type: 'string', in: 'body'
parameter :amount, required: true, type: 'number', in: 'body'
parameter :auth, required: true, type: 'string', in: 'cookies'
post "/", auth: [], provides: 'json' do
pex_id = LifePex::Pex.new(
name: json_params['name'],
category: json_params['category'],
amount: json_params['amount'],
user_id: current_user.id,
).save
{
message: "entity created",
pex: LifePex::Pex.find(id: pex_id),
}.to_json
end
summary 'Show the state of a pex'
notes "Sloppy implementation"
produces 'application/json'
status_codes [200]
parameter :id, required: true, type: 'string', in: 'path'
get "/by_id/:id", auth: [], provides: 'json' do
{
pex: LifePex::Pex.find(
id: params["id"],
user_id: current_user.id,
),
}.to_json
end
summary 'Modify an existing pex'
produces 'application/json'
status_codes [200]
parameter :id, required: true, type: 'integer', in: 'path'
parameter :name, required: false, type: 'string', in: 'body'
parameter :category, required: false, type: 'string', in: 'body'
parameter :amount, required: false, type: 'number', in: 'body'
parameter :auth, required: true, type: 'string', in: 'cookies'
post "/by_id/:id", auth: [], provides: 'json' do
LifePex::Pex.where(id: params["id"]).update(
name: json_params['name'],
category: json_params['category'].to_s.downcase,
amount: json_params['amount'],
)
{
message: "entity updated",
pex: LifePex::Pex.find(id: params["id"]),
}.to_json
end
summary 'Remove a pex and its dependencies'
notes "Sloppy implementation"
produces 'application/json'
status_codes [200]
parameter :id, required: true, type: 'integer', in: 'path'
parameter :auth, required: true, type: 'string', in: 'cookies'
delete "/by_id/:id", auth: [], provides: 'json' do
amount1 = LifePex::Pex.where(id: params["id"], user_id: current_user.id).delete
amount2 = LifePex::UserPex.where(pex_id: params["id"], user_id: current_user.id).delete
{
message: "deleted #{amount1 + amount2} entities",
amount1: amount1,
amount2: amount2,
}.to_json
end
summary 'Increase the amount occurence of this pex for a day (default today)'
notes "Sloppy implementation"
produces 'application/json'
status_codes [200]
parameter :id, required: true, type: 'integer', in: 'path'
parameter :date, required: false, type: '"now"|"yesterday"', in: 'cookies'
parameter :auth, required: true, type: 'string', in: 'cookies'
post "/by_id/:id/mark", auth: [], provides: 'json' do
user_id = user_id_decoded
pex_id = params["id"]
LifePex::UserPex.new(user_id: user_id, pex_id: pex_id, created_at: get_user_date).save
{ message: "ok" }.to_json
end
summary 'Decrease the amount occurence of this pex for a day (default today)'
notes "Sloppy implementation"
produces 'application/json'
status_codes [200]
parameter :id, required: true, type: 'integer', in: 'path'
parameter :date, required: false, type: '"now"|"yesterday"', in: 'cookies'
parameter :auth, required: true, type: 'string', in: 'cookies'
post "/by_id/:id/undo_mark", auth: [], provides: 'json' do
user_id = user_id_decoded
pex_id = params["id"]
id = LifePex::UserPex.where(user_id: user_id, pex_id: pex_id, created_at: get_user_date).select(:id).first[:id]
LifePex::UserPex.where(id: id).delete
{ message: "ok" }.to_json
end
end
end
include LifePex::Systems::ApiList
end