diff --git a/src/config.rb b/src/config.rb index 6d43cde..e7e1b0a 100644 --- a/src/config.rb +++ b/src/config.rb @@ -32,11 +32,13 @@ LOGIN_ERRORS = { fail: "Wrong password and/or email" } +# Auction stuff +AH_BUYOUT_FACTOR = 1.8 +AH_BIDS_FACTOR = 1.01 # min 1% AUCTION_ERRORS = { titlelen: "Title length must be between #{MIN_TITLE_LEN} and #{MAX_TITLE_LEN} characters!", initprice: "The initial price must be at least #{MIN_INIT_PRICE}!", - deltatime: "Time span is too short! Must be at least one day!" + deltatime: "Time span is too short! Must be at least one day!", + bidamount: "Bid amount must be at least #{((AH_BIDS_FACTOR-1)*100).round(2)}% greater than the highest bid!" } -# Auction stuff -AH_BUYOUT_FACTOR = 1.8 diff --git a/src/const.rb b/src/const.rb index 2c5421c..39a2e39 100644 --- a/src/const.rb +++ b/src/const.rb @@ -65,6 +65,14 @@ BIO_REGEX_STR = "{#{MIN_BIO_LEN},#{MAX_BIO_LEN}}" DESC_REGEX_STR = "{#{MIN_DESC_LEN},#{MAX_DESC_LEN}}" TITLE_REGEX_STR = "{#{MIN_TITLE_LEN},#{MAX_TITLE_LEN}}" +TIME_FORMATS = { + w: 604800, + d: 86400, + h: 3600, + m: 60, + s: 1 +} + # Routes that needs auth AUTH_ROUTES = %w[/settings /auction /user /admin] diff --git a/src/lib/db_models.rb b/src/lib/db_models.rb index c1a8213..45d6d31 100644 --- a/src/lib/db_models.rb +++ b/src/lib/db_models.rb @@ -283,12 +283,12 @@ class Auction < EntityModel attr_reader :user_id, :title, :description, :init_price, :start_time, :end_time def initialize(data) super data - @user_id = data["user_id"] + @user_id = data["user_id"].to_i @title = data["title"] @description = data["description"] - @init_price = data["init_price"] - @start_time = data["start_time"] - @end_time = data["end_time"] + @init_price = data["init_price"].to_i + @start_time = data["start_time"].to_i + @end_time = data["end_time"].to_i end def self.validate_ah(title, description, init_price, delta_time) @@ -356,8 +356,43 @@ class Auction < EntityModel Time.now.to_i > @end_time end + def time_left + @end_time - Time.now.to_i + end + + def time_left_s + left = self.time_left + result = [] + TIME_FORMATS.each do |sym, count| + amount = left.to_i / count + if amount > 0 then + result << "#{amount}#{sym.to_s}" + puts "#{sym} #{count}, #{left} : #{amount} : #{result}" + left -= count*amount + end + end + return result.join ", " + end + def bids - return [] + Bid.get_bids(@id) + end + + def place_bid(uid, amount, message) + Bid.place(@id, uid, amount, message) + end + + def max_bid + max_bid = self.bids.max_by {|bid| bid.amount} + end + + def current_bid + mbid = self.max_bid + if mbid != nil then + return mbid.amount + else + return @init_price + end end end @@ -372,15 +407,27 @@ class Bid < EntityModel @message = data["message"] end + def self.get_bids(ahid) + data = self.get "*", "auction_id = ?", ahid + data && data.map! {|dat| self.new(dat)} + end + def self.place(ahid, uid, amount, message) - # TODO: check if bid is greater than prev - payload = { - auction_id: ahid, - user_id: uid, - amount: amount, - message: message - } - self.insert(payload) + ah = Auction.find_by_id + if not ah then return false, "Invalid auction" end + max_bid = ah.max_bid + + if amount >= max_bid.amount * AH_BIDS_FACTOR then + payload = { + auction_id: ahid, + user_id: uid, + amount: amount, + message: message + } + self.insert(payload) + else + return false, AUCTION_ERRORS[:bidamount] + end end end diff --git a/src/routes/auction.rb b/src/routes/auction.rb index da85604..7dd11e5 100644 --- a/src/routes/auction.rb +++ b/src/routes/auction.rb @@ -57,3 +57,23 @@ get "/auctions/:id" do raise Sinatra::NotFound end end + +post "/auctions/:id/bids" do + id = params[:id].to_i + auction_obj = Auction.find_by_id id + + amount = params[:amount].to_f + message = params[:message] + + if !auction_obj.nil? then + success, resp = auction_obj.place_bid( session[:userid], amount, message) + if success then + flash[:success] = "Placed bid." + else + flash[:error] = resp + end + redirect "/auctions/#{id}" + else + raise Sinatra::NotFound + end +end diff --git a/src/views/auction/view.slim b/src/views/auction/view.slim index fc320c4..c9e2c2b 100644 --- a/src/views/auction/view.slim +++ b/src/views/auction/view.slim @@ -18,19 +18,29 @@ #auctioninfo.card h2 = auction.title - ul.list-container#category-list - - auction.categories.each do |category| - ul = category.name - - - if auction.bids.length >= 1 - .bid-container - - auctions.bids.each do |bid| - .bid - | BID - - else - p = "No bids! Be the first to bid on this item!" - - + - if auction.categories.length > 0 + ul.list-container#category-list + ul + | Categories: + - auction.categories.each do |category| + ul style="color: #{category.color}" = category.name + - if not auction.expired? + .card.border + h3 + | Current bid: + span.green = "#{COINS_PREFIX}#{auction.current_bid}#{COINS_SUFFIX}" + h3 + | Minimum bid factor: + span.gray = "#{((AH_BIDS_FACTOR-1)*100).round(2)}%" + h3 + | Buyout factor: + span.gray = "#{((AH_BUYOUT_FACTOR-1)*100).round(2)}%" + h3 + | Expires in: + span.red = "#{auction.time_left_s}" + - else + h3.red.tcenter + | Auction Expired script src="/js/slides.js" type="text/javascript" diff --git a/src/views/stylesheets/style.sass b/src/views/stylesheets/style.sass index b0625f5..0325fad 100644 --- a/src/views/stylesheets/style.sass +++ b/src/views/stylesheets/style.sass @@ -15,6 +15,7 @@ $shadow_clr: $bg_dark_clr $border_clr: $bg_alt_clr $green_clr: #5cb85c $red_clr: #de2a1d +$yellow_clr: #FFBF00 $gray_clr: #888 $special_clr: #4776C1 @@ -309,6 +310,8 @@ ul.list-container color: $green_clr .red color: $red_clr +.yellow + color: $yellow_clr .gray color: $gray_clr @@ -457,13 +460,23 @@ ul.list-container #auctioninfo grid-area: in + + .card + margin-top: 2rem h2 + padding: 0 font-size: 1.8rem + h3 + font-size: 1.5rem + #category-list flex-direction: row height: unset + ul + padding: 0 + margin-right: 1rem .slideshow-container grid-area: im