1
0
mirror of https://github.com/jcwimer/wrestlingApp synced 2026-03-25 01:14:43 +00:00

Merge pull request #6 from jcwimer/development

Development Merge
This commit is contained in:
2017-01-18 09:23:26 -05:00
committed by GitHub
109 changed files with 6902 additions and 954 deletions

3
.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
.git
frontend/node_modules
log

1
.gitignore vendored
View File

@@ -16,3 +16,4 @@
/tmp
.rvmrc
/deploy/prod.env
frontend/node_modules

View File

@@ -56,7 +56,9 @@ gem 'spring', :group => :development
gem 'delayed_job_active_record'
gem 'puma'
gem 'brakeman'
gem 'rails-lineman'
group :development do
#gem 'bullet'
end

View File

@@ -131,6 +131,8 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
rails-lineman (0.3.0)
rake
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
@@ -207,6 +209,7 @@ DEPENDENCIES
passenger
puma
rails (= 4.2.5)
rails-lineman
rails_12factor
rb-readline
round_robin_tournament
@@ -217,5 +220,8 @@ DEPENDENCIES
turbolinks
uglifier (>= 1.3.0)
RUBY VERSION
ruby 2.3.0p0
BUNDLED WITH
1.11.2
1.13.5

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@@ -0,0 +1,4 @@
/*
Place all the styles related to the matching controller here.
They will automatically be included in application.css.
*/

View File

@@ -0,0 +1,28 @@
class ApiController < ApplicationController
protect_from_forgery with: :null_session
def index
end
def tournaments
if params[:search]
@tournaments = Tournament.search(params[:search]).order("created_at DESC")
else
@tournaments = Tournament.all.sort_by{|t| t.daysUntil}.first(20)
end
end
def tournament
@tournament = Tournament.where(:id => params[:tournament]).includes(:schools,:weights,:mats,:matches,:user,:wrestlers).first
end
def newTournament
@tournament = Tournament.new(JSON.parse(params[:tournament]))
@tournament.save
end
def currentUserTournaments
@tournaments = current_user.tournaments
end
end

View File

@@ -3,8 +3,21 @@ class ApplicationController < ActionController::Base
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
after_filter :set_csrf_cookie_for_ng
def set_csrf_cookie_for_ng
cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end
rescue_from CanCan::AccessDenied do |exception|
# flash[:error] = "Access denied!"
redirect_to '/static_pages/not_allowed'
end
protected
# In Rails 4.2 and above
def verified_request?
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
end
end

View File

@@ -163,7 +163,7 @@ class TournamentsController < ApplicationController
end
def generate_matches
@tournament.generateMatchups
GenerateTournamentMatches.new(@tournament).generate
end
def brackets

View File

@@ -1,6 +1,6 @@
class WeightsController < ApplicationController
before_action :set_weight, only: [:show, :edit, :update, :destroy]
before_filter :check_access, only: [:new,:create,:update,:destroy,:edit]
before_action :set_weight, only: [:show, :edit, :update, :destroy,:re_gen]
before_filter :check_access, only: [:new,:create,:update,:destroy,:edit, :re_gen]
# GET /weights/1
@@ -69,6 +69,11 @@ class WeightsController < ApplicationController
format.json { head :no_content }
end
end
def re_gen
@tournament = @weight.tournament
GenerateTournamentMatches.new(@tournament).generateWeight(@weight)
end
private
# Use callbacks to share common setup or constraints between actions.

View File

@@ -31,6 +31,7 @@ class WrestlersController < ApplicationController
def edit
@weight = @wrestler.weight
@weights = @school.tournament.weights.sort_by{|w| w.max}
@school = @wrestler.school
end
# POST /wrestlers

View File

@@ -0,0 +1,2 @@
module ApiHelper
end

View File

@@ -1,62 +0,0 @@
module GeneratesTournamentMatches
def generateMatchups
self.curently_generating_matches = 1
self.save
resetSchoolScores
setSeedsAndRandomSeedingWrestlersWithoutSeeds
poolToBracket() if tournament_type == "Pool to bracket"
self.curently_generating_matches = nil
self.save
matches
end
if Rails.env.production?
handle_asynchronously :generateMatchups
end
def poolToBracket
destroyAllMatches
buildTournamentWeights
generateMatches
# This is not working for pool order and I cannot get tests working
movePoolSeedsToFinalPoolRound
end
def buildTournamentWeights
weights.order(:max).each do |weight|
Pool.new(weight).generatePools()
last_match = matches.where(weight: weight).order(round: :desc).limit(1).first
highest_round = last_match.round
PoolBracket.new(weight, highest_round).generateBracketMatches()
end
end
def generateMatches
moveFinalsMatchesToLastRound
assignBouts
assignLoserNames
assignFirstMatchesToMats
end
def moveFinalsMatchesToLastRound
finalsRound = self.totalRounds
finalsMatches = self.matches.select{|m| m.bracket_position == "1/2" || m.bracket_position == "3/4" || m.bracket_position == "5/6" || m.bracket_position == "7/8"}
finalsMatches. each do |m|
m.round = finalsRound
m.save
end
end
def setSeedsAndRandomSeedingWrestlersWithoutSeeds
weights.each do |w|
w.setSeeds
end
end
def movePoolSeedsToFinalPoolRound
self.weights.each do |w|
w.setOriginalSeedsToWrestleLastPoolRound
end
end
end

View File

@@ -7,6 +7,10 @@ class Match < ActiveRecord::Base
after_update do
after_update_actions
end
def after_update_actions
if self.finished == 1 && self.winner_id != nil
if self.w1 && self.w2
wrestler1.touch
@@ -28,9 +32,7 @@ class Match < ActiveRecord::Base
wrestler2.school.calcScore
end
end
if Rails.env.production?
handle_asynchronously :calcSchoolPoints
end
def mat_assigned
if self.mat
@@ -53,15 +55,11 @@ class Match < ActiveRecord::Base
def advance_wrestlers
if self.w1 && self.w2
@w1 = wrestler1
@w2 = wrestler2
@w1.advanceInBracket(self)
@w2.advanceInBracket(self)
AdvanceWrestler.new(wrestler1).advance
AdvanceWrestler.new(wrestler2).advance
end
end
if Rails.env.production?
handle_asynchronously :advance_wrestlers
end
def bracketScore
if self.finished != 1

View File

@@ -24,6 +24,9 @@ class School < ActiveRecord::Base
self.score = newScore
self.save
end
if Rails.env.production?
handle_asynchronously :calcScore
end
def totalWrestlerPoints
points = 0

View File

@@ -14,15 +14,11 @@ class Teampointadjust < ActiveRecord::Base
#Team score needs calculated
if self.wrestler_id != nil
#In case this affects pool order
if self.wrestler.lastFinishedMatch
self.wrestler.lastFinishedMatch.advance_wrestlers
end
AdvanceWrestler.new(self.wrestler).advance
self.wrestler.school.calcScore
elsif self.school_id != nil
self.school.calcScore
end
end
if Rails.env.production?
handle_asynchronously :advance_wrestlers_and_calc_team_score
end
end

View File

@@ -1,7 +1,5 @@
class Tournament < ActiveRecord::Base
include GeneratesLoserNames
include GeneratesTournamentMatches
belongs_to :user
has_many :schools, dependent: :destroy
has_many :weights, dependent: :destroy
@@ -24,10 +22,6 @@ class Tournament < ActiveRecord::Base
time
end
def resetSchoolScores
schools.update_all("score = 0.0")
end
def tournament_types
["Pool to bracket"]
end
@@ -50,19 +44,6 @@ class Tournament < ActiveRecord::Base
def matchesByRound(round)
matches.joins(:weight).where(round: round).order("weights.max")
end
def assignBouts
bout_counts = Hash.new(0)
matches.each do |m|
m.bout_number = m.round * 1000 + bout_counts[m.round]
bout_counts[m.round] += 1
m.save!
end
end
def assignFirstMatchesToMats
assignMats(mats)
end
def totalRounds
self.matches.sort_by{|m| m.round}.last.round

View File

@@ -14,7 +14,7 @@ class Weight < ActiveRecord::Base
end
before_save do
self.tournament.destroyAllMatches
# self.tournament.destroyAllMatches
end
def wrestlersForPool(pool)
@@ -46,22 +46,6 @@ class Weight < ActiveRecord::Base
wrestlersForPool(pool).sort_by{|w| [w.original_seed ? 0 : 1, w.original_seed || 0]}
end
def setOriginalSeedsToWrestleLastPoolRound
pool = 1
until pool > self.pools
wrestler1 = poolSeedOrder(pool).first
wrestler2 = poolSeedOrder(pool).second
match = wrestler1.poolMatches.sort_by{|m| m.round}.last
if match.w1 != wrestler2.id or match.w2 != wrestler2.id
if match.w1 == wrestler1.id
swapWrestlers(match.w2,wrestler2.id)
elsif match.w2 == wrestler1.id
swapWrestlers(match.w1,wrestler2.id)
end
end
pool += 1
end
end
def swapWrestlers(wrestler1_id,wrestler2_id)
SwapWrestlers.new.swapWrestlers(wrestler1_id,wrestler2_id)
@@ -180,38 +164,5 @@ class Weight < ActiveRecord::Base
def poolOrder(pool)
PoolOrder.new(wrestlersForPool(pool)).getPoolOrder
end
def randomSeeding
wrestlerWithSeeds = self.wrestlers.select{|w| w.original_seed != nil }.sort_by{|w| w.original_seed}
if wrestlerWithSeeds.size > 0
highestSeed = wrestlerWithSeeds.last.seed
seed = highestSeed + 1
else
seed = 1
end
wrestlersWithoutSeed = self.wrestlers.select{|w| w.original_seed == nil }
wrestlersWithoutSeed.shuffle.each do |w|
w.seed = seed
w.save
seed += 1
end
end
def setSeeds
resetAllSeeds
wrestlerWithSeeds = self.wrestlers.select{|w| w.original_seed != nil }
wrestlerWithSeeds.each do |w|
w.seed = w.original_seed
w.save
end
randomSeeding
end
def resetAllSeeds
self.wrestlers.each do |w|
w.seed = nil
w.save
end
end
end

View File

@@ -22,28 +22,19 @@ class Wrestler < ActiveRecord::Base
end
def totalTeamPoints
if self.extra
return 0
else
teamPointsEarned - totalDeductedPoints
end
CalculateWrestlerTeamScore.new(self).totalScore
end
def teamPointsEarned
points = 0.0
points = points + (poolWins.size * 2) + (championshipAdvancementWins.size * 2) + (consoAdvancementWins.size * 1) + (pinWins.size * 2) + (techWins.size * 1.5) + (majorWins.size * 1) + placementPoints
CalculateWrestlerTeamScore.new(self).earnedPoints
end
def placementPoints
PoolBracketPlacementPoints.new(self).calcPoints
CalculateWrestlerTeamScore.new(self).placementPoints
end
def totalDeductedPoints
points = 0
self.deductedPoints.each do |d|
points = points + d.points
end
points
CalculateWrestlerTeamScore.new(self).deductedPoints
end
def nextMatch
@@ -88,15 +79,15 @@ class Wrestler < ActiveRecord::Base
end
def resultByBout(bout)
@match = allMatches.select{|m| m.bout_number == bout and m.finished == 1}
if @match.size == 0
bout_match = allMatches.select{|m| m.bout_number == bout and m.finished == 1}
if bout_match.size == 0
return ""
end
if @match.first.winner_id == self.id
return "W #{@match.first.bracketScore}"
if bout_match.first.winner_id == self.id
return "W #{bout_match.first.bracketScore}"
end
if @match.first.winner_id != self.id
return "L #{@match.first.bracketScore}"
if bout_match.first.winner_id != self.id
return "L #{bout_match.first.bracketScore}"
end
end
@@ -113,26 +104,25 @@ class Wrestler < ActiveRecord::Base
end
def generatePoolNumber
@pool = self.weight.returnPoolNumber(self)
self.weight.returnPoolNumber(self)
end
def boutByRound(round)
@match = allMatches.select{|m| m.round == round}.first
if @match.blank?
round_match = allMatches.select{|m| m.round == round}.first
if round_match.blank?
return "BYE"
else
return @match.bout_number
return round_match.bout_number
end
end
def allMatches
@matches = matches.select{|m| m.w1 == self.id or m.w2 == self.id}
return @matches
return matches.select{|m| m.w1 == self.id or m.w2 == self.id}
end
def poolMatches
@poolMatches = allMatches.select{|m| m.bracket_position == "Pool"}
@poolMatches.select{|m| m.poolNumber == self.generatePoolNumber}
pool_matches = allMatches.select{|m| m.bracket_position == "Pool"}
pool_matches.select{|m| m.poolNumber == self.generatePoolNumber}
end
def championshipAdvancementWins
@@ -213,7 +203,4 @@ class Wrestler < ActiveRecord::Base
end
end
def advanceInBracket(match)
PoolAdvance.new(self,match).advanceWrestler
end
end

View File

@@ -0,0 +1,14 @@
class AdvanceWrestler
def initialize( wrestler )
@wrestler = wrestler
@tournament = @wrestler.tournament
end
def advance
PoolAdvance.new(@wrestler,@wrestler.lastMatch).advanceWrestler if @tournament.tournament_type == "Pool to bracket"
end
if Rails.env.production?
handle_asynchronously :advance
end
end

View File

@@ -109,21 +109,26 @@ class PoolOrder
end
def fastestPin
timeArray = []
wrestlersWithSamePoints.each do |w|
timeArray << w.fastestPin
wrestlersWithSamePointsWithPins = []
wrestlersWithSamePoints.each do |wr|
if wr.pinWins.size > 0
wrestlersWithSamePointsWithPins << wr
end
end
fastest = timeArray.max
wrestlersWithFastestPin = wrestlersWithSamePoints.select{|w| w.fastestPin == fastest}
addPointsToWrestlersAhead(wrestlersWithFastestPin.first)
wrestlersWithFastestPin.each do |wr|
addPoints(wr)
end
secondFastest = timeArray.sort[-2]
wrestlersWithSecondFastestPin = wrestlersWithSamePoints.select{|w| w.fastestPin == secondFastest}
addPointsToWrestlersAhead(wrestlersWithSecondFastestPin.first)
wrestlersWithSecondFastestPin.each do |wr|
addPoints(wr)
if wrestlersWithSamePointsWithPins.size > 0
fastest = wrestlersWithSamePointsWithPins.sort_by{|w| w.fastestPin.pinTime}.first.fastestPin
secondFastest = wrestlersWithSamePointsWithPins.sort_by{|w| w.fastestPin.pinTime}.second.fastestPin
wrestlersWithFastestPin = wrestlersWithSamePointsWithPins.select{|w| w.fastestPin.pinTime == fastest.pinTime}
addPointsToWrestlersAhead(wrestlersWithFastestPin.first)
wrestlersWithFastestPin.each do |wr|
addPoints(wr)
end
wrestlersWithSecondFastestPin = wrestlersWithSamePointsWithPins.select{|w| w.fastestPin.pinTime == secondFastest.pinTime}
addPointsToWrestlersAhead(wrestlersWithSecondFastestPin.first)
wrestlersWithSecondFastestPin.each do |wr|
addPoints(wr)
end
end
end

View File

@@ -0,0 +1,83 @@
class GenerateTournamentMatches
def initialize( tournament )
@tournament = tournament
end
def generateWeight(weight)
WipeTournamentMatches.new(@tournament).wipeWeightMatches(weight)
@tournament.curently_generating_matches = 1
@tournament.save
unAssignBouts
PoolToBracketMatchGeneration.new(@tournament).generatePoolToBracketMatchesWeight(weight) if @tournament.tournament_type == "Pool to bracket"
postMatchCreationActions
PoolToBracketGenerateLoserNames.new(@tournament).assignLoserNamesWeight(weight) if @tournament.tournament_type == "Pool to bracket"
end
if Rails.env.production?
handle_asynchronously :generateWeight
end
def generate
standardStartingActions
PoolToBracketMatchGeneration.new(@tournament).generatePoolToBracketMatches if @tournament.tournament_type == "Pool to bracket"
postMatchCreationActions
PoolToBracketMatchGeneration.new(@tournament).assignLoserNames if @tournament.tournament_type == "Pool to bracket"
end
if Rails.env.production?
handle_asynchronously :generate
end
def standardStartingActions
@tournament.curently_generating_matches = 1
@tournament.save
WipeTournamentMatches.new(@tournament).setUpMatchGeneration
TournamentSeeding.new(@tournament).setSeeds
end
def postMatchCreationActions
moveFinalsMatchesToLastRound
assignBouts
assignFirstMatchesToMats
@tournament.curently_generating_matches = nil
@tournament.save
end
def assignBouts
bout_counts = Hash.new(0)
@tournament.matches.each do |m|
m.bout_number = m.round * 1000 + bout_counts[m.round]
bout_counts[m.round] += 1
m.save!
end
end
def moveFinalsMatchesToLastRound
finalsRound = @tournament.totalRounds
finalsMatches = @tournament.matches.select{|m| m.bracket_position == "1/2" || m.bracket_position == "3/4" || m.bracket_position == "5/6" || m.bracket_position == "7/8"}
finalsMatches. each do |m|
m.round = finalsRound
m.save
end
end
def assignFirstMatchesToMats
matsToAssign = @tournament.mats
if matsToAssign.count > 0
until matsToAssign.sort_by{|m| m.id}.last.matches.count == 4
matsToAssign.sort_by{|m| m.id}.each do |m|
m.assignNextMatch
end
end
end
end
def unAssignBouts
bout_counts = Hash.new(0)
@tournament.matches.each do |m|
m.bout_number = nil
m.save!
end
end
end

View File

@@ -1,4 +1,4 @@
class PoolBracket
class PoolBracketGeneration
def initialize(weight, highest_round)
@weight = weight

View File

@@ -1,4 +1,4 @@
class Pool
class PoolGeneration
def initialize(weight)
@weight = weight
@tournament = @weight.tournament
@@ -6,17 +6,14 @@ class Pool
end
def generatePools
matches = []
pools = @weight.pools
while @pool <= pools
matches += roundRobin()
roundRobin
@pool += 1
end
return matches
end
def roundRobin
matches = []
wrestlers = @weight.wrestlersForPool(@pool)
poolMatches = RoundRobinTournament.schedule(wrestlers).reverse
poolMatches.each_with_index do |b, index|
@@ -24,16 +21,14 @@ class Pool
bouts = b.map
bouts.each do |bout|
if bout[0] != nil and bout[1] != nil
match = @tournament.matches.create(
@tournament.matches.create(
w1: bout[0].id,
w2: bout[1].id,
weight_id: @weight.id,
bracket_position: "Pool",
round: round)
matches << match
end
end
end
matches
end
end

View File

@@ -1,8 +1,24 @@
module GeneratesLoserNames
def assignLoserNames
class PoolToBracketGenerateLoserNames
def initialize( tournament )
@tournament = tournament
end
def assignLoserNamesWeight(weight)
matches_by_weight = @tournament.matches.where(weight_id: weight.id)
if weight.pool_bracket_type == "twoPoolsToSemi"
twoPoolsToSemiLoser(matches_by_weight)
elsif weight.pool_bracket_type == "fourPoolsToQuarter"
fourPoolsToQuarterLoser(matches_by_weight)
elsif weight.pool_bracket_type == "fourPoolsToSemi"
fourPoolsToSemiLoser(matches_by_weight)
end
saveMatches(matches_by_weight)
end
def assignLoserNames
matches_by_weight = nil
weights.each do |w|
matches_by_weight = matches.where(weight_id: w.id)
@tournament.weights.each do |w|
matches_by_weight = @tournament.matches.where(weight_id: w.id)
if w.pool_bracket_type == "twoPoolsToSemi"
twoPoolsToSemiLoser(matches_by_weight)
elsif w.pool_bracket_type == "fourPoolsToQuarter"
@@ -12,7 +28,7 @@ module GeneratesLoserNames
end
saveMatches(matches_by_weight)
end
end
end
def twoPoolsToSemiLoser(matches_by_weight)
match1 = matches_by_weight.select{|m| m.loser1_name == "Winner Pool 1"}.first
@@ -59,5 +75,6 @@ module GeneratesLoserNames
matches.each do |m|
m.save!
end
end
end
end
end

View File

@@ -0,0 +1,52 @@
class PoolToBracketMatchGeneration
def initialize( tournament )
@tournament = tournament
end
def generatePoolToBracketMatchesWeight(weight)
PoolGeneration.new(weight).generatePools()
last_match = @tournament.matches.where(weight: weight).order(round: :desc).limit(1).first
highest_round = last_match.round
PoolBracketGeneration.new(weight, highest_round).generateBracketMatches()
setOriginalSeedsToWrestleLastPoolRound(weight)
end
def generatePoolToBracketMatches
@tournament.weights.order(:max).each do |weight|
PoolGeneration.new(weight).generatePools()
last_match = @tournament.matches.where(weight: weight).order(round: :desc).limit(1).first
highest_round = last_match.round
PoolBracketGeneration.new(weight, highest_round).generateBracketMatches()
end
movePoolSeedsToFinalPoolRound
end
def movePoolSeedsToFinalPoolRound
@tournament.weights.each do |w|
setOriginalSeedsToWrestleLastPoolRound(w)
end
end
def setOriginalSeedsToWrestleLastPoolRound(weight)
pool = 1
until pool > weight.pools
wrestler1 = weight.poolSeedOrder(pool).first
wrestler2 = weight.poolSeedOrder(pool).second
match = wrestler1.poolMatches.sort_by{|m| m.round}.last
if match.w1 != wrestler2.id or match.w2 != wrestler2.id
if match.w1 == wrestler1.id
SwapWrestlers.new.swapWrestlers(match.w2,wrestler2.id)
elsif match.w2 == wrestler1.id
SwapWrestlers.new.swapWrestlers(match.w1,wrestler2.id)
end
end
pool += 1
end
end
def assignLoserNames
PoolToBracketGenerateLoserNames.new(@tournament).assignLoserNames
end
end

View File

@@ -0,0 +1,44 @@
class TournamentSeeding
def initialize( tournament )
@tournament = tournament
end
def setSeeds
@tournament.weights.each do |w|
resetAllSeeds(w)
setOriginalSeeds(w)
randomSeeding(w)
end
end
def randomSeeding(weight)
wrestlerWithSeeds = weight.wrestlers.select{|w| w.original_seed != nil }.sort_by{|w| w.original_seed}
if wrestlerWithSeeds.size > 0
highestSeed = wrestlerWithSeeds.last.seed
seed = highestSeed + 1
else
seed = 1
end
wrestlersWithoutSeed = weight.wrestlers.select{|w| w.original_seed == nil }
wrestlersWithoutSeed.shuffle.each do |w|
w.seed = seed
w.save
seed += 1
end
end
def setOriginalSeeds(weight)
wrestlerWithSeeds = weight.wrestlers.select{|w| w.original_seed != nil }
wrestlerWithSeeds.each do |w|
w.seed = w.original_seed
w.save
end
end
def resetAllSeeds(weight)
weight.wrestlers.each do |w|
w.seed = nil
w.save
end
end
end

View File

@@ -0,0 +1,23 @@
class WipeTournamentMatches
def initialize( tournament )
@tournament = tournament
end
def setUpMatchGeneration
wipeMatches
resetSchoolScores
end
def wipeWeightMatches(weight)
weight.matches.destroy_all
end
def wipeMatches
@tournament.matches.destroy_all
end
def resetSchoolScores
@tournament.schools.update_all("score = 0.0")
end
end

View File

@@ -0,0 +1,47 @@
class CalculateWrestlerTeamScore
def initialize( wrestler )
@wrestler = wrestler
@tournament = @wrestler.tournament
end
def totalScore
if @wrestler.extra
return 0
else
earnedPoints - deductedPoints
end
end
def earnedPoints
return poolPoints + bracketPoints + placementPoints + bonusWinPoints
end
def deductedPoints
points = 0
@wrestler.deductedPoints.each do |d|
points = points + d.points
end
points
end
def placementPoints
PoolBracketPlacementPoints.new(@wrestler).calcPoints if @tournament.tournament_type == "Pool to bracket"
end
def bracketPoints
(@wrestler.championshipAdvancementWins.size * 2) + (@wrestler.consoAdvancementWins.size * 1)
end
def poolPoints
if @tournament.tournament_type == "Pool to bracket"
(@wrestler.poolWins.size * 2)
else
0
end
end
def bonusWinPoints
(@wrestler.pinWins.size * 2) + (@wrestler.techWins.size * 1.5) + (@wrestler.majorWins.size * 1)
end
end

View File

@@ -0,0 +1,3 @@
json.array!(@tournaments) do |tournament|
json.extract! tournament, :id, :name, :address, :director, :director_email, :date
end

View File

@@ -0,0 +1,2 @@
<%= stylesheet_link_tag "lineman/app" %>
<%= javascript_include_tag "lineman/app" %>

View File

@@ -0,0 +1,55 @@
json.cache! ["api_tournament", @tournament] do
json.content(@tournament)
json.(@tournament, :id, :name, :address, :director, :director_email, :tournament_type, :created_at, :updated_at, :user_id)
json.schools @tournament.schools do |school|
json.id school.id
json.name school.name
json.score school.score
end
json.weights @tournament.weights do |weight|
json.id weight.id
json.max weight.max
json.bracket_size weight.bracket_size
json.wrestlers weight.wrestlers do |wrestler|
json.id wrestler.id
json.name wrestler.name
json.school wrestler.school.name
json.original_seed wrestler.original_seed
json.criteria wrestler.criteria
json.extra wrestler.extra
json.seasonWinPercentage wrestler.seasonWinPercentage
json.season_win wrestler.season_win
json.season_loss wrestler.season_loss
end
end
json.mats @tournament.mats do |mat|
json.name mat.name
json.unfinishedMatches mat.unfinishedMatches do |match|
json.bout_number match.bout_number
json.w1_name match.w1_name
json.w2_name match.w2_name
end
end
json.unassignedMatches @tournament.matches.select{|m| m.mat_id == nil}.sort_by{|m| m.bout_number}[0...9] do |match|
json.bout_number match.bout_number
json.w1_name match.w1_name
json.w2_name match.w2_name
json.weightClass match.weight.max
json.round match.round
end
json.matches @tournament.matches do |match|
json.bout_number match.bout_number
json.w1_name match.w1_name
json.w2_name match.w2_name
json.weightClass match.weight.max
json.round match.round
json.w1 match.w1
json.w2 match.w2
end
end

View File

@@ -0,0 +1,3 @@
json.array!(@tournaments) do |tournament|
json.extract! tournament, :id, :name, :address, :director, :director_email, :date
end

View File

@@ -9,7 +9,7 @@
<script src="https://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.map"></script>
<!--Mobile and tablet detection-->
<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>

View File

@@ -0,0 +1,3 @@
<%= link_to "Back to #{@weight.tournament.name}", "/tournaments/#{@weight.tournament.id}", :class=>"btn btn-default" %>
<br><br>
<%= @weight.max %> lbs Matches are being generated. This can take anywhere from 1-5 minutes to finish. It is recommended to delete all delegated school permissions to prevent lineup changes after the tournament has started.

View File

@@ -4,6 +4,9 @@
<%= link_to "Back to #{@tournament.name}", "/tournaments/#{@tournament.id}", :class=>"btn btn-default" %>
<% if can? :manage, @tournament %>
| <%= link_to "Edit #{@weight.max} Weight Class", edit_weight_path(@weight), :class=>"btn btn-primary" %>
| <%= form_for(@weight, url: regen_weight_path(@weight.id), :method => "post") do |f| %>
<%= submit_tag "Regenerate Weight Class Matches", :class=>"btn"%>
<% end %>
<% end %>
<br>

View File

@@ -17,14 +17,12 @@
<%= f.text_field :name %>
</div>
<% if can? :manage, @wrestler.tournament %>
<% if @tournament %>
<%= f.hidden_field :school_id, :value => @school.id %>
<% else %>
<div class="field">
<%= f.label 'School' %><br>
<%= f.collection_select :school_id, @school.tournament.schools, :id, :name %>
</div>
<% end %>
<% else %>
<%= f.hidden_field :school_id, :value => @school.id %>
<% end %>
<div class="field">
<%= f.label 'Weight Class' %><br>

View File

@@ -29,7 +29,15 @@ module Wrestling
config.active_job.queue_adapter = :delayed_job
config.rails_lineman.lineman_project_location = "frontend"
config.to_prepare do
DeviseController.respond_to :html, :json
end
config.autoload_paths += %W(#{config.root}/app/services/tournament_services)
config.autoload_paths += %W(#{config.root}/app/services/wrestler_services)
config.autoload_paths += %W(#{config.root}/app/services/bracket_advancement)
end

View File

@@ -110,4 +110,7 @@ Wrestling::Application.configure do
config.action_mailer.perform_deliveries = true
#Devise needs origin of email
Rails.application.routes.default_url_options[:host] = 'https://wrestlingdev.com'
#For lineman creating assets
config.serve_static_files = true
end

View File

@@ -51,6 +51,15 @@ Wrestling::Application.routes.draw do
get 'tournaments/:id/error' => 'tournaments#error'
post "/tournaments/:id/swap" => "tournaments#swap", :as => :swap_wrestlers
post 'weights/:id/re_gen' => 'weights#re_gen', :as => :regen_weight
#API
get "/api/tournaments" => "api#tournaments"
get "/api/tournaments/user" => "api#currentUserTournaments"
get "/api/tournaments/:tournament" => "api#tournament"
get "/api/index" => "api#index"
post "/api/tournaments/new" => "newTournament"
# Example of regular route:
# get 'products/:id' => 'catalog#view'

View File

@@ -1,5 +1,6 @@
cd ..
bash rails-prod.sh wrestlingdev
docker build -t wrestlingdev -f rails-prod-Dockerfile .
cd deploy
docker-compose -f docker-compose-test.yml kill
docker-compose -f docker-compose-test.yml up -d
echo Make sure your local mysql database has a wrestlingtourney db

View File

@@ -23,3 +23,10 @@ worker:
restart: always
env_file:
- ./prod.env
command: bundle exec rake jobs:work RAILS_ENV=production
memcached:
extends:
file: docker-compose-common.yml
service: memcached
restart: always

View File

@@ -10,10 +10,14 @@ app:
- WRESTLINGDEV_DB_PORT=3306
- WRESTLINGDEV_DEVISE_SECRET_KEY=2f29d49db6704377ba263f7cb9db085b386bcb301c0cd501126a674686ab1a109754071165b08cd72af03cec4642a4dd04361c994462254dd5d85e9594e8b9aa
- WRESTLINGDEV_SECRET_KEY_BASE=077cdbef5c2ccf22543fb17a67339f234306b7fa2e1e4463d851c444c10a5611829a2290b253da78339427f131571fac9a42c83d960b2d25ecc10a4a0a7ce1a2
- MEMCACHIER_SERVERS=memcached:11211
- MEMCACHIER_USERNAME=
- MEMCACHIER_PASSWORD=
links:
- db
- memcached
restart: always
db:
extends:
file: docker-compose-common.yml
@@ -21,6 +25,7 @@ db:
environment:
- MYSQL_ROOT_PASSWORD=password
restart: always
worker:
extends:
file: docker-compose-common.yml
@@ -33,7 +38,18 @@ worker:
- WRESTLINGDEV_DB_PORT=3306
- WRESTLINGDEV_DEVISE_SECRET_KEY=2f29d49db6704377ba263f7cb9db085b386bcb301c0cd501126a674686ab1a109754071165b08cd72af03cec4642a4dd04361c994462254dd5d85e9594e8b9aa
- WRESTLINGDEV_SECRET_KEY_BASE=077cdbef5c2ccf22543fb17a67339f234306b7fa2e1e4463d851c444c10a5611829a2290b253da78339427f131571fac9a42c83d960b2d25ecc10a4a0a7ce1a2
- MEMCACHIER_SERVERS=memcached:11211
- MEMCACHIER_USERNAME=
- MEMCACHIER_PASSWORD=
links:
- db
- memcached
restart: always
command: bundle exec rake jobs:work RAILS_ENV=production
memcached:
extends:
file: docker-compose-common.yml
service: memcached
restart: always

9
frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.DS_Store
#ignore node_modules, as the node project is not "deployed" per se: http://www.mikealrogers.com/posts/nodemodules-in-git.html
/node_modules
/dist
/generated
.sass-cache

9
frontend/.npmignore Normal file
View File

@@ -0,0 +1,9 @@
.DS_Store
#ignore node_modules, as the node project is not "deployed" per se: http://www.mikealrogers.com/posts/nodemodules-in-git.html
/node_modules
/dist
/generated
.sass-cache

4
frontend/.travis.yml Normal file
View File

@@ -0,0 +1,4 @@
language: node_js
node_js:
- 0.10
script: "lineman spec-ci"

4
frontend/Gruntfile.js Normal file
View File

@@ -0,0 +1,4 @@
/*global module:false*/
module.exports = function(grunt) {
require('./config/lineman').config.grunt.run(grunt);
};

1
frontend/Procfile Normal file
View File

@@ -0,0 +1 @@
web: npm run production

1
frontend/README.md Normal file
View File

@@ -0,0 +1 @@
# My Lineman Application

View File

@@ -0,0 +1,4 @@
.hello {
background-color: #efefef;
border: 1px solid #dedede;
}

0
frontend/app/img/.keep Normal file
View File

0
frontend/app/js/.keep Normal file
View File

11
frontend/app/js/app.js Normal file
View File

@@ -0,0 +1,11 @@
var app = angular.module("wrestlingdev", ["ngRoute","Devise"]).run(function($rootScope) {
// adds some basic utilities to the $rootScope for debugging purposes
$rootScope.log = function(thing) {
console.log(thing);
};
$rootScope.alert = function(thing) {
alert(thing);
};
});

View File

@@ -0,0 +1,51 @@
'use strict';
app.controller("loginController", function($scope, $routeParams, Auth, $rootScope) {
$scope.credentials = {
email: '',
password: ''
};
var config = {
headers: {
'X-HTTP-Method-Override': 'POST'
}
};
$scope.login = function(){
Auth.login($scope.credentials, config).then(function(user) {
console.log(user); // => {id: 1, ect: '...'}
$rootScope.user = user;
$rootScope.alertClass = "alert alert-success";
$rootScope.alertMessage = "Logged in successfully";
}, function(error) {
console.log(error);
$rootScope.alertClass = "alert alert-danger";
$rootScope.alertMessage = "Username and/or password is incorrect";
});
};
$scope.logout = function(){
Auth.logout(config).then(function(oldUser) {
// alert(oldUser.name + "you're signed out now.");
$rootScope.user = null;
$rootScope.alertClass = "alert alert-success";
$rootScope.alertMessage = "Logged out successfully";
}, function(error) {
// An error occurred logging out.
$rootScope.alertClass = "alert alert-danger";
$rootScope.alertMessage = "There was an error logging out";
});
};
Auth.currentUser().then(function(user) {
// User was logged in, or Devise returned
// previously authenticated session.
$rootScope.user = user;
}, function(error) {
// unauthenticated error
$rootScope.user = null;
});
});

View File

@@ -0,0 +1,11 @@
'use strict';
app.controller("myTournamentsController", function($scope, tournamentsService, $rootScope) {
tournamentsService.getMyTournaments().then(function(data) {
//this will execute when the
//AJAX call completes.
$scope.allTournaments = data;
});
});

View File

@@ -0,0 +1,86 @@
'use strict';
app.controller("tournamentController", function($scope, tournamentsService, $routeParams, Wrestler, Auth, $rootScope) {
$scope.message = "Test message in scope.";
// $scope.tournamentData = "test";
tournamentsService.tournamentDetails($routeParams.id).then(function(data) {
//this will execute when the
//AJAX call completes.
$scope.tournament = data;
});
$scope.refreshTournamentData = function(){
tournamentsService.tournamentDetails($routeParams.id).then(function(data) {
//this will execute when the
//AJAX call completes.
$scope.tournament = data;
});
};
// refresh tournament data every 10 seconds
// setInterval(function(){
// tournamentsService.tournamentDetails($routeParams.id).then(function(data) {
// //this will execute when the
// //AJAX call completes.
// $scope.tournament = data;
// });
// }, 10000);
$scope.wrestler = Wrestler;
$scope.showSchools = false;
$scope.toggleSchools = function(){
$scope.showSchools = !$scope.showSchools;
};
$scope.showWeightSeeds = false;
$scope.toggleWeightSeeds = function(){
$scope.showWeightSeeds = !$scope.showWeightSeeds;
};
$scope.showBoutBoard = false;
$scope.toggleBoutBoard = function(){
$scope.showBoutBoard = !$scope.showBoutBoard;
};
$scope.isTournamentOwner = function(tournamentId,userId){
if(userId == tournamentId){
return true;
} else {
return false;
}
};
$scope.newSchool = null;
$scope.saveNewSchool = function(){
$scope.newSchool.tournament_id = $scope.tournament.id;
tournamentsService.saveNewSchool($scope.newSchool).then(function(data) {
$scope.tournament.schools.push(data);
});
$scope.newSchool = null;
$('#NewSchool').modal('hide');
};
$scope.deleteSchool = function(school){
if (confirm('Are you sure you want to delete ' + school.name + '?')) {
tournamentsService.deleteSchool(school).then(function(data) {
$scope.tournament.schools.splice( $scope.tournament.schools.indexOf(school), 1 );
});
}
};
$scope.updateSchool = function(school){
tournamentsService.updateSchool(school);
$('#EditSchool' + school.id).modal('hide');
};
});

View File

@@ -0,0 +1,19 @@
'use strict';
app.controller("tournamentsController", function($scope, tournamentsService) {
tournamentsService.getAllTournaments().then(function(data) {
//this will execute when the
//AJAX call completes.
$scope.allTournaments = data;
});
$scope.searchTournaments = function (){
tournamentsService.searchTournaments($scope.searchTerms).then(function(data) {
//this will execute when the
//AJAX call completes.
$scope.allTournaments = data;
});
};
});

View File

@@ -0,0 +1,24 @@
(function(){
app.directive('usSpinner', ['$http', '$rootScope' ,function ($http, $rootScope){
return {
link: function (scope, elm, attrs)
{
$rootScope.spinnerActive = false;
scope.isLoading = function () {
return $http.pendingRequests.length > 0;
};
scope.$watch(scope.isLoading, function (loading)
{
$rootScope.spinnerActive = loading;
if(loading){
elm.removeClass('ng-hide');
}else{
elm.addClass('ng-hide');
}
});
}
};
}]);
}).call(this);

View File

@@ -0,0 +1,18 @@
'use strict';
app.factory('Wrestler', function Wrestler(){
var vm = this;
vm.matches = function(wrestler,matches){
console.log(matches);
return _.filter(matches, function(match){
return match.w1 == wrestler.id || match.w2 == wrestler.id;
});
};
return vm;
});

49
frontend/app/js/routes.js Normal file
View File

@@ -0,0 +1,49 @@
// $routeProvider.when('/list-of-books', {
// templateUrl: 'angular/books.html',
// controller: 'BooksController'
// // uncomment if you want to see an example of a route that resolves a request prior to rendering
// // resolve: {
// // books : function(BookService) {
// // return BookService.get();
// // }
// // }
// });
app.config(['$routeProvider', '$locationProvider', function($routeProvider,$locationProvider) {
$routeProvider.when('/', {
templateUrl: 'home.html',
});
$routeProvider.when('/tournaments', {
templateUrl: 'tournaments-search.html',
controller: 'tournamentsController'
});
$routeProvider.when('/tournaments/user', {
templateUrl: 'my-tournaments.html',
controller: 'myTournamentsController'
});
$routeProvider.when('/tournaments/:id', {
templateUrl: 'tournaments-show.html',
controller: 'tournamentController'
});
$routeProvider.when('/about', {
templateUrl: 'about.html',
});
$routeProvider.when('/tutorials', {
templateUrl: 'tutorials.html',
});
$routeProvider.otherwise({redirectTo: '/'});
//this give me normal routes instead of /#/
// $locationProvider.html5Mode(true);
}]);

View File

@@ -0,0 +1,101 @@
app.factory('tournamentsService', tournamentsService);
function tournamentsService($http,$rootScope){
var service = {};
service.getMyTournaments = function(user){
return $http({
url: '/api/tournaments/user/',
method: "GET"
}).then(successResponse, errorCallback);
};
service.getAllTournaments = function(){
return $http({
url: '/api/tournaments/',
method: "GET"
}).then(successResponse, errorCallback);
};
service.searchTournaments = function(search){
return $http({
method: 'GET',
url: '/api/tournaments/',
params: {
search: search
}
}).then(successResponse, errorCallback);
};
service.tournamentDetails = function(tournamentId){
return $http({
url: '/api/tournaments/' + tournamentId,
method: "GET"
}).then(successResponse, errorCallback);
};
service.saveNewSchool = function(newSchool){
return $http({
url: '/schools.json',
method: "POST",
data: {
school: {
'name': newSchool.name,
'tournament_id': newSchool.tournament_id
}
},
headers: {
"Content-Type": "application/json"
}
}).then(successResponse, errorCallback);
};
service.deleteSchool = function(school){
return $http({
url: '/schools/' + school.id + '/',
method: "DELETE"
}).then(successResponse, errorCallback);
};
service.updateSchool = function(schoolToEdit){
return $http({
url: '/schools/' + schoolToEdit.id,
method: "PATCH",
data: {
school: {
'name': schoolToEdit.name,
'tournament_id': schoolToEdit.tournament_id
}
},
headers: {
"Content-Type": "application/json"
}
}).then(successResponse, errorCallback);
};
function successResponse(response){
// console.log("success log below");
// console.log(response);
if(response.config.method == "POST" || response.config.method == "DELETE" || response.config.method == "PATCH"){
$rootScope.alertClass = "alert alert-success";
$rootScope.alertMessage = response.statusText;
}
return response.data;
}
function errorCallback(err){
// console.log("error log below");
// console.log(err);
if(err.status > 0){
$rootScope.alertClass = "alert alert-danger";
$rootScope.alertMessage = err.statusText;
}
return err;
}
return service;
}

View File

@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html ng-app="wrestlingdev">
<head>
<base href="/#/">
<title>WrestlingDev</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
</head>
<body style="padding-top: 70px;">
<div class="container">
<div class="navbar-roof"></div>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/#/">WrestlingDev</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right navbar-custom-link">
<li><a href="/#/tournaments">Browse Tournaments</a></li>
<li><a href="/#/about">About</a></li>
<li><a href="/#/tutorials">Tutorials</a></li>
<li class="dropdown" ng-controller="loginController">
<a ng-if="user == null" class="dropdown-toggle" data-toggle="dropdown">Login<span class="caret"></a>
<div ng-if="user == null" class="dropdown-menu" style="padding:17px;">
<form class="form" id="formLogin">
<div class="form-group">
<input name="username" class="form-control" id="username" type="text" placeholder="Email" ng-model="credentials.email">
<input name="password" class="form-control" id="password" type="password" placeholder="Password" ng-model="credentials.password"><br>
<button type="button" id="btnLogin" class="btn btn-primary" ng-click="login()">Login</button>
</div>
</form>
</div>
<a ng-if="user != null" class="dropdown-toggle" data-toggle="dropdown">{{user.email}}<span class="caret"></a>
<ul ng-if="user != null" class="dropdown-menu" style="list-style-type: none;">
<li><a href="/#/tournaments/user">My Tournaments and schools</a></li>
<li><a ng-click="logout()">Logout</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div id="page-content">
<div class="row no-margin">
<div ng-if="alertMessage != null" ng-class="alertClass">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{alertMessage}}
</div>
<div class="col-md-2">
<!--left sidebar-->
</div>
<div class="col-md-8" style="padding-left: 2%;">
<div id="view" ng-view></div>
</div>
<div class="col-md-2" >
<!--right sidebar-->
</div>
</div>
</div>
<!--footer-->
</div>
</body>
<!-- Latest compiled and minified JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-route.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<!--Mobile and tablet detection-->
<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</html>

View File

@@ -0,0 +1,46 @@
<h3>About WrestlingDev</h3>
<br>
<p>WrestlingDev was created to help bring wrestling into the 21st century for <strong>free</strong>. This site is <a href="https://github.com/jcwimer/wrestlingApp">open source</a> and is supported by the ads on the sidebar.</p>
<br>
<h4>Features</h4>
<br>
<p>At this moment in time, WrestlingDev supports a pool to bracket type tournament for up to 16 teams. The bracket format follows OHSAA's 5 match per day rule. WrestlingDev will automatically generate brackets, generate bout numbers, generate and update a bout board, track team points, and update brackets.</p>
<p>For pool to bracket tournaments, pool tie breakers are the following:</p>
<ul>
<li>Least team points deducted</li>
<li>Head to head</li>
<li>Most team points scored</li>
<li>Most wins by fall, default, dq</li>
<li>Most wins by tech fall</li>
<li>Most wins by major</li>
<li>Most points scored in decisions</li>
<li>Quickest pin</li>
<li>Coin flip</li>
</ul>
<p>If three wrestlers are tied, they will be put through this sequence until two wrestlers are left. Once two wrestlers are left, the pool runner up will be decided by head to head.</p>
<p>For pool to bracket tournaments, team points will be calculated as follows:</p>
<ul>
<li>Pool win: 2pt</li>
<li>Win in championship bracket: 2pt</li>
<li>Win in consolation bracket: 1pt</li>
<li>Win by major: 1pt extra</li>
<li>Win by tech fall: 1.5pt extra</li>
<li>Win by fall, default, dq: 2pt extra</li>
<li>1st place: 16pt</li>
<li>2nd place: 12pt</li>
<li>3rd place: 10pt</li>
<li>4th place: 9pt</li>
<li>5th place: 7pt</li>
<li>6th place: 6pt</li>
<li>7th place: 4pt</li>
<li>8th place: 3pt</li>
</ul>
<p>Finals matches will only recieve extra placement points for placing higher and bonus points for pin, tech, major, etc. Please note, only brackets with four pools place up to 8. Brackets with 1 or 2 pools only place top 4.</p>
<br>
<h4>Future Plans</h4>
<br>
<p>Future development plans to support normal double elimination brackets are underway and are planned to be finished in time for the 2016-2017 wrestling season.</p>
<br>
<h4>Contact</h4>
<br>
<p>Suggestions, criticism, and kind words are welcomed. Please contact us.</p>

View File

@@ -0,0 +1,10 @@
<div class="center hero-unit" >
<h1>Welcome to WrestlingDev</h1>
<br>
<p>This website was created to help wrestling coaches run their tournaments. It is 2015, why are we still running bout sheets to tables and why are we still using resources to push cards on a bout board? This website was created as a <strong>free</strong> way for coaches to run a tournament smoothly with as few workers as possible.</p>
<br>
<p>If you would like to run a tournament, please click log in and then click sign up.</p>
<br>
<a href='/#/tournaments' class="btn btn-large btn-primary">Browse Tournaments</a>
<p></p>
</div>

View File

@@ -0,0 +1,17 @@
<h3>Tutorials</h3>
<br>
<p>Unfortunately, I do not have tutorials available at this moment in time. If you would like to learn how to use this software, please email me at jacob.wimer@gmail.com and I will gladly provide an overview of how to use this software. I've done my best to make the software intuitive and easy to use.</p>
<br>
<h4>Planning on using this software?</h4>
<br>
<p>Here is a list of features available:</p>
<br>
<ul>
<li>Pool to bracket type bracket generation for up to 16 man brackets</li>
<li>Delegate control to coaches for lineup entry</li>
<li>Automatically updated bout board</li>
<li>Automatically updated brackets</li>
<li>Automatically updated team scores</li>
<li>Delegate director privileges to multiple people for tournament administration</li>
<li>Matches can be scored at the tables and submitted via computer or bout sheets can be brought to the head table and entered there</li>
</ul>

View File

@@ -0,0 +1,17 @@
<h2>My Tournaments</h2>
<br>
<table class="table">
<thead class="font-spot-color">
<tr>
<th>Name</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tournament in allTournaments">
<td><a ng-href="/#/tournaments/{{tournament.id}}">{{ tournament.name }}</a></td>
<td>{{ tournament.date }}</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,25 @@
<h2>Upcoming Tournaments</h2>
<br>
<form ng-submit="searchTournaments()">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search by name or date YYYY-MM-DD" ng-model="searchTerms">
<span class="input-group-btn">
<button class="btn btn-default" type="submit" id="submit">Search</button>
</span>
</div>
</form>
<br>
<table class="table">
<thead class="font-spot-color">
<tr>
<th>Name</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tournament in allTournaments">
<td><a ng-href="/#/tournaments/{{tournament.id}}">{{ tournament.name }}</a></td>
<td>{{ tournament.date }}</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,222 @@
<a href="/#/tournaments" class="btn btn-default">Back to browse tournaments</a>
<h1>
{{ tournament.name }}
</h1>
<p>
<strong>Address:</strong>
{{ tournament.address }}
</p>
<p>
<strong>Director:</strong>
{{ tournament.director }}
</p>
<p>
<strong>Director email:</strong>
{{ tournament.director_email }}
</p>
<p>
<strong>Tournament Type:</strong>
{{ tournament.tournament_type }}
</p>
<br>
<div class="panel panel-default">
<a class="panel-heading" ng-click="toggleSchools()" style="display: block;">
<h3 class="panel-title">School Lineups and Team Scores<span class="pull-left clickable"><i ng-if="showSchools == false" class="glyphicon glyphicon-chevron-down"></i>
<i ng-if="showSchools == true" class="glyphicon glyphicon-chevron-up"></i></span></h3>
</a>
<div id="Schools" ng-if="showSchools == true">
<div class="panel-body">
<button ng-if="isTournamentOwner(user.id,tournament.user_id)" class="btn btn-success btn-sm" data-toggle="modal" data-target="#NewSchool">Create New School</button>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Score</th>
<th ng-if="isTournamentOwner(user.id,tournament.user_id)">Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="school in tournament.schools | orderBy : 'score'">
<td>{{ school.name }}</td>
<td>{{ school.score }}</td>
<td ng-if="isTournamentOwner(user.id,tournament.user_id)">
<button class="btn btn-sm" data-toggle="modal" data-target="#EditSchool{{school.id}}">Edit</button>
<button ng-click="deleteSchool(school)"class="btn btn-danger btn-sm">Destroy</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="panel panel-default">
<a class="panel-heading" ng-click="toggleWeightSeeds()" style="display: block;">
<h3 class="panel-title">Weights and Seeds<span class="pull-left clickable"><i ng-if="showWeightSeeds == false" class="glyphicon glyphicon-chevron-down"></i>
<i ng-if="showWeightSeeds == true" class="glyphicon glyphicon-chevron-up"></i></span></h3>
</a>
<div id="Weights" ng-if="showWeightSeeds == true">
<div class="panel-body">
<p>Click weight class for seeds</p>
<br>
<table class="table">
<thead>
<tr>
<th>Weight Class</th>
<th>Bracket Size</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="weight in tournament.weights | orderBy : 'max' : reverse">
<td><a data-toggle="modal" data-target="#Weight{{weight.id}}">{{ weight.max }}</a></td>
<td>{{ weight.bracket_size }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="panel panel-default">
<a class="panel-heading" ng-click="toggleBoutBoard()" style="display: block;" >
<h3 class="panel-title">Mats and Bout Board<span class="pull-left clickable"><i ng-if="showBoutBoard == false" class="glyphicon glyphicon-chevron-down"></i>
<i ng-if="showBoutBoard == true" class="glyphicon glyphicon-chevron-up"></i></span></h3>
</a>
<div id="Mats" ng-if="showBoutBoard == true">
<div class="panel-body">
<p ng-if="tournament.matches.length == 0">Matches have not been generated</p>
<table ng-if="tournament.matches.length > 0" class="table">
<thead>
<tr>
<th>Name</th>
<th>On Mat</th>
<th>On Deck</th>
<th>In The Hole</th>
<th>Warm Up</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="mat in tournament.mats">
<td>{{ mat.name }}</td>
<td>{{ mat.unfinishedMatches[0].bout_number }} {{ mat.unfinishedMatches[0].w1_name }} vs. {{ mat.unfinishedMatches[0].w2_name }}</td>
<td>{{ mat.unfinishedMatches[1].bout_number }} {{ mat.unfinishedMatches[0].w1_name }} vs. {{ mat.unfinishedMatches[0].w2_name }}</td>
<td>{{ mat.unfinishedMatches[2].bout_number }} {{ mat.unfinishedMatches[0].w1_name }} vs. {{ mat.unfinishedMatches[0].w2_name }}</td>
<td>{{ mat.unfinishedMatches[3].bout_number }} {{ mat.unfinishedMatches[0].w1_name }} vs. {{ mat.unfinishedMatches[0].w2_name }}</td>
</tr>
</tbody>
</table>
<br>
<h3 ng-if="tournament.matches.length > 0" >Matches not assigned</h3>
<br>
<table ng-if="tournament.matches.length > 0" class="table">
<thead>
<tr>
<th>Round</th>
<th>Bout Number</th>
<th>Weight Class</th>
<th>Matchup</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="match in tournament.unassignedMatches">
<td>Round {{ match.round }}</td>
<td>{{ match.bout_number }}</td>
<td>{{ match.weightClass }}</td>
<td>{{ match.w1_name }} vs. {{ match.w2_name }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!--Hidden modals for weight seeds-->
<div ng-repeat="weight in tournament.weights">
<div class="modal fade bs-example-modal-lg" id="Weight{{weight.id}}" tabindex="-1" role="dialog" aria-labelledby="Weight{{weight.id}}">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h3 class="modal-title" id="gridSystemModalLabel">{{weight.max}}</h3>
</div>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>School</th>
<th>Seed</th>
<th>Record</th>
<th>Criteria</th>
<th>Extra?</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="wrestler in weight.wrestlers | orderBy : 'original_seed' : reverse">
<td>{{wrestler.name}}</td>
<td>{{wrestler.school}}</td>
<td>{{wrestler.original_seed}}</td>
<td>{{wrestler.season_win}}-{{wrestler.season_loss}}</td>
<td>{{wrestler.criteria}} Win %{{wrestler.seasonWinPercentage}}</td>
<td>{{wrestler.extra}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!--Hidden model for new school-->
<div class="modal fade bs-example-modal-lg" id="NewSchool" tabindex="-1" role="dialog" aria-labelledby="NewSchool">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h3 class="modal-title" id="gridSystemModalLabel">New School for {{tournament.name}}</h3>
</div>
<div class="modal-body">
<form class="form" id="formNewSchool" name="form" ng-submit="saveNewSchool()">
<div class="form-group">
<input name="school[name]" class="form-control" id="name" type="text" placeholder="School Name" ng-model="newSchool.name"><br>
<input type="submit" id="btnSaveNewSchool" class="btn btn-success" value="Save School">
</div>
</form>
</div>
</div>
</div>
</div>
<!--Hidden modals for school edit forms-->
<div ng-repeat="school in tournament.schools">
<div class="modal fade bs-example-modal-lg" id="EditSchool{{school.id}}" tabindex="-1" role="dialog" aria-labelledby="EditSchool{{school.id}}">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h3 class="modal-title" id="gridSystemModalLabel">Edit {{school.name}}</h3>
</div>
<div class="modal-body">
<form class="form" id="formEditSchool{{school.id}}" name="form" ng-submit="updateSchool(school)">
<div class="form-group">
<input name="school[name]" class="form-control" id="name" type="text" placeholder="School Name" ng-model="school.name"><br>
<input type="submit" id="btnSaveNewSchool" class="btn btn-success" value="Save School">
</div>
</form>
</div>
</div>
</div>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,3 @@
<div class="hello">
<%= text %>
</div>

View File

@@ -0,0 +1,66 @@
/* Exports a function which returns an object that overrides the default &
* plugin grunt configuration object.
*
* You can familiarize yourself with Lineman's defaults by looking at:
*
* - https://github.com/linemanjs/lineman/blob/master/config/application.coffee
* - https://github.com/linemanjs/lineman/blob/master/config/plugins
*
* You can also ask about Lineman's config from the command line:
*
* $ lineman config #=> to print the entire config
* $ lineman config concat_sourcemap.js #=> to see the JS config for the concat task.
*/
module.exports = function(lineman) {
//Override application configuration here. Common examples follow in the comments.
return {
// API Proxying
//
// During development, you'll likely want to make XHR (AJAX) requests to an API on the same
// port as your lineman development server. By enabling the API proxy and setting the port, all
// requests for paths that don't match a static asset in ./generated will be forwarded to
// whatever service might be running on the specified port.
//
server: {
apiProxy: {
enabled: true,
host: 'localhost',
port: 8080
},
web: {
port: 8081
}
},
removeTasks: {
common: ["jshint"]
},
// Sass
//
// Lineman supports Sass via grunt-contrib-sass, which requires you first
// have Ruby installed as well as the `sass` gem. To enable it, uncomment the
// following line:
//
// enableSass: true,
// Asset Fingerprints
//
// Lineman can fingerprint your static assets by appending a hash to the filename
// and logging a manifest of logical-to-hashed filenames in dist/assets.json
// via grunt-asset-fingerprint
//
// enableAssetFingerprint: true,
// LiveReload
//
// Lineman can LiveReload browsers whenever a file is changed that results in
// assets to be processed, preventing the need to hit F5/Cmd-R every time you
// make a change in each browser you're working against. To enable LiveReload,
// comment out the following line:
//
// livereload: true
};
};

26
frontend/config/files.js Normal file
View File

@@ -0,0 +1,26 @@
/* Exports a function which returns an object that overrides the default &
* plugin file patterns (used widely through the app configuration)
*
* To see the default definitions for Lineman's file paths and globs, see:
*
* - https://github.com/linemanjs/lineman/blob/master/config/files.coffee
*/
module.exports = function(lineman) {
//Override file patterns here
return {
// As an example, to override the file patterns for
// the order in which to load third party JS libs:
//
// js: {
// vendor: [
// "vendor/js/underscore.js",
// "vendor/js/**/*.js"
// ]
// }
//Override file patterns here
};
};

View File

@@ -0,0 +1 @@
module.exports = require(process.env['LINEMAN_MAIN']);

21
frontend/config/server.js Normal file
View File

@@ -0,0 +1,21 @@
/* Define custom server-side HTTP routes for lineman's development server
* These might be as simple as stubbing a little JSON to
* facilitate development of code that interacts with an HTTP service
* (presumably, mirroring one that will be reachable in a live environment).
*
* It's important to remember that any custom endpoints defined here
* will only be available in development, as lineman only builds
* static assets, it can't run server-side code.
*
* This file can be very useful for rapid prototyping or even organically
* defining a spec based on the needs of the client code that emerge.
*
*/
module.exports = {
drawRoutes: function(app) {
// app.get('/api/greeting/:message', function(req, res){
// res.json({ message: "OK, "+req.params.message });
// });
}
};

View File

@@ -0,0 +1,9 @@
{
"framework" : "jasmine",
"launch_in_dev" : ["Chrome"],
"launch_in_ci" : ["PhantomJS"],
"src_files" : [
"generated/js/app.js",
"generated/js/spec.js"
]
}

15
frontend/package.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "frontend",
"description": "Frontend for wrestlingdev",
"version": "0.0.1",
"private": true,
"author": "Jacob Cody Wimer",
"devDependencies": {
"lineman": "~0.36.6"
},
"scripts": {
"start": "lineman run",
"test": "lineman spec-ci",
"production": "lineman clean build && npm i express@3 && node -e \"var e = require('express'), a = e(); a.use(e.static('dist/')); a.listen(process.env.PORT)\""
}
}

View File

@@ -0,0 +1,4 @@
describe(".helloText", function(){
When(function(){ this.result = helloText(); });
Then(function(){ expect(this.result).toEqual("Hello, World!"); });
});

View File

@@ -0,0 +1,2 @@
window.context = window.describe;
window.xcontext = window.xdescribe;

View File

@@ -0,0 +1,433 @@
/* jasmine-fixture - 1.3.2
* Makes injecting HTML snippets into the DOM easy & clean!
* https://github.com/searls/jasmine-fixture
*/
(function() {
var createHTMLBlock,
__slice = [].slice;
(function($) {
var ewwSideEffects, jasmineFixture, originalAffix, originalJasmineDotFixture, originalJasmineFixture, root, _, _ref;
root = (1, eval)('this');
originalJasmineFixture = root.jasmineFixture;
originalJasmineDotFixture = (_ref = root.jasmine) != null ? _ref.fixture : void 0;
originalAffix = root.affix;
_ = function(list) {
return {
inject: function(iterator, memo) {
var item, _i, _len, _results;
_results = [];
for (_i = 0, _len = list.length; _i < _len; _i++) {
item = list[_i];
_results.push(memo = iterator(memo, item));
}
return _results;
}
};
};
root.jasmineFixture = function($) {
var $whatsTheRootOf, affix, create, jasmineFixture, noConflict;
affix = function(selectorOptions) {
return create.call(this, selectorOptions, true);
};
create = function(selectorOptions, attach) {
var $top;
$top = null;
_(selectorOptions.split(/[ ](?![^\{]*\})(?=[^\]]*?(?:\[|$))/)).inject(function($parent, elementSelector) {
var $el;
if (elementSelector === ">") {
return $parent;
}
$el = createHTMLBlock($, elementSelector);
if (attach || $top) {
$el.appendTo($parent);
}
$top || ($top = $el);
return $el;
}, $whatsTheRootOf(this));
return $top;
};
noConflict = function() {
var currentJasmineFixture, _ref1;
currentJasmineFixture = jasmine.fixture;
root.jasmineFixture = originalJasmineFixture;
if ((_ref1 = root.jasmine) != null) {
_ref1.fixture = originalJasmineDotFixture;
}
root.affix = originalAffix;
return currentJasmineFixture;
};
$whatsTheRootOf = function(that) {
if ((that != null ? that.jquery : void 0) != null) {
return that;
} else if ($('#jasmine_content').length > 0) {
return $('#jasmine_content');
} else {
return $('<div id="jasmine_content"></div>').appendTo('body');
}
};
jasmineFixture = {
affix: affix,
create: create,
noConflict: noConflict
};
ewwSideEffects(jasmineFixture);
return jasmineFixture;
};
ewwSideEffects = function(jasmineFixture) {
var _ref1;
if ((_ref1 = root.jasmine) != null) {
_ref1.fixture = jasmineFixture;
}
$.fn.affix = root.affix = jasmineFixture.affix;
return afterEach(function() {
return $('#jasmine_content').remove();
});
};
if ($) {
return jasmineFixture = root.jasmineFixture($);
} else {
return root.affix = function() {
var nowJQueryExists;
nowJQueryExists = window.jQuery || window.$;
if (nowJQueryExists != null) {
jasmineFixture = root.jasmineFixture(nowJQueryExists);
return affix.call.apply(affix, [this].concat(__slice.call(arguments)));
} else {
throw new Error("jasmine-fixture requires jQuery to be defined at window.jQuery or window.$");
}
};
}
})(window.jQuery || window.$);
createHTMLBlock = (function() {
var bindData, bindEvents, parseAttributes, parseClasses, parseContents, parseEnclosure, parseReferences, parseVariableScope, regAttr, regAttrDfn, regAttrs, regCBrace, regClass, regClasses, regData, regDatas, regEvent, regEvents, regExclamation, regId, regReference, regTag, regTagNotContent, regZenTagDfn;
createHTMLBlock = function($, ZenObject, data, functions, indexes) {
var ZenCode, arr, block, blockAttrs, blockClasses, blockHTML, blockId, blockTag, blocks, el, el2, els, forScope, indexName, inner, len, obj, origZenCode, paren, result, ret, zc, zo;
if ($.isPlainObject(ZenObject)) {
ZenCode = ZenObject.main;
} else {
ZenCode = ZenObject;
ZenObject = {
main: ZenCode
};
}
origZenCode = ZenCode;
if (indexes === undefined) {
indexes = {};
}
if (ZenCode.charAt(0) === "!" || $.isArray(data)) {
if ($.isArray(data)) {
forScope = ZenCode;
} else {
obj = parseEnclosure(ZenCode, "!");
obj = obj.substring(obj.indexOf(":") + 1, obj.length - 1);
forScope = parseVariableScope(ZenCode);
}
while (forScope.charAt(0) === "@") {
forScope = parseVariableScope("!for:!" + parseReferences(forScope, ZenObject));
}
zo = ZenObject;
zo.main = forScope;
el = $();
if (ZenCode.substring(0, 5) === "!for:" || $.isArray(data)) {
if (!$.isArray(data) && obj.indexOf(":") > 0) {
indexName = obj.substring(0, obj.indexOf(":"));
obj = obj.substr(obj.indexOf(":") + 1);
}
arr = ($.isArray(data) ? data : data[obj]);
zc = zo.main;
if ($.isArray(arr) || $.isPlainObject(arr)) {
$.map(arr, function(value, index) {
var next;
zo.main = zc;
if (indexName !== undefined) {
indexes[indexName] = index;
}
if (!$.isPlainObject(value)) {
value = {
value: value
};
}
next = createHTMLBlock($, zo, value, functions, indexes);
if (el.length !== 0) {
return $.each(next, function(index, value) {
return el.push(value);
});
}
});
}
if (!$.isArray(data)) {
ZenCode = ZenCode.substr(obj.length + 6 + forScope.length);
} else {
ZenCode = "";
}
} else if (ZenCode.substring(0, 4) === "!if:") {
result = parseContents("!" + obj + "!", data, indexes);
if (result !== "undefined" || result !== "false" || result !== "") {
el = createHTMLBlock($, zo, data, functions, indexes);
}
ZenCode = ZenCode.substr(obj.length + 5 + forScope.length);
}
ZenObject.main = ZenCode;
} else if (ZenCode.charAt(0) === "(") {
paren = parseEnclosure(ZenCode, "(", ")");
inner = paren.substring(1, paren.length - 1);
ZenCode = ZenCode.substr(paren.length);
zo = ZenObject;
zo.main = inner;
el = createHTMLBlock($, zo, data, functions, indexes);
} else {
blocks = ZenCode.match(regZenTagDfn);
block = blocks[0];
if (block.length === 0) {
return "";
}
if (block.indexOf("@") >= 0) {
ZenCode = parseReferences(ZenCode, ZenObject);
zo = ZenObject;
zo.main = ZenCode;
return createHTMLBlock($, zo, data, functions, indexes);
}
block = parseContents(block, data, indexes);
blockClasses = parseClasses($, block);
if (regId.test(block)) {
blockId = regId.exec(block)[1];
}
blockAttrs = parseAttributes(block, data);
blockTag = (block.charAt(0) === "{" ? "span" : "div");
if (ZenCode.charAt(0) !== "#" && ZenCode.charAt(0) !== "." && ZenCode.charAt(0) !== "{") {
blockTag = regTag.exec(block)[1];
}
if (block.search(regCBrace) !== -1) {
blockHTML = block.match(regCBrace)[1];
}
blockAttrs = $.extend(blockAttrs, {
id: blockId,
"class": blockClasses,
html: blockHTML
});
el = $("<" + blockTag + ">", blockAttrs);
el.attr(blockAttrs);
el = bindEvents(block, el, functions);
el = bindData(block, el, data);
ZenCode = ZenCode.substr(blocks[0].length);
ZenObject.main = ZenCode;
}
if (ZenCode.length > 0) {
if (ZenCode.charAt(0) === ">") {
if (ZenCode.charAt(1) === "(") {
zc = parseEnclosure(ZenCode.substr(1), "(", ")");
ZenCode = ZenCode.substr(zc.length + 1);
} else if (ZenCode.charAt(1) === "!") {
obj = parseEnclosure(ZenCode.substr(1), "!");
forScope = parseVariableScope(ZenCode.substr(1));
zc = obj + forScope;
ZenCode = ZenCode.substr(zc.length + 1);
} else {
len = Math.max(ZenCode.indexOf("+"), ZenCode.length);
zc = ZenCode.substring(1, len);
ZenCode = ZenCode.substr(len);
}
zo = ZenObject;
zo.main = zc;
els = $(createHTMLBlock($, zo, data, functions, indexes));
els.appendTo(el);
}
if (ZenCode.charAt(0) === "+") {
zo = ZenObject;
zo.main = ZenCode.substr(1);
el2 = createHTMLBlock($, zo, data, functions, indexes);
$.each(el2, function(index, value) {
return el.push(value);
});
}
}
ret = el;
return ret;
};
bindData = function(ZenCode, el, data) {
var datas, i, split;
if (ZenCode.search(regDatas) === 0) {
return el;
}
datas = ZenCode.match(regDatas);
if (datas === null) {
return el;
}
i = 0;
while (i < datas.length) {
split = regData.exec(datas[i]);
if (split[3] === undefined) {
$(el).data(split[1], data[split[1]]);
} else {
$(el).data(split[1], data[split[3]]);
}
i++;
}
return el;
};
bindEvents = function(ZenCode, el, functions) {
var bindings, fn, i, split;
if (ZenCode.search(regEvents) === 0) {
return el;
}
bindings = ZenCode.match(regEvents);
if (bindings === null) {
return el;
}
i = 0;
while (i < bindings.length) {
split = regEvent.exec(bindings[i]);
if (split[2] === undefined) {
fn = functions[split[1]];
} else {
fn = functions[split[2]];
}
$(el).bind(split[1], fn);
i++;
}
return el;
};
parseAttributes = function(ZenBlock, data) {
var attrStrs, attrs, i, parts;
if (ZenBlock.search(regAttrDfn) === -1) {
return undefined;
}
attrStrs = ZenBlock.match(regAttrDfn);
attrs = {};
i = 0;
while (i < attrStrs.length) {
parts = regAttr.exec(attrStrs[i]);
attrs[parts[1]] = "";
if (parts[3] !== undefined) {
attrs[parts[1]] = parseContents(parts[3], data);
}
i++;
}
return attrs;
};
parseClasses = function($, ZenBlock) {
var classes, clsString, i;
ZenBlock = ZenBlock.match(regTagNotContent)[0];
if (ZenBlock.search(regClasses) === -1) {
return undefined;
}
classes = ZenBlock.match(regClasses);
clsString = "";
i = 0;
while (i < classes.length) {
clsString += " " + regClass.exec(classes[i])[1];
i++;
}
return $.trim(clsString);
};
parseContents = function(ZenBlock, data, indexes) {
var html;
if (indexes === undefined) {
indexes = {};
}
html = ZenBlock;
if (data === undefined) {
return html;
}
while (regExclamation.test(html)) {
html = html.replace(regExclamation, function(str, str2) {
var begChar, fn, val;
begChar = "";
if (str.indexOf("!for:") > 0 || str.indexOf("!if:") > 0) {
return str;
}
if (str.charAt(0) !== "!") {
begChar = str.charAt(0);
str = str.substring(2, str.length - 1);
}
fn = new Function("data", "indexes", "var r=undefined;" + "with(data){try{r=" + str + ";}catch(e){}}" + "with(indexes){try{if(r===undefined)r=" + str + ";}catch(e){}}" + "return r;");
val = unescape(fn(data, indexes));
return begChar + val;
});
}
html = html.replace(/\\./g, function(str) {
return str.charAt(1);
});
return unescape(html);
};
parseEnclosure = function(ZenCode, open, close, count) {
var index, ret;
if (close === undefined) {
close = open;
}
index = 1;
if (count === undefined) {
count = (ZenCode.charAt(0) === open ? 1 : 0);
}
if (count === 0) {
return;
}
while (count > 0 && index < ZenCode.length) {
if (ZenCode.charAt(index) === close && ZenCode.charAt(index - 1) !== "\\") {
count--;
} else {
if (ZenCode.charAt(index) === open && ZenCode.charAt(index - 1) !== "\\") {
count++;
}
}
index++;
}
ret = ZenCode.substring(0, index);
return ret;
};
parseReferences = function(ZenCode, ZenObject) {
ZenCode = ZenCode.replace(regReference, function(str) {
var fn;
str = str.substr(1);
fn = new Function("objs", "var r=\"\";" + "with(objs){try{" + "r=" + str + ";" + "}catch(e){}}" + "return r;");
return fn(ZenObject, parseReferences);
});
return ZenCode;
};
parseVariableScope = function(ZenCode) {
var forCode, rest, tag;
if (ZenCode.substring(0, 5) !== "!for:" && ZenCode.substring(0, 4) !== "!if:") {
return undefined;
}
forCode = parseEnclosure(ZenCode, "!");
ZenCode = ZenCode.substr(forCode.length);
if (ZenCode.charAt(0) === "(") {
return parseEnclosure(ZenCode, "(", ")");
}
tag = ZenCode.match(regZenTagDfn)[0];
ZenCode = ZenCode.substr(tag.length);
if (ZenCode.length === 0 || ZenCode.charAt(0) === "+") {
return tag;
} else if (ZenCode.charAt(0) === ">") {
rest = "";
rest = parseEnclosure(ZenCode.substr(1), "(", ")", 1);
return tag + ">" + rest;
}
return undefined;
};
regZenTagDfn = /([#\.\@]?[\w-]+|\[([\w-!?=:"']+(="([^"]|\\")+")? {0,})+\]|\~[\w$]+=[\w$]+|&[\w$]+(=[\w$]+)?|[#\.\@]?!([^!]|\\!)+!){0,}(\{([^\}]|\\\})+\})?/i;
regTag = /(\w+)/i;
regId = /(?:^|\b)#([\w-!]+)/i;
regTagNotContent = /((([#\.]?[\w-]+)?(\[([\w!]+(="([^"]|\\")+")? {0,})+\])?)+)/i;
/*
See lookahead syntax (?!) at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
*/
regClasses = /(\.[\w-]+)(?!["\w])/g;
regClass = /\.([\w-]+)/i;
regReference = /(@[\w$_][\w$_\d]+)/i;
regAttrDfn = /(\[([\w-!]+(="?([^"]|\\")+"?)? {0,})+\])/ig;
regAttrs = /([\w-!]+(="([^"]|\\")+")?)/g;
regAttr = /([\w-!]+)(="?((([\w]+(\[.*?\])+)|[^"\]]|\\")+)"?)?/i;
regCBrace = /\{(([^\}]|\\\})+)\}/i;
regExclamation = /(?:([^\\]|^))!([^!]|\\!)+!/g;
regEvents = /\~[\w$]+(=[\w$]+)?/g;
regEvent = /\~([\w$]+)=([\w$]+)/i;
regDatas = /&[\w$]+(=[\w$]+)?/g;
regData = /&([\w$]+)(=([\w$]+))?/i;
return createHTMLBlock;
})();
}).call(this);

View File

@@ -0,0 +1,373 @@
/* jasmine-given - 2.6.3
* Adds a Given-When-Then DSL to jasmine as an alternative style for specs
* https://github.com/searls/jasmine-given
*/
/* jasmine-matcher-wrapper - 0.0.3
* Wraps Jasmine 1.x matchers for use with Jasmine 2
* https://github.com/testdouble/jasmine-matcher-wrapper
*/
(function() {
var __hasProp = {}.hasOwnProperty,
__slice = [].slice;
(function(jasmine) {
var comparatorFor, createMatcher;
if (jasmine == null) {
return typeof console !== "undefined" && console !== null ? console.warn("jasmine was not found. Skipping jasmine-matcher-wrapper. Verify your script load order.") : void 0;
}
if (jasmine.matcherWrapper != null) {
return;
}
jasmine.matcherWrapper = {
wrap: function(matchers) {
var matcher, name, wrappedMatchers;
if (jasmine.addMatchers == null) {
return matchers;
}
wrappedMatchers = {};
for (name in matchers) {
if (!__hasProp.call(matchers, name)) continue;
matcher = matchers[name];
wrappedMatchers[name] = createMatcher(name, matcher);
}
return wrappedMatchers;
}
};
createMatcher = function(name, matcher) {
return function() {
return {
compare: comparatorFor(matcher, false),
negativeCompare: comparatorFor(matcher, true)
};
};
};
return comparatorFor = function(matcher, isNot) {
return function() {
var actual, context, message, params, pass, _ref;
actual = arguments[0], params = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
context = {
actual: actual,
isNot: isNot
};
pass = matcher.apply(context, params);
if (isNot) {
pass = !pass;
}
if (!pass) {
message = (_ref = context.message) != null ? _ref.apply(context, params) : void 0;
}
return {
pass: pass,
message: message
};
};
};
})(jasmine || getJasmineRequireObj());
}).call(this);
(function() {
var __slice = [].slice;
(function(jasmine) {
var Waterfall, additionalInsightsForErrorMessage, apparentReferenceError, attemptedEquality, cloneArray, comparisonInsight, currentSpec, declareJasmineSpec, deepEqualsNotice, doneWrapperFor, errorWithRemovedLines, evalInContextOfSpec, finalStatementFrom, getBlock, invariantList, mostRecentExpectations, mostRecentStacks, mostRecentlyUsed, o, root, stringifyExpectation, wasComparison, whenList, wrapAsExpectations;
mostRecentlyUsed = null;
root = (1, eval)('this');
currentSpec = null;
beforeEach(function() {
return currentSpec = this;
});
root.Given = function() {
mostRecentlyUsed = root.Given;
return beforeEach(getBlock(arguments));
};
whenList = [];
root.When = function() {
var b;
mostRecentlyUsed = root.When;
b = getBlock(arguments);
beforeEach(function() {
return whenList.push(b);
});
return afterEach(function() {
return whenList.pop();
});
};
invariantList = [];
root.Invariant = function() {
var invariantBehavior;
mostRecentlyUsed = root.Invariant;
invariantBehavior = getBlock(arguments);
beforeEach(function() {
return invariantList.push(invariantBehavior);
});
return afterEach(function() {
return invariantList.pop();
});
};
getBlock = function(thing) {
var assignResultTo, setupFunction;
setupFunction = o(thing).firstThat(function(arg) {
return o(arg).isFunction();
});
assignResultTo = o(thing).firstThat(function(arg) {
return o(arg).isString();
});
return doneWrapperFor(setupFunction, function(done) {
var context, result;
context = currentSpec;
result = setupFunction.call(context, done);
if (assignResultTo) {
if (!context[assignResultTo]) {
return context[assignResultTo] = result;
} else {
throw new Error("Unfortunately, the variable '" + assignResultTo + "' is already assigned to: " + context[assignResultTo]);
}
}
});
};
mostRecentExpectations = null;
mostRecentStacks = null;
declareJasmineSpec = function(specArgs, itFunction) {
var expectationFunction, expectations, label, stacks;
if (itFunction == null) {
itFunction = it;
}
label = o(specArgs).firstThat(function(arg) {
return o(arg).isString();
});
expectationFunction = o(specArgs).firstThat(function(arg) {
return o(arg).isFunction();
});
mostRecentlyUsed = root.subsequentThen;
mostRecentExpectations = expectations = [expectationFunction];
mostRecentStacks = stacks = [errorWithRemovedLines("failed expectation", 3)];
itFunction("then " + (label != null ? label : stringifyExpectation(expectations)), doneWrapperFor(expectationFunction, function(jasmineDone) {
var userCommands;
userCommands = [].concat(whenList, invariantList, wrapAsExpectations(expectations, stacks));
return new Waterfall(userCommands, jasmineDone).flow();
}));
return {
Then: subsequentThen,
And: subsequentThen
};
};
wrapAsExpectations = function(expectations, stacks) {
var expectation, i, _i, _len, _results;
_results = [];
for (i = _i = 0, _len = expectations.length; _i < _len; i = ++_i) {
expectation = expectations[i];
_results.push((function(expectation, i) {
return doneWrapperFor(expectation, function(maybeDone) {
return expect(expectation).not.toHaveReturnedFalseFromThen(currentSpec, i + 1, stacks[i], maybeDone);
});
})(expectation, i));
}
return _results;
};
doneWrapperFor = function(func, toWrap) {
if (func.length === 0) {
return function() {
return toWrap();
};
} else {
return function(done) {
return toWrap(done);
};
}
};
root.Then = function() {
return declareJasmineSpec(arguments);
};
root.Then.only = function() {
return declareJasmineSpec(arguments, it.only);
};
root.subsequentThen = function(additionalExpectation) {
mostRecentExpectations.push(additionalExpectation);
mostRecentStacks.push(errorWithRemovedLines("failed expectation", 3));
return this;
};
errorWithRemovedLines = function(msg, n) {
var error, lines, stack, _ref;
if (stack = new Error(msg).stack) {
_ref = stack.split("\n"), error = _ref[0], lines = 2 <= _ref.length ? __slice.call(_ref, 1) : [];
return "" + error + "\n" + (lines.slice(n).join("\n"));
}
};
mostRecentlyUsed = root.Given;
root.And = function() {
return mostRecentlyUsed.apply(this, jasmine.util.argsToArray(arguments));
};
o = function(thing) {
return {
isFunction: function() {
return Object.prototype.toString.call(thing) === "[object Function]";
},
isString: function() {
return Object.prototype.toString.call(thing) === "[object String]";
},
firstThat: function(test) {
var i;
i = 0;
while (i < thing.length) {
if (test(thing[i]) === true) {
return thing[i];
}
i++;
}
return void 0;
}
};
};
Waterfall = (function() {
function Waterfall(functions, finalCallback) {
if (functions == null) {
functions = [];
}
this.finalCallback = finalCallback != null ? finalCallback : function() {};
this.functions = cloneArray(functions);
}
Waterfall.prototype.flow = function() {
var func,
_this = this;
if (this.functions.length === 0) {
return this.finalCallback();
}
func = this.functions.shift();
if (func.length > 0) {
return func(function() {
return _this.flow();
});
} else {
func();
return this.flow();
}
};
return Waterfall;
})();
cloneArray = function(a) {
return a.slice(0);
};
jasmine._given = {
matchers: {
toHaveReturnedFalseFromThen: function(context, n, stackTrace, done) {
var e, exception, result;
result = false;
exception = void 0;
try {
result = this.actual.call(context, done);
} catch (_error) {
e = _error;
exception = e;
}
this.message = function() {
var msg, stringyExpectation;
stringyExpectation = stringifyExpectation(this.actual);
msg = "Then clause" + (n > 1 ? " #" + n : "") + " `" + stringyExpectation + "` failed by ";
if (exception) {
msg += "throwing: " + exception.toString();
} else {
msg += "returning false";
}
msg += additionalInsightsForErrorMessage(stringyExpectation);
if (stackTrace != null) {
msg += "\n\n" + stackTrace;
}
return msg;
};
return result === false;
}
},
__Waterfall__: Waterfall
};
stringifyExpectation = function(expectation) {
var matches;
matches = expectation.toString().replace(/\n/g, '').match(/function\s?\(.*\)\s?{\s*(return\s+)?(.*?)(;)?\s*}/i);
if (matches && matches.length >= 3) {
return matches[2].replace(/\s+/g, ' ');
} else {
return "";
}
};
additionalInsightsForErrorMessage = function(expectationString) {
var comparison, expectation;
expectation = finalStatementFrom(expectationString);
if (comparison = wasComparison(expectation)) {
return comparisonInsight(expectation, comparison);
} else {
return "";
}
};
finalStatementFrom = function(expectationString) {
var multiStatement;
if (multiStatement = expectationString.match(/.*return (.*)/)) {
return multiStatement[multiStatement.length - 1];
} else {
return expectationString;
}
};
wasComparison = function(expectation) {
var comparator, comparison, left, right, s;
if (comparison = expectation.match(/(.*) (===|!==|==|!=|>|>=|<|<=) (.*)/)) {
s = comparison[0], left = comparison[1], comparator = comparison[2], right = comparison[3];
return {
left: left,
comparator: comparator,
right: right
};
}
};
comparisonInsight = function(expectation, comparison) {
var left, msg, right;
left = evalInContextOfSpec(comparison.left);
right = evalInContextOfSpec(comparison.right);
if (apparentReferenceError(left) && apparentReferenceError(right)) {
return "";
}
msg = "\n\nThis comparison was detected:\n " + expectation + "\n " + left + " " + comparison.comparator + " " + right;
if (attemptedEquality(left, right, comparison.comparator)) {
msg += "\n\n" + (deepEqualsNotice(comparison.left, comparison.right));
}
return msg;
};
apparentReferenceError = function(result) {
return /^<Error: "ReferenceError/.test(result);
};
evalInContextOfSpec = function(operand) {
var e;
try {
return (function() {
return eval(operand);
}).call(currentSpec);
} catch (_error) {
e = _error;
return "<Error: \"" + ((e != null ? typeof e.message === "function" ? e.message() : void 0 : void 0) || e) + "\">";
}
};
attemptedEquality = function(left, right, comparator) {
var _ref;
if (!(comparator === "==" || comparator === "===")) {
return false;
}
if (((_ref = jasmine.matchersUtil) != null ? _ref.equals : void 0) != null) {
return jasmine.matchersUtil.equals(left, right);
} else {
return jasmine.getEnv().equals_(left, right);
}
};
deepEqualsNotice = function(left, right) {
return "However, these items are deeply equal! Try an expectation like this instead:\n expect(" + left + ").toEqual(" + right + ")";
};
return beforeEach(function() {
if (jasmine.addMatchers != null) {
return jasmine.addMatchers(jasmine.matcherWrapper.wrap(jasmine._given.matchers));
} else {
return this.addMatchers(jasmine._given.matchers);
}
});
})(jasmine);
}).call(this);

View File

@@ -0,0 +1,98 @@
/* jasmine-only - 0.1.1
* Exclusivity spec helpers for jasmine: `describe.only` and `it.only`
* https://github.com/davemo/jasmine-only
*/
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
(function(jasmine) {
var describeOnly, env, itOnly, root;
root = (1, eval)('this');
env = jasmine.getEnv();
describeOnly = function(description, specDefinitions) {
var suite;
suite = new jasmine.Suite(this, description, null, this.currentSuite);
suite.exclusive_ = 1;
this.exclusive_ = Math.max(this.exclusive_, 1);
return this.describe_(suite, specDefinitions);
};
itOnly = function(description, func) {
var spec;
spec = this.it(description, func);
spec.exclusive_ = 2;
this.exclusive_ = 2;
return spec;
};
env.exclusive_ = 0;
env.describe = function(description, specDefinitions) {
var suite;
suite = new jasmine.Suite(this, description, null, this.currentSuite);
return this.describe_(suite, specDefinitions);
};
env.describe_ = function(suite, specDefinitions) {
var declarationError, e, parentSuite;
parentSuite = this.currentSuite;
if (parentSuite) {
parentSuite.add(suite);
} else {
this.currentRunner_.add(suite);
}
this.currentSuite = suite;
declarationError = null;
try {
specDefinitions.call(suite);
} catch (_error) {
e = _error;
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
this.currentSuite = parentSuite;
return suite;
};
env.specFilter = function(spec) {
return this.exclusive_ <= spec.exclusive_;
};
env.describe.only = function() {
return describeOnly.apply(env, arguments);
};
env.it.only = function() {
return itOnly.apply(env, arguments);
};
root.describe.only = function(description, specDefinitions) {
return env.describe.only(description, specDefinitions);
};
root.it.only = function(description, func) {
return env.it.only(description, func);
};
root.iit = root.it.only;
root.ddescribe = root.describe.only;
jasmine.Spec = (function(_super) {
__extends(Spec, _super);
function Spec(env, suite, description) {
this.exclusive_ = suite.exclusive_;
Spec.__super__.constructor.call(this, env, suite, description);
}
return Spec;
})(jasmine.Spec);
return jasmine.Suite = (function(_super) {
__extends(Suite, _super);
function Suite(env, suite, specDefinitions, parentSuite) {
this.exclusive_ = parentSuite && parentSuite.exclusive_ || 0;
Suite.__super__.constructor.call(this, env, suite, specDefinitions, parentSuite);
}
return Suite;
})(jasmine.Suite);
})(jasmine);
}).call(this);

View File

@@ -0,0 +1,214 @@
/* jasmine-stealth - 0.0.17
* Makes Jasmine spies a bit more robust
* https://github.com/searls/jasmine-stealth
*/
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
(function() {
var Captor, fake, root, stubChainer, unfakes, whatToDoWhenTheSpyGetsCalled, _;
root = (1, eval)('this');
_ = function(obj) {
return {
each: function(iterator) {
var item, _i, _len, _results;
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
item = obj[_i];
_results.push(iterator(item));
}
return _results;
},
isFunction: function() {
return Object.prototype.toString.call(obj) === "[object Function]";
},
isString: function() {
return Object.prototype.toString.call(obj) === "[object String]";
}
};
};
root.spyOnConstructor = function(owner, classToFake, methodsToSpy) {
var fakeClass, spies;
if (methodsToSpy == null) {
methodsToSpy = [];
}
if (_(methodsToSpy).isString()) {
methodsToSpy = [methodsToSpy];
}
spies = {
constructor: jasmine.createSpy("" + classToFake + "'s constructor")
};
fakeClass = (function() {
function _Class() {
spies.constructor.apply(this, arguments);
}
return _Class;
})();
_(methodsToSpy).each(function(methodName) {
spies[methodName] = jasmine.createSpy("" + classToFake + "#" + methodName);
return fakeClass.prototype[methodName] = function() {
return spies[methodName].apply(this, arguments);
};
});
fake(owner, classToFake, fakeClass);
return spies;
};
unfakes = [];
afterEach(function() {
_(unfakes).each(function(u) {
return u();
});
return unfakes = [];
});
fake = function(owner, thingToFake, newThing) {
var originalThing;
originalThing = owner[thingToFake];
owner[thingToFake] = newThing;
return unfakes.push(function() {
return owner[thingToFake] = originalThing;
});
};
root.stubFor = root.spyOn;
jasmine.createStub = jasmine.createSpy;
jasmine.createStubObj = function(baseName, stubbings) {
var name, obj, stubbing;
if (stubbings.constructor === Array) {
return jasmine.createSpyObj(baseName, stubbings);
} else {
obj = {};
for (name in stubbings) {
stubbing = stubbings[name];
obj[name] = jasmine.createSpy(baseName + "." + name);
if (_(stubbing).isFunction()) {
obj[name].andCallFake(stubbing);
} else {
obj[name].andReturn(stubbing);
}
}
return obj;
}
};
whatToDoWhenTheSpyGetsCalled = function(spy) {
var matchesStub, priorPlan;
matchesStub = function(stubbing, args, context) {
switch (stubbing.type) {
case "args":
return jasmine.getEnv().equals_(stubbing.ifThis, jasmine.util.argsToArray(args));
case "context":
return jasmine.getEnv().equals_(stubbing.ifThis, context);
}
};
priorPlan = spy.plan;
return spy.andCallFake(function() {
var i, stubbing;
i = 0;
while (i < spy._stealth_stubbings.length) {
stubbing = spy._stealth_stubbings[i];
if (matchesStub(stubbing, arguments, this)) {
if (stubbing.satisfaction === "callFake") {
return stubbing.thenThat.apply(stubbing, arguments);
} else {
return stubbing.thenThat;
}
}
i++;
}
return priorPlan.apply(spy, arguments);
});
};
jasmine.Spy.prototype.whenContext = function(context) {
var spy;
spy = this;
spy._stealth_stubbings || (spy._stealth_stubbings = []);
whatToDoWhenTheSpyGetsCalled(spy);
return stubChainer(spy, "context", context);
};
jasmine.Spy.prototype.when = function() {
var ifThis, spy;
spy = this;
ifThis = jasmine.util.argsToArray(arguments);
spy._stealth_stubbings || (spy._stealth_stubbings = []);
whatToDoWhenTheSpyGetsCalled(spy);
return stubChainer(spy, "args", ifThis);
};
stubChainer = function(spy, type, ifThis) {
var addStubbing;
addStubbing = function(satisfaction) {
return function(thenThat) {
spy._stealth_stubbings.unshift({
type: type,
ifThis: ifThis,
satisfaction: satisfaction,
thenThat: thenThat
});
return spy;
};
};
return {
thenReturn: addStubbing("return"),
thenCallFake: addStubbing("callFake")
};
};
jasmine.Spy.prototype.mostRecentCallThat = function(callThat, context) {
var i;
i = this.calls.length - 1;
while (i >= 0) {
if (callThat.call(context || this, this.calls[i]) === true) {
return this.calls[i];
}
i--;
}
};
jasmine.Matchers.ArgThat = (function(_super) {
__extends(ArgThat, _super);
function ArgThat(matcher) {
this.matcher = matcher;
}
ArgThat.prototype.jasmineMatches = function(actual) {
return this.matcher(actual);
};
return ArgThat;
})(jasmine.Matchers.Any);
jasmine.Matchers.ArgThat.prototype.matches = jasmine.Matchers.ArgThat.prototype.jasmineMatches;
jasmine.argThat = function(expected) {
return new jasmine.Matchers.ArgThat(expected);
};
jasmine.Matchers.Capture = (function(_super) {
__extends(Capture, _super);
function Capture(captor) {
this.captor = captor;
}
Capture.prototype.jasmineMatches = function(actual) {
this.captor.value = actual;
return true;
};
return Capture;
})(jasmine.Matchers.Any);
jasmine.Matchers.Capture.prototype.matches = jasmine.Matchers.Capture.prototype.jasmineMatches;
Captor = (function() {
function Captor() {}
Captor.prototype.capture = function() {
return new jasmine.Matchers.Capture(this);
};
return Captor;
})();
return jasmine.captor = function() {
return new Captor();
};
})();
}).call(this);

0
frontend/tasks/.keep Normal file
View File

0
frontend/vendor/css/.keep vendored Normal file
View File

0
frontend/vendor/img/.keep vendored Normal file
View File

10
frontend/vendor/js/devise-min.js vendored Normal file
View File

@@ -0,0 +1,10 @@
// AngularDevise
// -------------------
// v1.2.1
//
// Copyright (c)2016 Justin Ridgewell
// Distributed under MIT license
//
// https://github.com/cloudspace/angular_devise
!function(a){"use strict";var b=a.module("Devise",[]);b.provider("AuthIntercept",function(){var a=!1;this.interceptAuth=function(b){return a=!!b||void 0===b,this},this.$get=["$rootScope","$q",function(b,c){return{responseError:function(d){var e=d.config.interceptAuth;if(e=!!e||a&&void 0===e,e&&401===d.status){var f=c.defer();return b.$broadcast("devise:unauthorized",d,f),f.reject(d),f.promise}return c.reject(d)}}}]}).config(["$httpProvider",function(a){a.interceptors.push("AuthIntercept")}]),b.provider("Auth",function(){function b(b,c,d){var h={method:f[b].toLowerCase(),url:e[b]};return c&&(g?(h.data={},h.data[g]=c):h.data=c),a.extend(h,d),h}function c(b,c){a.forEach(b,function(a,d){this[d+c]=function(a){return void 0===a?b[d]:(b[d]=a,this)}},this)}function d(a){return function(){return a}}var e={login:"/users/sign_in.json",logout:"/users/sign_out.json",register:"/users.json",sendResetPasswordInstructions:"/users/password.json",resetPassword:"/users/password.json"},f={login:"POST",logout:"DELETE",register:"POST",sendResetPasswordInstructions:"POST",resetPassword:"PUT"},g="user",h=function(a){return a.data};c.call(this,f,"Method"),c.call(this,e,"Path"),this.resourceName=function(a){return void 0===a?g:(g=a,this)},this.parse=function(a){return"function"!=typeof a?h:(h=a,this)},this.$get=["$q","$http","$rootScope",function(a,c,e){function f(a){return j._currentUser=a,a}function g(){f(null),j._promise=null}function i(a){return function(b){return e.$broadcast("devise:"+a,b),b}}var j={_currentUser:null,parse:h,_promise:null,reset:function(){g(),j.currentUser()},login:function(a,d){var e=arguments.length>0,g=j.isAuthenticated();return a=a||{},c(b("login",a,d)).then(j.parse).then(f).then(function(a){return e&&!g?i("new-session")(a):a}).then(i("login"))},logout:function(a){var e=d(j._currentUser);return c(b("logout",void 0,a)).then(g).then(e).then(i("logout"))},register:function(a,d){return a=a||{},c(b("register",a,d)).then(j.parse).then(f).then(i("new-registration"))},sendResetPasswordInstructions:function(a){return a=a||{},c(b("sendResetPasswordInstructions",a)).then(j.parse).then(i("send-reset-password-instructions-successfully"))},resetPassword:function(a){return a=a||{},c(b("resetPassword",a)).then(j.parse).then(f).then(i("reset-password-successfully"))},currentUser:function(){return j.isAuthenticated()?a.when(j._currentUser):(null===j._promise&&(j._promise=j.login()),j._promise)},isAuthenticated:function(){return!!j._currentUser}};return j}]})}(angular);

1343
frontend/vendor/js/underscore.js vendored Normal file

File diff suppressed because it is too large Load Diff

0
frontend/vendor/static/.keep vendored Normal file
View File

View File

@@ -3,7 +3,7 @@ FROM ruby:2.3.0
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y nodejs sqlite3
RUN apt-get install -y nodejs-legacy nodejs sqlite3 npm
ENV WRESTLINGDEV_SECRET_KEY_BASE 077cdbef5c2ccf22543fb17a67339f234306b7fa2e1e4463d851c444c10a5611829a2290b253da78339427f131571fac9a42c83d960b2d25ecc10a4a0a7ce1a2
ENV WRESTLINGDEV_DEVISE_SECRET_KEY 2f29d49db6704377ba263f7cb9db085b386bcb301c0cd501126a674686ab1a109754071165b08cd72af03cec4642a4dd04361c994462254dd5d85e9594e8b9aa
@@ -13,8 +13,13 @@ ADD Gemfile* /tmp/
WORKDIR /tmp
RUN bundle install --without production
RUN npm install -g lineman
RUN mkdir /rails
WORKDIR /rails
ADD . /rails
VOLUME ["/rails"]
EXPOSE 3000

View File

@@ -4,7 +4,7 @@ FROM ruby:2.3.0
RUN apt-get update
RUN apt-get -y upgrade
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential libssl-dev libyaml-dev libreadline-dev openssl curl git-core zlib1g-dev bison libxml2-dev libxslt1-dev libcurl4-openssl-dev libsqlite3-dev sqlite3 wget apache2 apt-transport-https nodejs mysql-client postfix
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential libssl-dev libyaml-dev libreadline-dev openssl curl git-core zlib1g-dev bison libxml2-dev libxslt1-dev libcurl4-openssl-dev libsqlite3-dev sqlite3 wget apache2 apt-transport-https nodejs nodejs-legacy npm mysql-client postfix
#New Relic
#RUN echo deb http://apt.newrelic.com/debian/ newrelic non-free >> /etc/apt/sources.list.d/newrelic.list
@@ -50,6 +50,12 @@ COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install --without test
#Cache node_modules
WORKDIR /tmp
COPY frontend/package.json package.json
RUN npm install
RUN npm install lineman
RUN npm install -g lineman
# Copy site into place.
RUN rm -rf /var/www
@@ -59,9 +65,13 @@ ENV WRESTLINGDEV_SECRET_KEY_BASE 077cdbef5c2ccf22543fb17a67339f234306b7fa2e1e446
ENV WRESTLINGDEV_DEVISE_SECRET_KEY 2f29d49db6704377ba263f7cb9db085b386bcb301c0cd501126a674686ab1a109754071165b08cd72af03cec4642a4dd04361c994462254dd5d85e9594e8b9aa
WORKDIR /var/www/
ADD . /var/www/
#Copy node_modules to /var/www
RUN mv /tmp/node_modules /var/www/frontend/node_modules
#RUN RAILS_ENV=production bundle exec rake db:migrate
RUN RAILS_ENV=production bundle exec rake assets:precompile
#RUN cp /var/www/frontend/dist/*.html /var/www/public/
# Update the default apache site with the config we created.
RUN rm /etc/apache2/sites-enabled/000-default.conf
@@ -73,8 +83,7 @@ RUN a2ensite default-ssl.conf
RUN echo PassengerMaxPoolSize 3 >> /etc/apache2/apache2.conf
RUN echo PassengerMinInstances 3 >> /etc/apache2/apache2.conf
RUN echo PassengerPreStart *:443 >> /etc/apache2/apache2.conf
# By default, simply start apache.
CMD /usr/sbin/apache2ctl -D FOREGROUND

2
run-all-tests.sh Executable file
View File

@@ -0,0 +1,2 @@
rake db:migrate RAILS_ENV=test
rake test

View File

@@ -0,0 +1,7 @@
require 'test_helper'
class ApiControllerTest < ActionController::TestCase
# test "the truth" do
# assert true
# end
end

View File

@@ -5,12 +5,12 @@ class MatchesControllerTest < ActionController::TestCase
setup do
@tournament = Tournament.find(1)
@tournament.generateMatchups
@match = @tournament.matches.first
# @tournament.generateMatchups
@match = Match.where("tournament_id = ? and mat_id = ?",1,1).first
end
def post_update
patch :update, id: @match.id, match: {w1: @match.w1, w2: @match.w2}
patch :update, id: @match.id, match: {tournament_id: 1, mat_id: 1}
end
def get_edit

View File

@@ -5,7 +5,7 @@ class MatsControllerTest < ActionController::TestCase
setup do
@tournament = Tournament.find(1)
@tournament.generateMatchups
# @tournament.generateMatchups
@mat = mats(:one)
end

View File

@@ -5,7 +5,7 @@ class SchoolsControllerTest < ActionController::TestCase
setup do
@tournament = Tournament.find(1)
@tournament.generateMatchups
# @tournament.generateMatchups
@school = @tournament.schools.first
end

View File

@@ -5,7 +5,7 @@ class StaticPagesControllerTest < ActionController::TestCase
setup do
@tournament = Tournament.find(1)
@tournament.generateMatchups
# @tournament.generateMatchups
@school = @tournament.schools.first
end

View File

@@ -5,7 +5,7 @@ include Devise::TestHelpers
setup do
@tournament = Tournament.find(1)
@tournament.generateMatchups
# @tournament.generateMatchups
@school = @tournament.schools.first
@wrestlers = @tournament.weights.first.wrestlers
@adjust = Teampointadjust.find(1)

Some files were not shown because too many files have changed in this diff Show More