 module.exports = (objects) ->
-  ##################################
-  # Lanes
-  ##################################
-  class Lanes
-    constructor: (lanes) ->
-      @distanceFromCenter = []
-      for lane in lanes
-        @distanceFromCenter[lane.index] = lane.distanceFromCenter
-
-    getDistances: ({startLaneIndex, endLaneIndex}) ->
-      startDistance = @distanceFromCenter[startLaneIndex]
-      endDistance = @distanceFromCenter[endLaneIndex]
-
-      startDistance: startDistance
-      endDistance: endDistance
-      totalDistance: Math.abs startDistance - endDistance
-      isSwitch: startLaneIndex isnt endLaneIndex
-
-
-  ##################################
-  # Track
-  ##################################
-  class Track
-    constructor: ({@id, @pieces, lanes}) ->
-      @lanes = new Lanes lanes
-
-    normalizedPieceIndex: ({pieceIndex, lap}) =>
-      lap * @pieces.length + pieceIndex
-
-    pieceAt: (normalizedIndex) ->
-      # positive modulus
-      index = ((normalizedIndex % @pieces.length) + @pieces.length) % @pieces.length
-      @pieces[index]
-
-    addPiecesLengthsBetween: (initialPosition, piecePosition, carLane) ->
-      indices = [(@normalizedPieceIndex initialPosition)...(@normalizedPieceIndex piecePosition)]
-      indices.reduce ((sum, index) => sum + @pieceLength index, carLane), -initialPosition.inPieceDistance
-
-    pieceLength: (index, carLane) ->
-      {startDistance, endDistance, totalDistance, isSwitch} = @lanes.getDistances carLane.atIndex index
-      piece = @pieceAt(index)
-      if (piece.length?)
-        if isSwitch
-          1.0008 * Math.sqrt totalDistance * totalDistance + piece.length * piece.length
-        else
-          piece.length
-      else
-        lengthOnStartLane = @bendedPieceLength piece, startDistance
-        return lengthOnStartLane unless isSwitch
-        lengthOnEndLane = @bendedPieceLength piece, endDistance
-        innerLength = Math.min(lengthOnEndLane, lengthOnStartLane)
-        outerLength = Math.max(lengthOnEndLane, lengthOnStartLane)
-        ratio = (outerLength / innerLength)
-        factor = 1.023 / Math.pow(ratio, 2.2)
-        innerLength + (outerLength - innerLength) * factor
-
-    bendedPieceLength: ({radius, angle}, distanceFromCenter) ->
-        bended = if angle < 0 then 1 else -1
-        laneRadius = radius + bended * distanceFromCenter
-        laneRadius * Math.PI * Math.abs(angle) / 180
-
   ##################################
   # Race
   ##################################
   class Race
+    race = null
     constructor: ({track, @cars, @raceSession}) ->
+      race = this
       @currentTick = 0
       @track = new Track track
       @carLanes = []

      for car in @cars
        color = car.id.color
        @carColors.push color
        @carLanes[color] = @createCarLane()
        @carPositions[color] = new CarPositions

    createCarLane: -> new CarLane @track.normalizedPieceIndex

    distance: (piecePosition, initialPosition = createPosition(0, 0), carLane = @createCarLane()) ->
      if not (carLane instanceof CarLane)
        carLane = @getCarLane carLane
      sum = @track.addPiecesLengthsBetween initialPosition, piecePosition, carLane



    ##################################
    # Track
    ##################################
    class Track
      mod = (n, m) -> ((n % m) + m) % m

      constructor: ({@id, @pieces, lanes}) ->
        @lanes = new Lanes lanes

      normalizedPieceIndex: ({pieceIndex, lap}) => lap * @pieces.length + pieceIndex
      pieceAt: (normalizedIndex) -> @pieces[mod normalizedIndex, @pieces.length]

      addPiecesLengthsBetween: (initialPosition, piecePosition, carLane) ->
        indices = [(@normalizedPieceIndex initialPosition)...(@normalizedPieceIndex piecePosition)]
        indices.reduce ((sum, index) => sum + @pieceLength index, carLane), -initialPosition.inPieceDistance

      pieceLength: (index, carLane) ->
        {startDistance, endDistance, totalDistance, isSwitch} = @lanes.getDistances carLane.atIndex index
        piece = @pieceAt(index)
        if (piece.length?)
          if isSwitch
            1.0008 * Math.sqrt totalDistance * totalDistance + piece.length * piece.length
          else
            piece.length
        else
          lengthOnStartLane = @bendedPieceLength piece, startDistance
          return lengthOnStartLane unless isSwitch
          lengthOnEndLane = @bendedPieceLength piece, endDistance
          innerLength = Math.min(lengthOnEndLane, lengthOnStartLane)
          outerLength = Math.max(lengthOnEndLane, lengthOnStartLane)
          ratio = (outerLength / innerLength)
          factor = 1.023 / Math.pow(ratio, 2.2)
          innerLength + (outerLength - innerLength) * factor

      bendedPieceLength: ({radius, angle}, distanceFromCenter) ->
        bended = if angle < 0 then 1 else -1
        laneRadius = radius + bended * distanceFromCenter
        laneRadius * Math.PI * Math.abs(angle) / 180

    ##################################
    # Lanes
    ##################################
    class Lanes
      constructor: (lanes) ->
        @distanceFromCenter = []
        for lane in lanes
          @distanceFromCenter[lane.index] = lane.distanceFromCenter

      getDistances: ({startLaneIndex, endLaneIndex}) ->
        startDistance = @distanceFromCenter[startLaneIndex]
        endDistance = @distanceFromCenter[endLaneIndex]

        startDistance: startDistance
        endDistance: endDistance
        totalDistance: Math.abs startDistance - endDistance
        isSwitch: startLaneIndex isnt endLaneIndex


    ##################################
    # CarLane
    ##################################
    class CarLane
      constructor: () ->
        @laneAtIndex = []
        @lowestIndex = null

      at: (position) -> @atIndex race.normalizedPieceIndex position
      isLowerThanLowestIndex: (index) -> not @lowestIndex? or index < @lowestIndex

      atIndex: (index) ->
