<file_sep>Rails.application.routes.draw do
  devise_for :users
  root to: 'pages#home'
  resources :users, only: [ :show, :index ]
  post 'users/:id/friendships', to: 'friendships#create', as: :user_friendships_create
  resources :challenges, only: [ :new, :create, :index, :show ] do
    resources :challenge_users, only: [ :new, :create ]
    resources :goals, only: [ :new, :create ]
  end
  delete 'friendships/:id', to: 'friendships#destroy', as: :friendships_destroy
  patch 'friendships/:id', to: 'friendships#update', as: :friendships_update
  resources :friendships, only: [ :index ]
  patch 'challenge_users/:id', to: 'challenge_users#update'
  post 'goals/:id/progress_entries', to: 'progress_entries#create'

  resources :user_goals do
    patch :plus_one
  end

  get "memories", to: "memories#index"

end
<file_sep>class UserGoalsController < ApplicationController

 def plus_one
  @user_goal = UserGoal.find(params[:user_goal_id])
  @user_goal.current_amount += 1
  @user_goal.save!
  @challenge = @user_goal.goal.challenge
  redirect_to challenge_path(@challenge, anchor: "container-#{@user_goal.goal.id}")
 end


end
<file_sep>class Challenge < ApplicationRecord
  belongs_to :user
  has_many :challenge_users
  has_many :users, through: :challenge_users
  has_many :goals
  has_many :user_goals, through: :goals

  validates :name, presence: true
  validates :end_date, presence: true
  validates :start_date, presence: true

  def day_of_challenge
    (Date.today - self.start_date).to_i
  end

  def challenge_duration
    (self.end_date - self.start_date).to_i
  end

  def days_left
    (self.end_date - Date.today).to_i
  end

end
<file_sep>class UserGoal < ApplicationRecord
  belongs_to :user
  belongs_to :goal
  has_many :steps

  # finds ACTUAL amount for specific user and specific goal
  # scope :user_amount_of_day, ->(goal, user) { where(user: user, goal: goal)[0].current_amount }

  def delta_to_target
    self.current_amount - self.goal.goal_for_the_day
  end

  def delta_to_team_average
    self.current_amount - self.goal.team_average
  end

end
<file_sep>class Goal < ApplicationRecord
  belongs_to :challenge
  has_many :user_goals
  has_many :steps, through: :user_goals
  has_many :users, through: :user_goals

  validates :name, presence: true
  validates :target_amount, presence: true
  validates :unit, presence: true
  # validates :goal_type, presence: true

  enum goal_type: [:min_amount, :max_amount]

  def team_average
    all_amounts = self.user_goals.map{|x| x[:current_amount]}
    team_average = all_amounts.inject(&:+).to_f / all_amounts.size
    return team_average
  end

  def min_max_nice
    self.goal_type == "min_amount" ? "min" : "max"
  end

  def amount_per_day
    (self.target_amount.to_f / self.challenge.challenge_duration.to_f)
  end

  def goal_for_the_day
    self.amount_per_day * self.challenge.day_of_challenge
  end








end
<file_sep>class GoalsController < ApplicationController
  def new
    @challenge = Challenge.find(params[:challenge_id])
    @goals = @challenge.goals
    @goal = Goal.new
  end


  def create
    @challenge = Challenge.find(params[:challenge_id])
    @goals = @challenge.goals
    @goal = Goal.new(goal_params)
    @goal.challenge = @challenge
    if @goal.save
      # UserGoal.create(user: user, goal: goal, current_amount: amount)
      @challenge.users.each do |user|
        UserGoal.find_or_create_by(goal: @goal, user: user)
        
      end
      redirect_to challenge_path(@challenge)
    else
      render :new
    end
  end


  private
  def goal_params
    params.require(:goal).permit(:name, :target_amount, :unit)
  end
end
<file_sep>class Step < ApplicationRecord
  belongs_to :user_goal
end
<file_sep>class UsersController < ApplicationController

  def index
    @friendships = Friendship.where("asker_id = ? or receiver_id = ?", current_user.id, current_user.id)
    @friends = []
    @friendships.each do |friendship|
      if friendship.receiver_id == current_user.id
        @friends << friendship.asker
      else
        @friends << friendship.receiver
      end
    end
    if params[:query].present?
      @users = User.where("first_name ILIKE ?", "%#{params[:query]}%")
    else
      @users = []
    end
    @users -= @friends
  end

end
<file_sep>class ChallengeUsersController < ApplicationController
  def new
    @challenge = Challenge.find(params[:challenge_id])
    @challenge_users = @challenge.challenge_users
    @challenge_user = ChallengeUser.new
    @friendships_unsorted = Friendship.where(asker_id: current_user.id) + Friendship.where(receiver_id: current_user.id)
    @friendships = @friendships_unsorted.select { |friendship| friendship.accepted? }
    @friends_unsorted = []
    @friendships.each do |friendship|
      @friends_unsorted << User.find(friendship.asker_id)
      @friends_unsorted << User.find(friendship.receiver_id)
    end
    @friends = @friends_unsorted.uniq.reject { |friend| friend.id == current_user.id }
  end


  def create
    @challenge = Challenge.find(params[:challenge_id])
    @challenge_users = @challenge.challenge_users
    @challenge_users_names = @challenge_users.map {|user| user.user.first_name}
    @challenge_user = ChallengeUser.new(challenge_user_params)
    @challenge_user.challenge = @challenge
    if @challenge_user.save && !@challenge_users_names.include?(@challenge_user.user.first_name)
      @challenge.goals.each do |goal|
        UserGoal.create(user_id: @challenge_user.user_id, goal_id: goal.id, current_amount: 0)
      end
      redirect_to challenge_path(@challenge)
    end
  end


  private
  def challenge_user_params
    params.require(:challenge_user).permit(:user_id)
  end
end

<file_sep>class FriendshipsController < ApplicationController
  def index
    @friendships = Friendship.where("asker_id = ? or receiver_id = ?", current_user.id, current_user.id)
    @friends = []
    @friends_pending = []
    @friends_accepting = []
    @friendships.each do |friendship|
      if friendship.status != "pending"
        if friendship.receiver_id == current_user.id
          @friends << friendship.asker
        else
          @friends << friendship.receiver
        end
      else
        if friendship.asker_id == current_user.id
          @friends_pending << friendship.receiver
        else
          @friends_accepting << friendship.asker
        end
      end
    end


  end

  def create
    friendship = Friendship.new
    friendship.asker = current_user
    user = User.find(params[:id])
    friendship.receiver = user
    friendship.status = 0
    friendship.save!
    redirect_to friendships_path
  end

  def update
    @friendships = Friendship.where("asker_id = ? and receiver_id = ? or asker_id = ? and receiver_id = ?", current_user.id, params[:id], params[:id], current_user.id)
    @friendships.each do |friendship|
      friendship.update(:status => 1)
    end
    redirect_to friendships_path
  end

  def destroy
    @friendships = Friendship.where("asker_id = ? and receiver_id = ? or asker_id = ? and receiver_id = ?", current_user.id, params[:id], params[:id], current_user.id)
    @friendships.each do |friendship|
      friendship.destroy
    end

    redirect_to friendships_path
  end

end
<file_sep>class AddDefaultValueUserGoal < ActiveRecord::Migration[6.0]
  def change
    change_column :user_goals, :current_amount, :integer, default: 0
  end
end
<file_sep># This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
#
# Examples:
#
#   movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
#   Character.create(name: 'Luke', movie: movies.first)
require 'date'

UserGoal.destroy_all
Goal.destroy_all
ChallengeUser.destroy_all
Challenge.destroy_all
Friendship.destroy_all
User.destroy_all



puts "** Let's create some users for my2022 **"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1617603749/da22yjwdbfkl4uq8cqvy.jpg')
jonas = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Jonas", last_name: "Hagedorn")
jonas.photo.attach(io: file, filename: 'jonas.jpg', content_type: 'image/jpg')
jonas.save!
puts "#{jonas.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1617604976/nuur2wmzwub7k9xcgd5f.jpg')
caterina = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Caterina", last_name: "Biffis")
caterina.photo.attach(io: file, filename: 'caterina.jpg', content_type: 'image/jpg')
caterina.save!
puts "#{caterina.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1617972092/txqoasjgslma5y22gfdu.jpg')
silke = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Silke", last_name: "Guthrie")
silke.photo.attach(io: file, filename: 'silke.jpg', content_type: 'image/jpg')
silke.save!
puts "#{silke.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1617954179/ojiticlbou6iocwbqeje.jpg')
seb = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Sebastian", last_name: "Strube")
seb.photo.attach(io: file, filename: 'seb.jpg', content_type: 'image/jpg')
seb.save!
puts "#{seb.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1596118942/yvkorthmlicxnuag0szm.jpg')
max = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Max", last_name: "Keller")
max.photo.attach(io: file, filename: 'max.jpg', content_type: 'image/jpg')
max.save!
puts "#{max.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1601461074/xrbi2mzjyawsdisknhdd.jpg')
santi = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Santi", last_name: "Sanchez")
santi.photo.attach(io: file, filename: 'santi.jpg', content_type: 'image/jpg')
santi.save!
puts "#{santi.first_name} was created. What a great user!"

file = URI.open('https://avatars.githubusercontent.com/u/37805251?v=4')
val = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Valerie", last_name: "Schraauwers")
val.photo.attach(io: file, filename: 'val.jpg', content_type: 'image/jpg')
val.save!
puts "#{val.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1617958938/yniyzgmayab38bubnpjb.jpg')
dave = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "David", last_name: "Klören
  ")
dave.photo.attach(io: file, filename: 'dave.jpg', content_type: 'image/jpg')
dave.save!
puts "#{dave.first_name} was created. What a great user!"

file = URI.open('https://res.cloudinary.com/wagon/image/upload/c_fill,g_face,h_200,w_200/v1617870772/pllppuncxqixjiwdavjr.jpg')
soto = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Soto", last_name: "Dimitriu")
soto.photo.attach(io: file, filename: 'soto.jpg', content_type: 'image/jpg')
soto.save!
puts "#{soto.first_name} was created. What a great user!"

file = URI.open('https://avatars.githubusercontent.com/u/80338339?v=4')
marnie = User.new(email: "<EMAIL>", password: "<PASSWORD>", first_name: "Marnie", last_name: "Nyenhuis")
marnie.photo.attach(io: file, filename: 'marnie.jpg', content_type: 'image/jpg')
marnie.save!
puts "#{marnie.first_name} was created. What a great user!"

puts "** #{User.count} beautiful users created! They will love the app! **"

puts ""

puts "Lets make some friendships"

friendship1 = Friendship.new(asker_id: jonas.id, receiver_id: seb.id, status: 1)
friendship1.save!

friendship1 = Friendship.new(asker_id: jonas.id, receiver_id: caterina.id, status: 1)
friendship1.save!

friendship1 = Friendship.new(asker_id: jonas.id, receiver_id: silke.id, status: 1)
friendship1.save!

friendship1 = Friendship.new(asker_id: jonas.id, receiver_id: marnie.id, status: 1)
friendship1.save!


puts ""

puts "** Now let's build a challenge **"

challenge1 = Challenge.new(name: "Surviving the bootcamp", description: "Let's not destroy our bodies tooo much while coding the whole day", start_date: "12.04.2021", end_date: "13.06.2021", user: jonas)
challenge1.save!
puts "The challenge with the fancy name << #{challenge1.name} >> was created by #{challenge1.user.first_name}. It starts at #{challenge1.start_date} and ends at #{challenge1.end_date}."

puts ""

puts "** Let's see, which friends will be joining #{challenge1.user.first_name} for the challenge ***"

ChallengeUser.create(challenge: challenge1, user: jonas)
ChallengeUser.create(challenge: challenge1, user: seb)
ChallengeUser.create(challenge: challenge1, user: silke)
ChallengeUser.create(challenge: challenge1, user: caterina)

puts ""

puts "** Now let's add some GOALS to the challenge << #{challenge1.name} >>**"

goal1 = Goal.new(challenge: challenge1, name: "Flashcard Practice", target_amount: 36, unit: "days", goal_type: :min_amount)
goal1.save!
puts "The goal << #{goal1.name} (#{goal1.goal_type} #{goal1.target_amount} #{goal1.unit}) >> was added to the challenge."

# add minmax

goal2 = Goal.new(challenge: challenge1, name: "Do sports", target_amount: 27, unit: "Sport Sessions", goal_type: :min_amount)
goal2.save!
puts "The goal << #{goal2.name} (#{goal2.goal_type} #{goal2.target_amount} #{goal2.unit}) >> was added to the challenge."

goal3 = Goal.new(challenge: challenge1, name: "Meet new people", target_amount: 32, unit: "new Person", goal_type: :min_amount)
goal3.save!
puts "The goal << #{goal3.name} (#{goal3.goal_type} #{goal3.target_amount} #{goal3.unit}) >> was added to the challenge."

goal4 = Goal.new(challenge: challenge1, name: "Rock the demo day", target_amount: 1, unit: "Demo Day rocked", goal_type: :min_amount)
goal4.save!
puts "The goal << #{goal4.name} (#{goal4.goal_type} #{goal4.target_amount} #{goal4.unit}) >> was added to the challenge."

puts ""

puts "*** Now let's see, how everyone is performing... ***"

UserGoal.create(user: jonas, goal: goal1, current_amount: 37)
UserGoal.create(user: seb, goal: goal1, current_amount: 20)
UserGoal.create(user: silke, goal: goal1, current_amount: 32)
UserGoal.create(user: caterina, goal: goal1, current_amount: 25)

UserGoal.create(user: jonas, goal: goal2, current_amount: 20)
UserGoal.create(user: seb, goal: goal2, current_amount: 12)
UserGoal.create(user: silke, goal: goal2, current_amount: 33)
UserGoal.create(user: caterina, goal: goal2, current_amount: 37)

UserGoal.create(user: jonas, goal: goal3, current_amount: 15)
UserGoal.create(user: seb, goal: goal3, current_amount: 45)
UserGoal.create(user: silke, goal: goal3, current_amount: 35)
UserGoal.create(user: caterina, goal: goal3, current_amount: 25)

UserGoal.create(user: jonas, goal: goal4, current_amount: 0)
UserGoal.create(user: seb, goal: goal4, current_amount: 1)
UserGoal.create(user: silke, goal: goal4, current_amount: 1)
UserGoal.create(user: caterina, goal: goal4, current_amount: 1)

puts "/// USER PROGRESS TO BE ADDED ///"

puts "** Now let's build a 2nd challenge **"

challenge2 = Challenge.create(name: "Life after bootcamp", description: "Let's make sure to keep crushing what we have learned", start_date: "11.06.2021", end_date: "09.09.2021", user: jonas)
challenge2.save!

ChallengeUser.create(challenge: challenge2, user: jonas)
ChallengeUser.create(challenge: challenge2, user: marnie)

goal21 = Goal.new(challenge: challenge2, name: "Revise Lectures", target_amount: 25, unit: "Lectures", goal_type: :min_amount)
goal21.save!
puts "The goal << #{goal21.name} (#{goal21.goal_type} #{goal2.target_amount} #{goal21.unit}) >> was added to the challenge."

goal22 = Goal.new(challenge: challenge2, name: "Play CSS Codewars", target_amount: 50, unit: "Hours", goal_type: :min_amount)
goal22.save!
puts "The goal << #{goal22.name} (#{goal22.goal_type} #{goal2.target_amount} #{goal22.unit}) >> was added to the challenge."

puts "*** Now let's see, how everyone is performing... ***"

UserGoal.create(user: jonas, goal: goal21, current_amount: 0)
UserGoal.create(user: jonas, goal: goal22, current_amount: 0)

UserGoal.create(user: marnie, goal: goal21, current_amount: 0)
UserGoal.create(user: marnie, goal: goal22, current_amount: 0)
<file_sep>class Friendship < ApplicationRecord
  belongs_to :asker, class_name: "User"
  belongs_to :receiver, class_name: "User"

  enum status: [:pending, :accepted, :declined]
end
<file_sep>class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :user_goals
  has_many :challenge_users
  has_many :challenges, through: :challenge_users
  has_many :goals, through: :user_goals
  has_many :friendships_as_asker, class_name: "Friendship", foreign_key: :asker_id
  has_many :friendships_as_receiver, class_name: "Friendship", foreign_key: :receiver_id

  validates :first_name, presence: true
  validates :last_name, presence: true

  has_one_attached :photo

  def full_name
    "#{first_name} #{last_name}"
  end

end
<file_sep>require 'date'
class ChallengesController < ApplicationController
  def new
    @challenge = Challenge.new
  end

  def create
    @challenge = Challenge.new(challenge_params)
    @challenge.user = current_user
    if @challenge.save
    ChallengeUser.create(challenge: @challenge, user: current_user)  # accepted: true)
      redirect_to challenge_path(@challenge)
    else
      render :new
    end
  end

  def index
    @challenge_users = ChallengeUser.where(user: current_user)
  end

  def show
    @challenge = Challenge.find(params[:id])
    @users = @challenge.users
    @goals = @challenge.goals
  end

  private
  def challenge_params
    params.require(:challenge). permit(:name, :start_date, :end_date)
  end

end

<file_sep>class AddStartDateToChallenge < ActiveRecord::Migration[6.0]
  def change
    add_column :challenges, :start_date, :date
  end
end
