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