Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-07-16 16:15:46 -07:00
commit 727638b090
70 changed files with 616 additions and 96 deletions

View file

@ -96,7 +96,9 @@ Aether.addGlobal('_', _);
var serializedClasses = {
"Thang": self.require('lib/world/thang'),
"Vector": self.require('lib/world/vector'),
"Rectangle": self.require('lib/world/rectangle')
"Rectangle": self.require('lib/world/rectangle'),
"Ellipse": self.require('lib/world/ellipse'),
"LineSegment": self.require('lib/world/line_segment')
};
self.currentUserCodeMapCopy = "";
self.currentDebugWorldFrame = 0;

View file

@ -181,12 +181,11 @@ module.exports = class Mark extends CocoClass
buildDebug: ->
@mark = new createjs.Shape()
PX = 3
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x]
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x] # TODO: doesn't work with rotation
@mark.alpha = 0.5
@mark.graphics.beginFill '#abcdef'
if @sprite.thang.shape in ['ellipsoid', 'disc']
[w, h] = [Math.max(PX, w, h), Math.max(PX, w, h)]
@mark.graphics.drawCircle 0, 0, w / 2
@mark.graphics.drawEllipse -w / 2, -h / 2, w, h
else
@mark.graphics.drawRect -w / 2, -h / 2, w, h
@mark.graphics.endFill()
@ -259,7 +258,7 @@ module.exports = class Mark extends CocoClass
updateRotation: ->
if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ['rectangle', 'box'])
@mark.rotation = @sprite.thang.rotation * 180 / Math.PI
@mark.rotation = -@sprite.thang.rotation * 180 / Math.PI
updateScale: ->
if @name is 'bounds' and ((@sprite.thang.width isnt @lastWidth or @sprite.thang.height isnt @lastHeight) or (@sprite.thang.drawsBoundsIndex isnt @drawsBoundsIndex))

View file

@ -0,0 +1,174 @@
Vector = require './vector'
LineSegment = require './line_segment'
Rectangle = require './rectangle'
class Ellipse
@className: "Ellipse"
# TODO: add class methods for add, multiply, subtract, divide, rotate
isEllipse: true
apiProperties: ['x', 'y', 'width', 'height', 'rotation', 'distanceToPoint', 'distanceSquaredToPoint', 'distanceToRectangle', 'distanceSquaredToRectangle', 'distanceToEllipse', 'distanceSquaredToEllipse', 'distanceToShape', 'distanceSquaredToShape', 'containsPoint', 'intersectsLineSegment', 'intersectsRectangle', 'intersectsEllipse', 'getPos', 'containsPoint', 'copy']
constructor: (@x=0, @y=0, @width=0, @height=0, @rotation=0) ->
copy: ->
new Ellipse(@x, @y, @width, @height, @rotation)
getPos: ->
new Vector(@x, @y)
rectangle: ->
new Rectangle(@x, @y, @width, @height, @rotation)
axisAlignedBoundingBox: (rounded=true) ->
@rectangle().axisAlignedBoundingBox()
distanceToPoint: (p) ->
@rectangle().distanceToPoint p # TODO: actually implement ellipse ellipse-point distance
distanceSquaredToPoint: (p) ->
# Doesn't handle rotation; just supposed to be faster than distanceToPoint.
@rectangle().distanceSquaredToPoint p # TODO: actually implement ellipse-point distance
distanceToRectangle: (other) ->
Math.sqrt @distanceSquaredToRectangle other
distanceSquaredToRectangle: (other) ->
@rectangle().distanceSquaredToRectangle other # TODO: actually implement ellipse-rectangle distance
distanceToEllipse: (ellipse) ->
Math.sqrt @distanceSquaredToEllipse ellipse
distanceSquaredToEllipse: (ellipse) ->
@rectangle().distanceSquaredToEllipse ellipse # TODO: actually implement ellipse-ellipse distance
distanceToShape: (shape) ->
Math.sqrt @distanceSquaredToShape shape
distanceSquaredToShape: (shape) ->
if shape.isEllipse then @distanceSquaredToEllipse shape else @distanceSquaredToRectangle shape
containsPoint: (p, withRotation=true) ->
[a, b] = [@width / 2, @height / 2]
[h, k] = [@x, @y]
[x, y] = [p.x, p.y]
x2 = Math.pow(x, 2)
a2 = Math.pow(a, 2)
a4 = Math.pow(a, 4)
b2 = Math.pow(b, 2)
b4 = Math.pow(b, 4)
h2 = Math.pow(h, 2)
k2 = Math.pow(k, 2)
if withRotation and @rotation
sint = Math.sin(@rotation)
sin2t = Math.sin(2 * @rotation)
cost = Math.cos(@rotation)
cos2t = Math.cos(2 * @rotation)
numeratorLeft = (-a2 * h * sin2t) + (a2 * k * cos2t) + (a2 * k) + (a2 * x * sin2t)
numeratorMiddle = Math.SQRT2 * Math.sqrt((a4 * b2 * cos2t) + (a4 * b2) - (a2 * b4 * cos2t) + (a2 * b4) - (2 * a2 * b2 * h2) + (4 * a2 * b2 * h * x) - (2 * a2 * b2 * x2))
numeratorRight = (b2 * h * sin2t) - (b2 * k * cos2t) + (b2 * k) - (b2 * x * sin2t)
denominator = (a2 * cos2t) + a2 - (b2 * cos2t) + b2
solution1 = (numeratorLeft - numeratorMiddle + numeratorRight) / denominator
solution2 = (numeratorLeft + numeratorMiddle + numeratorRight) / denominator
if (not isNaN solution1) and (not isNaN solution2)
[bigSolution, littleSolution] = if solution1 > solution2 then [solution1, solution2] else [solution2, solution1]
if y > littleSolution and y < bigSolution
return true
else
return false
else
return false
else
numeratorLeft = a2 * k
numeratorRight = Math.sqrt((a4 * b2) - (a2 * b2 * h2) + (2 * a2 * b2 * h * x) - (a2 * b2 * x2))
denominator = a2
solution1 = (numeratorLeft + numeratorRight) / denominator
solution2 = (numeratorLeft - numeratorRight) / denominator
if (not isNaN solution1) and (not isNaN solution2)
[bigSolution, littleSolution] = if solution1 > solution2 then [solution1, solution2] else [solution2, solution1]
if y > littleSolution and y < bigSolution
return true
else
return false
else
return false
false
intersectsLineSegment: (p1, p2) ->
[px1, py1, px2, py2] = [p1.x, p1.y, p2.x, p2.y]
m = (py1 - py2) / (px1 - px2)
m2 = Math.pow(m, 2)
c = py1 - (m * px1)
c2 = Math.pow(c, 2)
[a, b] = [@width / 2, @height / 2]
[h, k] = [@x, @y]
a2 = Math.pow(a, 2)
a4 = Math.pow(a, 2)
b2 = Math.pow(b, 2)
b4 = Math.pow(b, 4)
h2 = Math.pow(h, 2)
k2 = Math.pow(k, 2)
sint = Math.sin(@rotation)
sin2t = Math.sin(2 * @rotation)
cost = Math.cos(@rotation)
cos2t = Math.cos(2 * @rotation)
if (not isNaN m) and m != Infinity and m != -Infinity
numeratorLeft = (-a2 * c * m * cos2t) - (a2 * c * m) + (a2 * c * sin2t) - (a2 * h * m * sin2t) - (a2 * h * cos2t) + (a2 * h) + (a2 * k * m * cos2t) + (a2 * k * m) - (a2 * k * sin2t)
numeratorMiddle = Math.SQRT2 * Math.sqrt((a4 * b2 * m2 * cos2t) + (a4 * b2 * m2) - (2 * a4 * b2 * m * sin2t) - (a4 * b2 * cos2t) + (a4 * b2) - (a2 * b4 * m2 * cos2t) + (a2 * b4 * m2) + (2 * a2 * b4 * m * sin2t) + (a2 * b4 * cos2t) + (a2 * b4) - (2 * a2 * b2 * c2) - (4 * a2 * b2 * c * h * m) + (4 * a2 * b2 * c * k) - (2 * a2 * b2 * h2 * m2) + (4 * a2 * b2 * h * k * m) - (2 * a2 * b2 * k2))
numeratorRight = (b2 * c * m * cos2t) - (b2 * c * m) - (b2 * c * sin2t) + (b2 * h * m * sin2t) + (b2 * h * cos2t) + (b2 * h) - (b2 * k * m * cos2t) + (b2 * k * m) + (b2 * k * sin2t)
denominator = (a2 * m2 * cos2t) + (a2 * m2) - (2 * a2 * m * sin2t) - (a2 * cos2t) + a2 - (b2 * m2 * cos2t) + (b2 * m2) + (2 * b2 * m * sin2t) + (b2 * cos2t) + b2
solution1 = (-numeratorLeft - numeratorMiddle + numeratorRight) / denominator
solution2 = (-numeratorLeft + numeratorMiddle + numeratorRight) / denominator
if (not isNaN solution1) and (not isNaN solution2)
[littleX, bigX] = if px1 < px2 then [px1, px2] else [px2, px1]
if (littleX <= solution1 and bigX >= solution1) or (littleX <= solution2 and bigX >= solution2)
return true
if (not isNaN solution1) or (not isNaN solution2)
solution = if not isNaN solution1 then solution1 else solution2
[littleX, bigX] = if px1 < px2 then [px1, px2] else [px2, px1]
if littleX <= solution and bigX >= solution
return true
else
return false
else
x = px1
x2 = Math.pow(x, 2)
numeratorLeft = (-a2 * h * sin2t) + (a2 * k * cos2t) + (a2 * k) + (a2 * x * sin2t)
numeratorMiddle = Math.SQRT2 * Math.sqrt((a4 * b2 * cos2t) + (a4 * b2) - (a2 * b4 * cos2t) + (a2 * b4) - (2 * a2 * b2 * h2) + (4 * a2 * b2 * h * x) - (2 * a2 * b2 * x2))
numeratorRight = (b2 * h * sin2t) - (b2 * k * cos2t) + (b2 * k) - (b2 * x * sin2t)
denominator = (a2 * cos2t) + a2 - (b2 * cos2t) + b2
solution1 = (numeratorLeft - numeratorMiddle + numeratorRight) / denominator
solution2 = (numeratorLeft + numeratorMiddle + numeratorRight) / denominator
if (not isNaN solution1) or (not isNaN solution2)
solution = if not isNaN solution1 then solution1 else solution2
[littleY, bigY] = if py1 < py2 then [py1, py2] else [py2, py1]
if littleY <= solution and bigY >= solution
return true
else
return false
false
intersectsRectangle: (rectangle) ->
rectangle.intersectsEllipse @
intersectsEllipse: (ellipse) ->
@rectangle().intersectsEllipse @ # TODO: actually implement ellipse-ellipse intersection
#return true if @containsPoint ellipse.getPos()
intersectsShape: (shape) ->
if shape.isEllipse then @intersectsEllipse shape else @intersectsRectangle shape
toString: ->
return "{x: #{@x.toFixed(0)}, y: #{@y.toFixed(0)}, w: #{@width.toFixed(0)}, h: #{@height.toFixed(0)}, rot: #{@rotation.toFixed(3)}}"
serialize: ->
{CN: @constructor.className, x: @x, y: @y, w: @width, h: @height, r: @rotation}
@deserialize: (o, world, classMap) ->
new Ellipse o.x, o.y, o.w, o.h, o.r
serializeForAether: -> @serialize()
@deserializeFromAether: (o) -> @deserialize o
module.exports = Ellipse

View file

@ -0,0 +1,80 @@
class LineSegment
@className: "LineSegment"
constructor: (@a, @b) ->
@slope = (@a.y - @b.y) / (@a.x - @b.x)
@y0 = @a.y - (@slope * @a.x)
@left = if @a.x < @b.x then @a else @b
@right = if @a.x > @b.x then @a else @b
@bottom = if @a.y < @b.y then @a else @b
@top = if @a.y > @b.y then @a else @b
y: (x) ->
(@slope * x) + @y0
x: (y) ->
(y - @y0) / @slope
intersectsLineSegment: (lineSegment) ->
if lineSegment.slope is @slope
if lineSegment.y0 is @y0
if lineSegment.left.x is @left.x or lineSegment.left.x is @right.x or lineSegment.right.x is @right.x or lineSegment.right.x is @left.x
# segments are of the same line with shared start and/or end points
return true
else
[left, right] = if lineSegment.left.x < @left.x then [lineSegment, @] else [@, lineSegment]
if left.right.x > right.left.x
# segments are of the same line and one is contained within the other
return true
else if Math.abs(@slope) isnt Infinity and Math.abs(lineSegment.slope) isnt Infinity
x = (lineSegment.y0 - @y0) / (@slope - lineSegment.slope)
if x >= @left.x and x <= @right.x and x >= lineSegment.left.x and x <= lineSegment.right.x
return true
else if Math.abs(@slope) isnt Infinity or Math.abs(lineSegment.slope) isnt Infinity
[vertical, nonvertical] = if Math.abs(@slope) isnt Infinity then [lineSegment, @] else [@, lineSegment]
x = vertical.a.x
bottom = vertical.bottom.y
top = vertical.top.y
y = nonvertical.y(x)
left = nonvertical.left.x
right = nonvertical.right.x
if y >= bottom and y <= top and x >= left and x <= right
return true
false
pointOnLine: (point, segment=true) ->
if point.y is @y(point.x)
if segment
[littleY, bigY] = if @a.y < @b.y then [@a.y, @b.y] else [@b.y, @a.y]
if littleY <= point.y and bigY >= point.y
return true
else
return true
false
distanceSquaredToPoint: (point) ->
# http://stackoverflow.com/a/1501725/540620
return @a.distanceSquared point if @a.equals @b
res = Math.min point.distanceSquared(@a), point.distanceSquared(@b)
lineMagnitudeSquared = @a.distanceSquared @b
t = ((point.x - @a.x) * (@b.x - @a.x) + (point.y - @a.y) * (@b.y - @a.y)) / lineMagnitudeSquared
return @a.distanceSquared point if t < 0
return @b.distanceSquared point if t > 1
point.distanceSquared x: @a.x + t * (@b.x - @a.x), y: @a.y + t * (@b.y - @a.y)
distanceToPoint: (point) ->
Math.sqrt @distanceSquaredToPoint point
toString: ->
"lineSegment(a=#{@a}, b=#{@b}, slope=#{@slope}, y0=#{@y0}, left=#{@left}, right=#{@right}, bottom=#{@bottom}, top=#{@top})"
serialize: ->
{CN: @constructor.className, a: @a, b: @b}
@deserialize: (o, world, classMap) ->
new LineSegment o.a, o.b
serializeForAether: -> @serialize()
@deserializeFromAether: (o) -> @deserialize o
module.exports = LineSegment

View file

@ -1,14 +1,16 @@
Vector = require './vector'
LineSegment = require './line_segment'
class Rectangle
@className: 'Rectangle'
# Class methods for nondestructively operating
# Class methods for nondestructively operating - TODO: add rotate
for name in ['add', 'subtract', 'multiply', 'divide']
do (name) ->
Rectangle[name] = (a, b) ->
a.copy()[name](b)
apiProperties: ['x', 'y', 'width', 'height', 'rotation', 'getPos', 'vertices', 'touchesRect', 'touchesPoint', 'distanceToPoint', 'containsPoint', 'copy']
isRectangle: true
apiProperties: ['x', 'y', 'width', 'height', 'rotation', 'getPos', 'vertices', 'touchesRect', 'touchesPoint', 'distanceToPoint', 'distanceSquaredToPoint', 'distanceToRectangle', 'distanceSquaredToRectangle', 'distanceToEllipse', 'distanceSquaredToEllipse', 'distanceToShape', 'distanceSquaredToShape', 'containsPoint', 'copy', 'intersectsLineSegment', 'intersectsEllipse', 'intersectsRectangle', 'intersectsShape']
constructor: (@x=0, @y=0, @width=0, @height=0, @rotation=0) ->
@ -28,6 +30,14 @@ class Rectangle
new Vector @x + (w2 * cos + h2 * sin), @y + (w2 * sin - h2 * cos)
]
lineSegments: ->
vertices = @vertices()
lineSegment0 = new LineSegment vertices[0], vertices[1]
lineSegment1 = new LineSegment vertices[1], vertices[2]
lineSegment2 = new LineSegment vertices[2], vertices[3]
lineSegment3 = new LineSegment vertices[3], vertices[0]
[lineSegment0, lineSegment1, lineSegment2, lineSegment3]
touchesRect: (other) ->
# Whether this rect shares part of any edge with other rect, for non-rotated, non-overlapping rectangles.
# I think it says kitty-corner rects touch, but I don't think I want that.
@ -62,25 +72,90 @@ class Rectangle
box
distanceToPoint: (p) ->
# Get p in rect's coordinate space, then operate in one quadrant
# Get p in rect's coordinate space, then operate in one quadrant.
p = Vector.subtract(p, @getPos()).rotate(-@rotation)
dx = Math.max(Math.abs(p.x) - @width / 2, 0)
dy = Math.max(Math.abs(p.y) - @height / 2, 0)
Math.sqrt dx * dx + dy * dy
distanceSquaredToPoint: (p) ->
# Doesn't handle rotation; just supposed to be faster than distanceToPoint
# Doesn't handle rotation; just supposed to be faster than distanceToPoint.
p = Vector.subtract(p, @getPos())
dx = Math.max(Math.abs(p.x) - @width / 2, 0)
dy = Math.max(Math.abs(p.y) - @height / 2, 0)
dx * dx + dy * dy
distanceToRectangle: (other) ->
Math.sqrt @distanceSquaredToRectangle other
distanceSquaredToRectangle: (other) ->
return 0 if @intersectsRectangle other
[firstVertices, secondVertices] = [@vertices(), other.vertices()]
[firstEdges, secondEdges] = [@lineSegments(), other.lineSegments()]
ans = Infinity
for i in [0 ... 4]
for j in [0 ... firstEdges.length]
ans = Math.min ans, firstEdges[j].distanceSquaredToPoint(secondVertices[i])
for j in [0 ... secondEdges.length]
ans = Math.min ans, secondEdges[j].distanceSquaredToPoint(firstVertices[i])
ans
distanceToEllipse: (ellipse) ->
Math.sqrt @distanceSquaredToEllipse ellipse
distanceSquaredToEllipse: (ellipse) ->
@distanceSquaredToRectangle ellipse.rectangle() # TODO: actually implement rectangle-ellipse distance
distanceToShape: (shape) ->
Math.sqrt @distanceSquaredToShape shape
distanceSquaredToShape: (shape) ->
if shape.isEllipse then @distanceSquaredToEllipse shape else @distanceSquaredToRectangle shape
containsPoint: (p, withRotation=true) ->
if withRotation and @rotation
not @distanceToPoint(p)
else
@x - @width / 2 < p.x < @x + @width / 2 and @y - @height / 2 < p.y < @y + @height / 2
intersectsLineSegment: (p1, p2) ->
[px1, py1, px2, py2] = [p1.x, p1.y, p2.x, p2.y]
m1 = (py1 - py2) / (px1 - px2)
b1 = py1 - (m1 * px1)
vertices = @vertices()
lineSegments = [[vertices[0], vertices[1]], [vertices[1], vertices[2]], [vertices[2], vertices[3]], [vertices[3], vertices[0]]]
for lineSegment in lineSegments
[px1, py1, px2, py2] = [p1.x, p1.y, p2.x, p2.y]
m2 = (py1 - py2) / (px1 - px2)
b2 = py1 - (m * px1)
if m1 isnt m2
m = m1 - m2
b = b2 - b1
x = b / m
[littleX, bigX] = if px1 < px2 then [px1, px2] else [px2, px1]
if x >= littleX and x <= bigX
y = (m1 * x) + b1
[littleY, bigY] = if py1 < py2 then [py1, py2] else [py2, py1]
if littleY <= solution and bigY >= solution
return true
false
intersectsRectangle: (rectangle) ->
return true if @containsPoint rectangle.getPos()
for thisLineSegment in @lineSegments()
for thatLineSegment in rectangle.lineSegments()
if thisLineSegment.intersectsLineSegment(thatLineSegment)
return true
false
intersectsEllipse: (ellipse) ->
return true if @containsPoint ellipse.getPos()
return true for lineSegment in @lineSegments() when ellipse.intersectsLineSegment lineSegment.a, lineSegment.b
false
intersectsShape: (shape) ->
if shape.isEllipse then @intersectsEllipse shape else @intersectsRectangle shape
subtract: (point) ->
@x -= point.x
@y -= point.y
@ -102,10 +177,10 @@ class Rectangle
@
isEmpty: () ->
@width == 0 and @height == 0
@width is 0 and @height is 0
invalid: () ->
return (@x == Infinity) || isNaN(@x) || @y == Infinity || isNaN(@y) || @width == Infinity || isNaN(@width) || @height == Infinity || isNaN(@height) || @rotation == Infinity || isNaN(@rotation)
return (@x is Infinity) || isNaN(@x) || @y is Infinity || isNaN(@y) || @width is Infinity || isNaN(@width) || @height is Infinity || isNaN(@height) || @rotation is Infinity || isNaN(@rotation)
toString: ->
return "{x: #{@x.toFixed(0)}, y: #{@y.toFixed(0)}, w: #{@width.toFixed(0)}, h: #{@height.toFixed(0)}, rot: #{@rotation.toFixed(3)}}"

View file

@ -1,5 +1,7 @@
Vector = require './vector'
Rectangle = require './rectangle'
Ellipse = require './ellipse'
LineSegment = require './line_segment'
WorldFrame = require './world_frame'
Thang = require './thang'
ThangState = require './thang_state'
@ -21,7 +23,7 @@ module.exports = class World
apiProperties: ['age', 'dt']
constructor: (@userCodeMap, classMap) ->
# classMap is needed for deserializing Worlds, Thangs, and other classes
@classMap = classMap ? {Vector: Vector, Rectangle: Rectangle, Thang: Thang}
@classMap = classMap ? {Vector: Vector, Rectangle: Rectangle, Thang: Thang, Ellipse: Ellipse, LineSegment: LineSegment}
Thang.resetThangIDs()
@userCodeMap ?= {}

View file

@ -1,5 +1,7 @@
Vector = require './vector'
Rectangle = require './rectangle'
Ellipse = require './ellipse'
LineSegment = require './line_segment'
Grid = require './Grid'
module.exports.typedArraySupport = typedArraySupport = Float32Array? # Not in IE until IE 10; we'll fall back to normal arrays
@ -36,7 +38,7 @@ module.exports.clone = clone = (obj, skipThangs=false) ->
flags += 'y' if obj.sticky?
return new RegExp(obj.source, flags)
if (obj instanceof Vector) or (obj instanceof Rectangle)
if (obj instanceof Vector) or (obj instanceof Rectangle) or (obj instanceof Ellipse) or (obj instanceof LineSegment)
return obj.copy()
if skipThangs and obj.isThang

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "български език", englishDescri
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
error_saving: "Chyba při ukládání"
saved: "Změny uloženy"
password_mismatch: "Hesla nesouhlasí."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
error_saving: "Fejl under Gemning"
saved: "Ændringer Gemt"
password_mismatch: "Password matcher ikke."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
error_saving: "Fehler beim Speichern"
saved: "Änderungen gespeichert"
password_mismatch: "Passwörter stimmen nicht überein."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Jobprofil"
job_profile_approved: "Dein Jobprofil wurde von CodeCombat freigegeben. Arbeitgeber können dieses solange einsehen, bis du es als inaktiv markiert oder wenn innerhalb von vier Wochen keine Änderung daran vorgenommen wurde."
job_profile_explanation: "Hi! Fülle dies aus und wir melden uns bei dir bezüglich des Auffindens eines Jobs als Programmierer"

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
error_saving: "Fehler beim Speichern"
saved: "Änderungen gespeichert"
password_mismatch: "Passwörter stimmen nicht überein."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Jobprofil"
job_profile_approved: "Dein Jobprofil wurde von CodeCombat freigegeben. Arbeitgeber können dieses solange einsehen, bis du es als inaktiv markiert oder wenn innerhalb von vier Wochen keine Änderung daran vorgenommen wurde."
job_profile_explanation: "Hi! Fülle dies aus und wir melden uns bei dir bezüglich des Auffindens eines Jobs als Programmierer"

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
error_saving: "Σφάλμα αποθήκευσης"
saved: "Οι αλλαγές αποθηκεύτηκαν"
password_mismatch: "Οι κωδικοί δεν ταιριάζουν"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@
error_saving: "Error Saving"
saved: "Changes Saved"
password_mismatch: "Password does not match."
password_repeat: "Please repeat your massword."
password_repeat: "Please repeat your password."
job_profile: "Job Profile"
job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
error_saving: "Error al Guardar"
saved: "Cambios Guardados"
password_mismatch: "La contraseña no coincide."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Perfil de Trabajo"
job_profile_approved: "Tu perfil de trabajo ha sido aprobado por CodeCombat. Los empleadores podrán verlo hasta que lo marques como inactivo o permanezca sin cambios por cuatro semanas."
job_profile_explanation: "¡Hola! Llena esto, y te contactaremos acerca de encontrar un trabajo como desarrollador de software."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
error_saving: "Error al guardar"
saved: "Cambios guardados"
password_mismatch: "La contraseña no coincide"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Perfil de trabajo"
job_profile_approved: "Tu perfil de trabajo ha sido aprobado por CodeCombat. Los empleadores podrán verlo hasta que lo marques como inactivo o no haya sido cambiado durante cuatro semanas."
job_profile_explanation: "¡Hola! Rellena esto y estaremos en contacto para hablar sobre encontrarte un trabajo como desarrollador de software."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
error_saving: "Error al guardar"
saved: "Cambios guardados"
password_mismatch: "La contraseña no coincide"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
error_saving: "Problème d'enregistrement"
saved: "Changements sauvegardés"
password_mismatch: "Le mot de passe ne correspond pas."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Profil d'emploi"
job_profile_approved: "Votre profil d'emploi a été approuvé par CodeCombat. Les employeurs seront en mesure de voir votre profil jusqu'à ce que vous le marquez inactif ou qu'il n'a pas été changé pendant quatre semaines."
job_profile_explanation: "Salut! Remplissez-le et nous prendrons contact pour vous trouver un emploi de développeur de logiciels."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
error_saving: "בעיה בשמירה"
saved: "השינויים נשמרו"
password_mismatch: "סיסמאות לא זהות"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
error_saving: "Hiba a mentés során"
saved: "Változtatások elmentve"
password_mismatch: "A jelszavak nem egyeznek."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Munkaköri leírás"
job_profile_approved: "Munkaköri leírásodat a Codecombat jóváhagyta. Munkaadók mindaddig láthatják, amíg meg nem jelölöd inaktívként, vagy négy hétig, ha addig nem kerül megváltoztatásra."
job_profile_explanation: "Szió! Töltsd ki ezt és majd kapcsolatba lépünk veled és keresünk neked egy szoftware fejlesztői állást."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
error_saving: "Errore durante il salvataggio"
saved: "Modifiche salvate"
password_mismatch: "La password non corrisponde."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
error_saving: "セーブ中にエラーが発生しました"
saved: "変更しました"
password_mismatch: "パスワードが違います"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "求職情報"
job_profile_approved: "CodeCombatは、あなたの求職情報を承りました。無効にする、もしくは4週間の間変更をしなければ雇用者はあなたの求職情報を見ることができなくなります。"
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
error_saving: "오류 저장"
saved: "변경사항 저장 완료"
password_mismatch: "비밀번호가 일치하지 않습니다."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
error_saving: "Masalah menyimpan"
saved: "Pengubahsuian disimpan"
password_mismatch: "Kata-laluan tidak sama."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
error_saving: "Lagring Feilet"
saved: "Endringer Lagret"
password_mismatch: "Passordene er ikke like."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
error_saving: "Fout Tijdens Het Opslaan"
saved: "Aanpassingen Opgeslagen"
password_mismatch: "Het wachtwoord komt niet overeen."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Job Profiel"
job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken."
job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
error_saving: "Fout Tijdens Het Opslaan"
saved: "Aanpassingen Opgeslagen"
password_mismatch: "Het wachtwoord komt niet overeen."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Job Profiel"
job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken."
job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
error_saving: "Fout Tijdens Het Opslaan"
saved: "Aanpassingen Opgeslagen"
password_mismatch: "Het wachtwoord komt niet overeen."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Job Profiel"
job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken."
job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
error_saving: "Lagring Feilet"
saved: "Endringer Lagret"
password_mismatch: "Passordene er ikke like."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
error_saving: "Błąd zapisywania"
saved: "Zmiany zapisane"
password_mismatch: "Hasła róznią się od siebie"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
error_saving: "Erro no salvamento"
saved: "Alterações Salvas"
password_mismatch: "As senhas não estão iguais"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Perfil de trabalho"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
error_saving: "Erro ao Guardar"
saved: "Alterações Guardadas"
password_mismatch: "As palavras-passe não coincidem."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Perfil de Emprego"
job_profile_approved: "O seu perfil de emprego foi aprovado pelo CodeCombat. Os empregadores poderão vê-lo até que o defina como inativo ou não o tenha alterado à 4 semanas."
job_profile_explanation: "Olá! Preencha isto e entraremos em contacto consigo sobre encontrar um emprego de desenvolvedor de software para si."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
error_saving: "Erro no salvamento"
saved: "Alterações Salvas"
password_mismatch: "As senhas não estão iguais"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
error_saving: "Salvare erori"
saved: "Modificări salvate"
password_mismatch: "Parola nu se potrivește."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
error_saving: "Ошибка сохранения"
saved: "Изменения сохранены"
password_mismatch: "Пароли не совпадают."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Профиль соискателя"
job_profile_approved: "Ваш профиль соискателя был одобрен CodeCombat. Работодатели смогут видеть его, пока вы не отметите его неактивным или он не будет изменен в течение четырёх недель."
job_profile_explanation: "Привет! Заполните это, и мы свяжемся с вами при нахождении работы разработчика программного обеспечения для вас."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
error_saving: "Chyba pri ukladaní"
saved: "Zmeny uložené"
password_mismatch: "Heslá nesedia."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
error_saving: "Чување грешке..."
saved: "Измене су сачуване"
password_mismatch: "Шифре се не слажу."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
error_saving: "Ett fel uppstod när ändringarna skulle sparas"
saved: "Ändringar sparade"
password_mismatch: "De angivna lösenorden stämmer inte överens."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
error_saving: "บันทึกผิดพลาด"
saved: "เปลี่ยนรหัสผ่าน"
password_mismatch: "รหัสผ่านไม่ถูกต้อง"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
error_saving: "Kayıt Esnasında Hata"
saved: "Değişiklikler Kaydedildi"
password_mismatch: "Şifreler Uyuşmuyor"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
error_saving: "Помилка при збереженні"
saved: "Зміни збережено"
password_mismatch: "Паролі не збігаються."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "Профіль роботи"
job_profile_approved: "Ваш робочий пофіль буде затверджений CodeCombat. Роботодавці зможуть бачити його якщо він буде відмічений як активний, або він не зазнає змін протягом 4 тижнів."
job_profile_explanation: "Привіт! Заповніть це і ми з Вами зв‘яжемось знайшовши для Вас роботу розробника ПЗ."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
error_saving: "Lỗi lưu"
saved: "Thay đổi được lưu"
password_mismatch: "Mật khẩu không khớp."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
error_saving: "保存时出错"
saved: "更改已保存"
password_mismatch: "密码不匹配。"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "工作经历"
job_profile_approved: "你填写的工作经历将由CodeCombat认证. 雇主将看到这些信息,除非你将它设置为不启用状态或者连续四周没有更新."
job_profile_explanation: "你好! 填写这些信息, 我们将使用它帮你寻找一份软件开发的工作."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
error_saving: "保存時發生錯誤"
saved: "修改已儲存"
password_mismatch: "密碼不正確。"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
# error_saving: "Error Saving"
# saved: "Changes Saved"
# password_mismatch: "Password does not match."
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
error_saving: "保存時出錯"
saved: "保存起來哉"
password_mismatch: "密碼弗合。"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
job_profile: "工作經歷"
job_profile_approved: "爾填個工作經歷會讓CodeCombat來確認. 僱主會望着箇許訊息,除非爾畀渠調成望弗着狀態要勿粘牢四個星期朆改動。"
job_profile_explanation: "爾好!填箇許訊息,我裏會用渠幫爾尋一份軟件開發個工作。"

View file

@ -186,7 +186,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
error_saving: "保存失败"
saved: "已保存"
password_mismatch: "密码不对应"
# password_repeat: "Please repeat your massword."
# password_repeat: "Please repeat your password."
# job_profile: "Job Profile"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."

View file

@ -1,5 +1,7 @@
#test-view
background-color: #eee
margin: 0 20px
padding: 0
h2
background: #add8e6
@ -11,4 +13,4 @@
width: 78%
#test-nav
width: 20%
width: 20%

View file

@ -20,3 +20,5 @@ ol.breadcrumb
span.spl= child.name
if child.type == 'folder'
strong (#{child.size})
.clearfix

View file

@ -6,6 +6,8 @@ serializedClasses =
Thang: require 'lib/world/thang'
Vector: require 'lib/world/vector'
Rectangle: require 'lib/world/rectangle'
Ellipse: require 'lib/world/ellipse'
LineSegment: require 'lib/world/line_segment'
module.exports = class DebugView extends View
className: 'spell-debug-view'

View file

@ -14,7 +14,7 @@ describe 'Camera (Surface point of view)', ->
sup = cam.worldToSurface wop
expect(sup.x).toBeCloseTo wop.x * Camera.PPM
expect(sup.y).toBeCloseTo cam.surfaceHeight - (wop.y + wop.z * cam.z2y) * cam.y2x * Camera.PPM
expect(sup.y).toBeCloseTo -(wop.y + wop.z * cam.z2y) * cam.y2x * Camera.PPM
cap = cam.worldToCanvas wop
expect(cap.x).toBeCloseTo (sup.x - cam.surfaceViewport.x) * cam.zoom
@ -83,47 +83,48 @@ describe 'Camera (Surface point of view)', ->
testAngles = [0, Math.PI / 4, null, Math.PI / 2]
testFOVs = [Math.PI / 6, Math.PI / 3, Math.PI / 2, Math.PI]
xit 'handles lots of different cases correctly', ->
it 'handles lots of different cases correctly', ->
for wop in testWops
for size in testCanvasSizes
for zoom in testZooms
for target in testZoomTargets
for angle in testAngles
for fov in testFOVs
cam = new Camera size.width, size.height, size.width * Camera.MPP, size.height * Camera.MPP, testLayer, zoom, null, angle, fov
cam = new Camera {attr: (attr) -> if 'attr' is 'width' then size.width else size.height}, angle, fov
checkCameraPos cam, wop
cam.zoomTo target, zoom, 0
checkConversionsFromWorldPos wop, cam
checkCameraPos cam, wop
it 'works at 90 degrees', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
cam = new Camera {attr: (attr) -> 100}, Math.PI / 2
expect(cam.x2y).toBeCloseTo 1
expect(cam.x2z).toBeGreaterThan 9001
expect(cam.z2y).toBeCloseTo 0
it 'works at 0 degrees', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
expect(cam.x2z).toBeGreaterThan 9001
expect(cam.x2y).toBeCloseTo 1
expect(cam.z2y).toBeCloseTo 0
cam = new Camera {attr: (attr) -> 100}, 0
expect(cam.x2y).toBeGreaterThan 9001
expect(cam.x2z).toBeCloseTo 1
expect(cam.z2y).toBeGreaterThan 9001
it 'works at 45 degrees', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
expect(cam.x2y).toBeCloseTo 1
expect(cam.x2z).toBeGreaterThan 9001
expect(cam.z2y).toBeCloseTo 0
cam = new Camera {attr: (attr) -> 100}, Math.PI / 4
expect(cam.x2y).toBeCloseTo Math.sqrt(2)
expect(cam.x2z).toBeCloseTo Math.sqrt(2)
expect(cam.z2y).toBeCloseTo 1
xit 'works at default angle of asin(0.75) ~= 48.9 degrees', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
angle = 1 / Math.cos angle
it 'works at default angle of asin(0.75) ~= 48.9 degrees', ->
cam = new Camera {attr: (attr) -> 100}, null
angle = Math.asin(3 / 4)
expect(cam.angle).toBeCloseTo angle
expect(cam.x2y).toBeCloseTo 1
expect(cam.x2z).toBeGreaterThan 9001
expect(cam.z2y).toBeCloseTo 0
expect(cam.x2y).toBeCloseTo 4 / 3
expect(cam.x2z).toBeCloseTo 1 / Math.cos angle
expect(cam.z2y).toBeCloseTo (4 / 3) * Math.cos angle
xit 'works at 2x zoom, 90 degrees', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
cam = new Camera {attr: (attr) -> 100}, Math.PI / 2
cam.zoomTo null, 2, 0
checkCameraPos cam
wop = x: 5, y: 2.5, z: 7
cap = cam.worldToCanvas wop
@ -143,7 +144,8 @@ describe 'Camera (Surface point of view)', ->
expectPositionsEqual cap, {x: 0, y: 50}
xit 'works at 2x zoom, 30 degrees', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 2 * 100 * Camera.MPP
cam = new Camera {attr: (attr) -> 100}, Math.PI / 6
cam.zoomTo null, 2, 0
expect(cam.x2y).toBeCloseTo 1
expect(cam.x2z).toBeGreaterThan 9001
checkCameraPos cam
@ -164,15 +166,18 @@ describe 'Camera (Surface point of view)', ->
expectPositionsEqual cap, {x: 50, y: -100}
it 'works at 2x zoom, 60 degree hFOV', ->
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
cam = new Camera {attr: (attr) -> 100}, null, Math.PI / 3
cam.zoomTo null, 2, 0
checkCameraPos cam
xit 'works at 2x zoom, 60 degree hFOV, 40 degree hFOV', ->
cam = new Camera {attr: (x) -> x is 'height' ? 63.041494 : 100}, 100 * Camera.MPP, 63.041494 * Camera.MPP
it 'works at 2x zoom, 60 degree hFOV, 40 degree vFOV', ->
cam = new Camera {attr: (attr) -> if attr is 'height' then 63.041494 else 100}, null, Math.PI / 3
cam.zoomTo null, 2, 0
checkCameraPos cam
xit 'works on a surface wider than it is tall, 30 degrees, default viewing upper left corner', ->
cam = new Camera {attr: (x) -> 100}, 200 * Camera.MPP, 2 * 50 * Camera.MPP
xit 'works at 2x zoom on a surface wider than it is tall, 30 degrees, default viewing upper left corner', ->
cam = new Camera {attr: (attr) -> 100}, Math.PI / 6 # 200 * Camera.MPP, 2 * 50 * Camera.MPP
cam.zoomTo null, 2, 0
checkCameraPos cam
expect(cam.zoom).toBeCloseTo 2
wop = x: 5, y: 4, z: 6 * cam.y2z # like x: 5, y: 10 out of world width: 20, height: 10

View file

@ -0,0 +1,99 @@
describe 'Ellipse', ->
Ellipse = require 'lib/world/ellipse'
Rectangle = require 'lib/world/rectangle'
Vector = require 'lib/world/vector'
#it 'contains its own center', ->
# ellipse = new Ellipse 0, 0, 10, 10
# expect(ellipse.containsPoint(new Vector 0, 0)).toBe true
#
#it 'contains a point when rotated', ->
# ellipse = new Ellipse 0, -20, 40, 40, 3 * Math.PI / 4
# p = new Vector 0, 2
# expect(ellipse.containsPoint(p, true)).toBe true
#
#it 'contains more points properly', ->
# # ellipse with y major axis, off-origin center, and 45 degree rotation
# ellipse = new Ellipse 1, 2, 4, 6, Math.PI / 4
# expect(ellipse.contains new Vector(1, 2)).toBe true
# expect(ellipse.contains new Vector(-1, 3)).toBe true
# expect(ellipse.contains new Vector(0, 4)).toBe true
# expect(ellipse.contains new Vector(1, 4)).toBe true
# expect(ellipse.contains new Vector(3, 0)).toBe true
# expect(ellipse.contains new Vector(1, 0)).toBe true
# expect(ellipse.contains new Vector(0, 1)).toBe true
# expect(ellipse.contains new Vector(-1, 2)).toBe true
# expect(ellipse.contains new Vector(2, 2)).toBe true
# expect(ellipse.contains new Vector(0, 0)).toBe false
# expect(ellipse.contains new Vector(0, 5)).toBe false
# expect(ellipse.contains new Vector(3, 4)).toBe false
# expect(ellipse.contains new Vector(4, 0)).toBe false
# expect(ellipse.contains new Vector(2, -1)).toBe false
# expect(ellipse.contains new Vector(0, -3)).toBe false
# expect(ellipse.contains new Vector(-2, -2)).toBe false
# expect(ellipse.contains new Vector(-2, 0)).toBe false
# expect(ellipse.contains new Vector(-2, 4)).toBe false
#
#it 'correctly calculates distance to a faraway point', ->
# ellipse = new Ellipse 100, 50, 20, 40
# p = new Vector 200, 300
# d = 10 * Math.sqrt(610)
# expect(ellipse.distanceToPoint(p)).toBeCloseTo d
# ellipse.rotation = Math.PI / 2
# d = 80 * Math.sqrt(10)
# expect(ellipse.distanceToPoint(p)).toBeCloseTo d
#
#it 'does not modify itself or target Vector when calculating distance', ->
# ellipse = new Ellipse -100, -200, 1, 100
# ellipse2 = ellipse.copy()
# p = new Vector -100.25, -101
# p2 = p.copy()
# ellipse.distanceToPoint(p)
# expect(p.x).toEqual p2.x
# expect(p.y).toEqual p2.y
# expect(ellipse.x).toEqual ellipse2.x
# expect(ellipse.y).toEqual ellipse2.y
# expect(ellipse.width).toEqual ellipse2.width
# expect(ellipse.height).toEqual ellipse2.height
# expect(ellipse.rotation).toEqual ellipse2.rotation
#
#it 'correctly calculates distance to contained point', ->
# ellipse = new Ellipse -100, -200, 1, 100
# ellipse2 = ellipse.copy()
# p = new Vector -100.25, -160
# p2 = p.copy()
# expect(ellipse.distanceToPoint(p)).toBe 0
# ellipse.rotation = 0.00000001 * Math.PI
# expect(ellipse.distanceToPoint(p)).toBe 0
#
#it 'AABB works when not rotated', ->
# ellipse = new Ellipse 10, 20, 30, 40
# rect = new Rectangle 10, 20, 30, 40
# aabb1 = ellipse.axisAlignedBoundingBox()
# aabb2 = ellipse.axisAlignedBoundingBox()
# for prop in ['x', 'y', 'width', 'height']
# expect(aabb1[prop]).toBe aabb2[prop]
#
#it 'AABB works when rotated', ->
# ellipse = new Ellipse 10, 20, 30, 40, Math.PI / 3
# rect = new Rectangle 10, 20, 30, 40, Math.PI / 3
# aabb1 = ellipse.axisAlignedBoundingBox()
# aabb2 = ellipse.axisAlignedBoundingBox()
# for prop in ['x', 'y', 'width', 'height']
# expect(aabb1[prop]).toBe aabb2[prop]
#
#it 'calculates ellipse intersections properly', ->
# # ellipse with y major axis, off-origin center, and 45 degree rotation
# ellipse = new Ellipse 1, 2, 4, 6, Math.PI / 4
# expect(ellipse.intersectsShape new Rectangle(0, 0, 2, 2, 0)).toBe true
# expect(ellipse.intersectsShape new Rectangle(0, -1, 2, 3, 0)).toBe true
# expect(ellipse.intersectsShape new Rectangle(-1, -0.5, 2 * Math.SQRT2, 2 * Math.SQRT2, Math.PI / 4)).toBe true
# expect(ellipse.intersectsShape new Rectangle(-1, -0.5, 2 * Math.SQRT2, 2 * Math.SQRT2, 0)).toBe true
# expect(ellipse.intersectsShape new Rectangle(-1, -1, 2 * Math.SQRT2, 2 * Math.SQRT2, 0)).toBe true
# expect(ellipse.intersectsShape new Rectangle(-1, -1, 2 * Math.SQRT2, 2 * Math.SQRT2, Math.PI / 4)).toBe false
# expect(ellipse.intersectsShape new Rectangle(-2, -2, 2, 2, 0)).toBe false
# expect(ellipse.intersectsShape new Rectangle(-Math.SQRT2 / 2, -Math.SQRT2 / 2, Math.SQRT2, Math.SQRT2, 0)).toBe false
# expect(ellipse.intersectsShape new Rectangle(-Math.SQRT2 / 2, -Math.SQRT2 / 2, Math.SQRT2, Math.SQRT2, Math.PI / 4)).toBe false
# expect(ellipse.intersectsShape new Rectangle(-2, 0, 2, 2, 0)).toBe false
# expect(ellipse.intersectsShape new Rectangle(0, -2, 2, 2, 0)).toBe false
# expect(ellipse.intersectsShape new Rectangle(1, 2, 1, 1, 0)).toBe true

View file

@ -0,0 +1,51 @@
describe 'LineSegment', ->
LineSegment = require 'lib/world/line_segment'
Vector = require 'lib/world/vector'
v00 = new Vector(0, 0)
v11 = new Vector(1, 1)
v22 = new Vector(2, 2)
v34 = new Vector(3, 4)
v04 = new Vector(0, 4)
v30 = new Vector(3, 0)
vneg = new Vector(-1, -1)
it 'intersects itself', ->
lineSegment = new LineSegment v00, v34
expect(lineSegment.intersectsLineSegment lineSegment).toBe true
it 'intersects other segments properly', ->
l1 = new LineSegment v00, v34
l2 = new LineSegment v04, v30
l3 = new LineSegment v00, v11
expect(l1.intersectsLineSegment l2).toBe true
expect(l2.intersectsLineSegment l1).toBe true
expect(l1.intersectsLineSegment l3).toBe true
expect(l3.intersectsLineSegment l1).toBe true
expect(l2.intersectsLineSegment l3).toBe false
expect(l3.intersectsLineSegment l2).toBe false
it 'can tell when a point is on a line or segment', ->
lineSegment = new LineSegment v00, v11
expect(lineSegment.pointOnLine v22, false).toBe true
#expect(lineSegment.pointOnLine v22, true).toBe false
#expect(lineSegment.pointOnLine v00, false).toBe true
#expect(lineSegment.pointOnLine v00, true).toBe true
#expect(lineSegment.pointOnLine v11, true).toBe true
#expect(lineSegment.pointOnLine v11, false).toBe true
#expect(lineSegment.pointOnLine v34, false).toBe false
#expect(lineSegment.pointOnLine v34, true).toBe false
it 'correctly calculates distance to points', ->
lineSegment = new LineSegment v00, v11
expect(lineSegment.distanceToPoint v00).toBe 0
expect(lineSegment.distanceToPoint v11).toBe 0
expect(lineSegment.distanceToPoint v22).toBeCloseTo Math.SQRT2
expect(lineSegment.distanceToPoint v34).toBeCloseTo Math.sqrt(2 * 2 + 3 * 3)
expect(lineSegment.distanceToPoint v04).toBeCloseTo Math.sqrt(1 * 1 + 3 * 3)
expect(lineSegment.distanceToPoint v30).toBeCloseTo Math.sqrt(2 * 2 + 1 * 1)
expect(lineSegment.distanceToPoint vneg).toBeCloseTo Math.SQRT2
nullSegment = new LineSegment v11, v11
expect(lineSegment.distanceToPoint v11).toBe 0
expect(lineSegment.distanceToPoint v22).toBeCloseTo Math.SQRT2

View file

@ -1,6 +1,7 @@
describe 'Rectangle', ->
Rectangle = require 'lib/world/rectangle'
Vector = require 'lib/world/vector'
Ellipse = require 'lib/world/ellipse'
it 'contains its own center', ->
rect = new Rectangle 0, 0, 10, 10
@ -43,6 +44,13 @@ describe 'Rectangle', ->
rect.rotation = 0.00000001 * Math.PI
expect(rect.distanceToPoint(p)).toBe 0
it 'correctly calculates distance to other rectangles', ->
expect(new Rectangle(0, 0, 4, 4, Math.PI / 4).distanceToRectangle(new Rectangle(4, -4, 2, 2, 0))).toBeCloseTo 2.2426
expect(new Rectangle(0, 0, 3, 3, 0).distanceToRectangle(new Rectangle(0, 0, 2, 2, 0))).toBe 0
expect(new Rectangle(0, 0, 3, 3, 0).distanceToRectangle(new Rectangle(0, 0, 2.5, 2.5, Math.PI / 4))).toBe 0
expect(new Rectangle(0, 0, 4, 4, 0).distanceToRectangle(new Rectangle(4, 2, 2, 2, 0))).toBe 1
expect(new Rectangle(0, 0, 4, 4, 0).distanceToRectangle(new Rectangle(4, 2, 2, 2, Math.PI / 4))).toBeCloseTo 2 - Math.SQRT2
it 'has predictable vertices', ->
rect = new Rectangle 50, 50, 100, 100
v = rect.vertices()
@ -79,3 +87,22 @@ describe 'Rectangle', ->
aabb = rect.axisAlignedBoundingBox()
for prop in ['x', 'y', 'width', 'height']
expect(rect[prop]).toBe aabb[prop]
it 'calculates rectangle intersections properly', ->
rect = new Rectangle 1, 1, 2, 2, 0
expect(rect.intersectsShape new Rectangle(3, 1, 2, 2, 0)).toBe true
expect(rect.intersectsShape new Rectangle(3, 3, 2, 2, 0)).toBe true
expect(rect.intersectsShape new Rectangle(1, 1, 2, 2, 0)).toBe true
expect(rect.intersectsShape new Rectangle(1, 1, Math.SQRT1_2, Math.SQRT1_2, Math.PI / 4)).toBe true
expect(rect.intersectsShape new Rectangle(4, 1, 2, 2, 0)).toBe false
expect(rect.intersectsShape new Rectangle(3, 4, 2, 2, 0)).toBe false
expect(rect.intersectsShape new Rectangle(1, 4, 2 * Math.SQRT1_2, 2 * Math.SQRT1_2, Math.PI / 4)).toBe false
expect(rect.intersectsShape new Rectangle(3, 1, 2, 2, Math.PI / 4)).toBe true
expect(rect.intersectsShape new Rectangle(1, 2, 2 * Math.SQRT2, 2 * Math.SQRT2, Math.PI / 4)).toBe true
it 'calculates ellipse intersections properly', ->
rect = new Rectangle 1, 1, 2, 2, 0
expect(rect.intersectsShape new Ellipse(1, 1, Math.SQRT1_2, Math.SQRT1_2, Math.PI / 4)).toBe true
expect(rect.intersectsShape new Ellipse(4, 1, 2, 2, 0)).toBe false
expect(rect.intersectsShape new Ellipse(3, 4, 2, 2, 0)).toBe false
expect(rect.intersectsShape new Ellipse(1, 4, 2 * Math.SQRT1_2, 2 * Math.SQRT1_2, Math.PI / 4)).toBe false

View file

@ -1,5 +1,3 @@
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
.html-reporter a { text-decoration: none; }
.html-reporter a:hover { text-decoration: underline; }