[plm] 01/13: re-enable scala now that Scala 2.11 is in Debian

Martin Quinson mquinson at moszumanska.debian.org
Sat Jan 2 21:09:10 UTC 2016


This is an automated email from the git hooks/post-receive script.

mquinson pushed a commit to branch master
in repository plm.

commit fbccdfc4c7394baf1020ff096a96776e83401ab9
Author: Martin Quinson <martin.quinson at loria.fr>
Date:   Fri Jan 1 11:47:57 2016 +0100

    re-enable scala now that Scala 2.11 is in Debian
---
 debian/changelog        |    7 +
 debian/control          |   13 +-
 debian/patches/no-scala | 2660 -----------------------------------------------
 debian/patches/series   |    1 -
 4 files changed, 12 insertions(+), 2669 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 6e1555e..8c3aa8f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+plm (2.4.11+repack-3) UNRELEASED; urgency=medium
+
+  * Enable scala teaching, now that Scala 2.11 is in Debian 
+    (Fix: #809482) Thanks Rogério Brito for the reminder.
+
+ -- Martin Quinson <mquinson at debian.org>  Fri, 01 Jan 2016 11:41:48 +0100
+
 plm (2.4.11+repack-2) unstable; urgency=medium
 
   * Specify to jh_build that javac will encounter UTF-8 files 
diff --git a/debian/control b/debian/control
index f3f66c0..d8b1be0 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,7 @@ Section: java
 Priority: extra
 Maintainer: Martin Quinson <mquinson at debian.org>
 Build-Depends: debhelper (>> 8), javahelper (>= 0.32), ant, quilt
-Build-Depends-Indep: openjdk-7-jdk, libmiglayout-java, librsyntaxtextarea-java,
+Build-Depends-Indep: openjdk-7-jdk, scala, libmiglayout-java, librsyntaxtextarea-java,
   junit4, libgettext-commons-java, libjson-simple-java, libhttpclient-java, libhttpmime-java, libjgit-java,
   jython, libgettext-ant-tasks-java, imagemagick
 Standards-Version: 3.9.6
@@ -17,11 +17,11 @@ Depends: java-wrappers, ${java:Depends}, ${misc:Depends},
   libhttpmime-java,
 Recommends: ${java:Recommends}
 Suggests: jython
-Description: Programming exerciser in Java, Python and others
+Description: Programming exerciser in Java, Python, Scala and others
  The Programmer's Learning Machine (PLM) is a free cross-platform programming
  exerciser. It lets you explore various concepts of programming through 
- over 190 interactive exercises, that you can solve in either Java or
- Python.
+ over 190 interactive exercises, that you can solve in either Java, 
+ Python or Scala.
  .
  The PLM interface and content is thoughtfully translated to English
  and French; we hope that other translations will be contributed in
@@ -40,8 +40,5 @@ Description: Programming exerciser in Java, Python and others
  .
  Other lessons are planned to explore new concepts, such as the
  backtracking, dynamic programming, object-oriented programming or the
- standard libraries of python and Java. Other programming languages
+ standard libraries of python, Scala and Java. Other programming languages
  (such as Ruby or JavaScript) may be added in the future.
- .
- The Scala language was cut of the package because the Debian version
- of that language is too ancient for the PLM.
\ No newline at end of file
diff --git a/debian/patches/no-scala b/debian/patches/no-scala
deleted file mode 100644
index 2affd88..0000000
--- a/debian/patches/no-scala
+++ /dev/null
@@ -1,2660 +0,0 @@
----
- src/lessons/lander/Main.fr.html                                                |   23 
- src/lessons/lander/Main.html                                                   |   21 
- src/lessons/lander/Main.scala                                                  |   14 
- src/lessons/lander/icon.svg                                                    |  104 ----
- src/lessons/lander/lvl1_lander_101/Lander101.fr.html                           |   49 -
- src/lessons/lander/lvl1_lander_101/Lander101.html                              |   41 -
- src/lessons/lander/lvl1_lander_101/Lander101.it.html                           |   45 -
- src/lessons/lander/lvl1_lander_101/Lander101.pt_BR.html                        |   45 -
- src/lessons/lander/lvl1_lander_101/Lander101.scala                             |   17 
- src/lessons/lander/lvl1_lander_101/Lander101Entity.java                        |   14 
- src/lessons/lander/lvl1_lander_101/Lander101Entity.py                          |   13 
- src/lessons/lander/lvl1_lander_101/ScalaLander101Entity.scala                  |   17 
- src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.fr.html          |   39 -
- src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.html             |   34 -
- src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.scala            |   19 
- src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.java       |   57 --
- src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.py         |   43 -
- src/lessons/lander/lvl2_locate_landing_zone/ScalaLocateLandingZoneEntity.scala |   54 --
- src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.fr.html                    |   41 -
- src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.html                       |   33 -
- src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.pt_BR.html                 |   37 -
- src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.scala                      |   20 
- src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.java                 |   48 -
- src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.py                   |   45 -
- src/lessons/lander/lvl3_fly_the_lander/ScalaFlyTheLanderEntity.scala           |   53 --
- src/lessons/lander/short_desc.fr.html                                          |    9 
- src/lessons/lander/short_desc.html                                             |    7 
- src/lessons/lander/universe/Configurations.scala                               |   77 ---
- src/lessons/lander/universe/DelegatingLanderWorld.fr.html                      |   48 -
- src/lessons/lander/universe/DelegatingLanderWorld.html                         |   44 -
- src/lessons/lander/universe/DelegatingLanderWorld.java                         |   71 --
- src/lessons/lander/universe/DelegatingLanderWorld.pt_BR.html                   |   43 -
- src/lessons/lander/universe/Geometry.scala                                     |   47 -
- src/lessons/lander/universe/LanderEntity.scala                                 |   59 --
- src/lessons/lander/universe/LanderWorld.scala                                  |  148 -----
- src/lessons/lander/universe/LanderWorldView.scala                              |  207 --------
- src/plm/core/lang/JVMCompiledLang.java                                         |    9 
- src/plm/core/lang/LangScala.java                                               |  247 ----------
- src/plm/core/model/Game.java                                                   |   51 --
- src/plm/core/model/lesson/ExerciseTemplated.java                               |    4 
- src/plm/core/model/lesson/ExerciseTemplatingEntity.java                        |   19 
- src/plm/core/ui/ChooseLessonDialog.java                                        |    2 
- src/plm/core/ui/JavaEditorPanel.java                                           |    2 
- src/plm/core/ui/editor/MissionEditor.java                                      |    6 
- src/plm/test/ExoTest.java                                                      |   13 
- src/plm/test/LessonTest.java                                                   |   10 
- src/plm/test/simple/test/AllSimpleExerciseTests.java                           |    2 
- src/plm/test/simple/test/ScalaSimpleExerciseTest.java                          |   52 --
- src/plm/universe/bat/BatExercise.java                                          |    2 
- src/plm/universe/bat/BatTest.java                                              |   16 
- 50 files changed, 17 insertions(+), 2104 deletions(-)
-
-Index: b/src/lessons/lander/universe/Configurations.scala
-===================================================================
---- a/src/lessons/lander/universe/Configurations.scala
-+++ /dev/null
-@@ -1,77 +0,0 @@
--package lessons.lander.universe
--
--import plm.universe.World
--
--object Configurations {
--  import NumUtil._
--
--  // helper creation functions
--
--  private case class Terrain(width: Int, height: Int, ground: List[Point])
--
--  private def makeWorld(name: String, terrain: Terrain, position: Point, speed: Point,
--      angle: Double, thrust: Int, fuel: Int) =
--    new DelegatingLanderWorld(name, terrain.width, terrain.height, terrain.ground, position, speed,
--        angle, thrust, fuel)
--
--  // helper geometric functions
--
--  private def angleToSpeed(angle: Double, speed: Double) =
--    radianToVector(gameAngleToRadian(angle)) * speed
--
--  // terrains
--
--  private val SIMPLE_TERRAIN = Terrain(
--      width = 2000,
--      height = 1000,
--      ground = List(Point(0, 100), Point(125, 414), Point(205, 271),
--          Point(348, 597), Point(460, 257), Point(534, 438), Point(637, 160),
--          Point(760, 371), Point(854, 200), Point(1468, 200), Point(1585, 440),
--          Point(1682, 280), Point(1845, 668), Point(2000, 294)))
--
--  private val CHALLENGING_TERRAIN = Terrain(
--      width = 2000,
--      height = 1000,
--      ground =  List(Point(0,260), Point(37,160), Point(160,371), Point(254,200),
--          Point(430,200), Point(535,394), Point(639,300), Point(780,300), Point(890,440),
--          Point(1082,280), Point(1245,668), Point(1400,294), Point(1580, 410), Point(1730, 360),
--          Point(1870, 560), Point(2000, 400)))
--
--  // worlds
--
--  val SIMPLE_TERRAIN_TRIVIAL_CONFIG = makeWorld(
--      name = "Simple Terrain, Simple Configuration",
--      terrain = SIMPLE_TERRAIN,
--      position = Point(1200, 700),
--      speed = Point(0, 0),
--      angle = 0.0,
--      thrust = 0,
--      fuel = 3000)
--
--  val CHALLENGING_TERRAIN_SIMPLE_CONFIG = makeWorld(
--      name = "Challenging Terrain, Simple Configuration",
--      terrain = CHALLENGING_TERRAIN,
--      position = Point(530, 600),
--      speed = Point(0, 10),
--      angle = 0,
--      thrust = 4,
--      fuel = 3000)
--
--  val SIMPLE_TERRAIN_CHALLENGING_CONFIG = makeWorld(
--      name = "Simple Terrain, Challenging Configuration",
--      terrain = SIMPLE_TERRAIN,
--      position = Point(500, 500),
--      speed = angleToSpeed(-20, 20),
--      angle = -20,
--      thrust = 3,
--      fuel = 3000)
--
--  val SIMPLE_TERRAIN_HARD_CONFIG = makeWorld(
--      name = "Simple Terrain, Hard Configuration",
--      terrain = SIMPLE_TERRAIN,
--      position = Point(1900, 900),
--      speed = angleToSpeed(90, 80),
--      angle = 90,
--      thrust = 4,
--      fuel = 3000)
--}
-\ No newline at end of file
-Index: b/src/lessons/lander/universe/Geometry.scala
-===================================================================
---- a/src/lessons/lander/universe/Geometry.scala
-+++ /dev/null
-@@ -1,47 +0,0 @@
--package lessons.lander.universe
--
--import Math.PI
--import Math.cos
--import Math.sin
--
--object NumUtil {
--  def clamp(min: Double, max: Double, value: Double): Double = {
--    if (value < min) min else if (value > max) max else value
--  }
--  def clamp(min: Int, max: Int, value: Int): Int = {
--    if (value < min) min else if (value > max) max else value
--  }
--
--  def radianToVector(angle: Double) = Point(cos(angle), sin(angle))
--  
--  def gameAngleToRadian(angle: Double) = (angle + 90) * PI / 180
--}
--
--case class Point(x: Double, y: Double) {
--  def +(p: Point): Point = new Point(x + p.x, y + p.y)
--  def -(p: Point): Point = new Point(x - p.x, y - p.y)
--  def *(l: Double): Point = new Point(x * l, y * l)
--  def /(l: Double): Point = new Point(x / l, y / l)
--  def unary_- = this * -1
--
--  def length: Double = Math.sqrt(x * x + y * y)
--  def normed = this / length
--  def dot(p: Point) = x * p.x + y * p.y
--  def cross(p: Point) = x * p.y - y * p.x
--}
--
--case class Segment(start: Point, end: Point)
--
--case class Ray(origin: Point, direction: Point) {
--  def intersects(s: Segment): Boolean = {
--    val v = s.end - s.start
--    val cross = direction.cross(v);
--    if (cross == 0) {
--      false
--    } else {
--      val f1 = (s.start - origin).cross(v) / cross
--      val f2 = (s.start - origin).cross(direction) / cross
--      f1 >= 0 && f2 >= 0 && f2 <= 1
--    }
--  }
--}
-Index: b/src/lessons/lander/universe/LanderEntity.scala
-===================================================================
---- a/src/lessons/lander/universe/LanderEntity.scala
-+++ /dev/null
-@@ -1,59 +0,0 @@
--package lessons.lander.universe
--
--import plm.universe.Entity
--import scala.collection.JavaConversions._
--
--class LanderEntity extends Entity {
--
--  private def landerWorld = getWorld().asInstanceOf[DelegatingLanderWorld].realWorld
--
--  override def command(command: String, out: java.io.BufferedWriter){
--    
--  }
--  
--  override def run() = {
--    initialize()
--    while (isFlying()) {
--      step()
--      simulateStep()
--    }
--  }
--
--  // methods to be overridden by the player
--  def initialize(): Unit = ()
--  def step(): Unit = ()
--
--  // query terrain2
--  def getGround(): java.util.List[Point] = landerWorld.ground
--
--  // query lander state
--  def getX(): Double = landerWorld.position.x
--  def getY(): Double = landerWorld.position.y
--  def getSpeedX(): Double = landerWorld.speed.x
--  def getSpeedY(): Double = landerWorld.speed.y
--  def getAngle(): Double = landerWorld.angle
--  def getThrust(): Int = landerWorld.thrust
--  def getFuel(): Int = landerWorld.fuel
--
--  def setDesiredAngle(desiredAngle: Double) {
--    landerWorld.desiredAngle = desiredAngle
--  }
--  def setDesiredThrust(desiredThrust: Int) {
--    landerWorld.desiredThrust = desiredThrust
--  }
--  
--  /* Internal commands used by the python entities to simulate the above run method */
--  def isFlying(): Boolean = (landerWorld.state == LanderWorld.State.FLYING)
--  def simulateStep() = {
--    landerWorld.simulate(0.1)
--    stepUI()
--  }
--  
--  /* BINDINGS TRANSLATION: French */
--  def getSol() = getGround()
--  def getVitesseX(): Double = getSpeedX()
--  def getVitesseY(): Double = getSpeedY()
--  def getPoussee(): Int = getThrust()
--  def setAngleDesire(desiredAngle: Double) = setDesiredAngle(desiredAngle) 
--  def setPousseeDesiree(desiredThrust: Int) = setDesiredThrust(desiredThrust)
--}
-Index: b/src/lessons/lander/universe/LanderWorld.scala
-===================================================================
---- a/src/lessons/lander/universe/LanderWorld.scala
-+++ /dev/null
-@@ -1,148 +0,0 @@
--package lessons.lander.universe
--
--import Math.PI
--
--import javax.script.ScriptEngine
--import javax.swing.ImageIcon
--import plm.core.lang.ProgrammingLanguage
--import plm.core.model.Game
--import plm.core.lang.ProgrammingLanguage
--import plm.core.ui.ResourcesCache
--import plm.universe.World
--
--object LanderWorld {
--  object State extends Enumeration {
--    val FLYING, LANDED, CRASHED, OUT = Value
--  }
--
--  private val GRAVITY = Point(0, -1) * 3.711;
--}
--
--class LanderWorld(val parent: DelegatingLanderWorld) {
--
--  import LanderWorld.State._
--  import NumUtil._
--
--  var width: Int = 0
--  var height: Int = 0
--  var ground: List[Point] = null
--  var position: Point = null
--  var speed: Point = null
--  /** Angle in degrees, 0 points north, 90 points west. */
--  var angle: Double = 0
--  var thrust: Int = 0
--  var fuel: Int = 0
--  var state = FLYING
--
--  var desiredAngle: Double = 0
--  var desiredThrust: Int = 0
--
--  parent.setDelay(10)
--  parent.addEntity(new LanderEntity())
--
--  // "inherited" methods
--
--  def getIcon = ResourcesCache.getIcon("img/world_lander.png");
--
--  def setupBindings(lang: ProgrammingLanguage, engine: ScriptEngine) {
--  		if (lang.equals(Game.PYTHON)) {
--  			engine.put("Segment", Segment.getClass())
--			engine.eval(
--			    "def isFlying():\n"+
--			    "  return entity.isFlying()\n"+
--			    "def simulateStep():\n"+
--			    "  entity.simulateStep()\n"+
--			    "def getGround():\n"+
--			    "  return [ (elm.x(), elm.y()) for elm in entity.getGround() ]\n"+
--			    "def getX():\n"+
--			    "  return entity.getX()\n"+
--			    "def getY():\n"+
--			    "  return entity.getY()\n"+
--			    "def getSpeedX():\n"+
--			    "  return entity.getSpeedX()\n"+
--			    "def getSpeedY():\n"+
--			    "  return entity.getSpeedY()\n"+
--			    "def getAngle():\n"+
--			    "  return entity.getAngle()\n"+
--			    "def setDesiredAngle(a):\n"+
--			    "  entity.setDesiredAngle(a)\n"+
--			    "def getThrust():\n"+
--			    "  return entity.getThrust()\n"+
--			    "def setDesiredThrust(t):\n"+
--			    "  entity.setDesiredThrust(t)\n"+
--			    "def getFuel():\n"+
--			    "  return entity.getFuel()\n"+
--			    "")
--  		} else {
--  			throw new RuntimeException("No binding of LanderWorld for "+lang)
--  		}
--  }
--
--  /** Returns true if both worlds have same name and same state. */
--  def winning(target: World): Boolean = state == LANDED
--
--  def diffTo(world: World): String = null
--
--  def reset(initialWorld: LanderWorld): Unit = {
--    width = initialWorld.width
--    height = initialWorld.height
--    ground = initialWorld.ground
--    position = initialWorld.position
--    speed = initialWorld.speed
--    angle = initialWorld.angle
--    thrust = initialWorld.thrust
--    fuel = initialWorld.fuel
--    state = initialWorld.state
--    desiredAngle = angle
--    desiredThrust = thrust
--  }
--
--  def getView() = new LanderWorldView(parent)
--
--  override def toString() = "scala lander world"
--
--  // simulation
--
--  def angleRadian = gameAngleToRadian(angle)
--
--  private def groundSegments = {
--    if (ground.isEmpty) List()
--    else (ground, ground.tail).zipped map (Segment(_, _))
--  }
--
--  private def flatSegments = groundSegments.filter((s) => s.start.y == s.end.y)
--
--  private def touchesSomeFlatSegment(p: Point) = flatSegments
--      .find((s) => p.x > s.start.x && p.x < s.end.x && p.y - s.start.y < 1)
--      .isDefined
--
--  private def isUnderground(p: Point) =
--    groundSegments.filter(new Ray(p, Point(0, 1)).intersects(_)).length % 2 == 1
--
--  def simulate(dt: Double) {
--    if (state == FLYING) {
--      angle = clamp(-90.0 max (angle - 5), 90.0 min (angle + 5), desiredAngle)
--      thrust = clamp(0 max (thrust - 1), 5 min (thrust + 1), desiredThrust) min fuel
--      val force = radianToVector(angleRadian) * thrust + LanderWorld.GRAVITY
--      position = position + speed * dt
--      speed = speed + force * dt
--      fuel = (fuel - thrust) max 0
--
--      lazy val underground = isUnderground(position)
--      lazy val goodConfig = speed.y.abs <= 10 && speed.x.abs <= 5 && (angleRadian - PI/2) < 1e-2
--      lazy val touchesFlat = touchesSomeFlatSegment(position)
--      lazy val outOfWorldX = position.x < 0 || position.x > width
--      lazy val outOfWorldY = position.y < 0 || position.y > height
--      lazy val outOfWorld = outOfWorldX || outOfWorldY
--
--      state =
--        if (underground) {
--          if (goodConfig && touchesFlat) LANDED
--          else CRASHED
--        } else {
--          if (outOfWorld) OUT
--          else FLYING
--        }
--    }
--  }
--}
-Index: b/src/lessons/lander/universe/LanderWorldView.scala
-===================================================================
---- a/src/lessons/lander/universe/LanderWorldView.scala
-+++ /dev/null
-@@ -1,207 +0,0 @@
--package lessons.lander.universe
--
--import plm.core.ui.WorldView
--import plm.universe.World
--import java.awt.Graphics
--import java.awt.Graphics2D
--import java.awt.RenderingHints
--import java.awt.Color
--import java.awt.geom.Rectangle2D
--import java.awt.geom.Line2D
--import java.awt.BasicStroke
--import java.awt.geom.AffineTransform
--import java.awt.geom.GeneralPath
--import java.awt.geom.Path2D
--import Math.PI
--import java.awt.geom.QuadCurve2D
--import scala.util.Random
--import java.awt.Font
--import java.awt.event.MouseListener
--import java.awt.event.MouseMotionListener
--import java.awt.event.MouseMotionAdapter
--import java.awt.event.MouseEvent
--import java.awt.event.MouseAdapter
--import java.awt.geom.Point2D
--
--object LanderWorldView {
--  private val LANDER_SHAPE = List(
--      List(Point(-2, 3), Point(-3, 4), Point(-3, 7), Point(-2, 8), Point(2, 8), Point(3, 7),
--          Point(3, 4), Point(2, 3), Point(-2, 3)),
--      List(Point(-6, 0), Point(-4, 0)),
--      List(Point(6, 0), Point(4, 0)),
--      List(Point(-5, 0), Point(-4, 2.8), Point(-2, 3)),
--      List(Point(5, 0), Point(4, 2.8), Point(2, 3)))
--
--  private val EXPLOSION_SHAPE = List(
--      Point(-4, 3), Point(-1, 2), Point(0, 4), Point(1, 2), Point(4, 2), Point(2, 0),
--      Point(3, -2), Point(0, -1), Point(-3, -3), Point(-2, 0), Point(-4, 3))
--}
--
--class LanderWorldView(delagatingWorld: DelegatingLanderWorld) extends WorldView(delagatingWorld) {
--
--  import LanderWorld.State._
--
--  private def realWorld = world.asInstanceOf[DelegatingLanderWorld].realWorld
--
--  private var mouseIn : Boolean = false
--  private var mousePos : Point = Point(0, 0)
--
--  addMouseListener(new MouseAdapter() {
--    override def mouseEntered(e: MouseEvent) {
--      mouseIn = true
--    }
--    override def mouseExited(e: MouseEvent) {
--      mouseIn = false
--      repaint()
--    }
--  })
--
--  addMouseMotionListener(new MouseMotionAdapter() {
--    override def mouseMoved(event: MouseEvent) = {
--      mousePos = Point(event.getX, event.getY)
--      repaint()
--    }
--  })
--
--  override def paintComponent(g: Graphics) = {
--    super.paintComponent(g);
--    val g2 = g.asInstanceOf[Graphics2D];
--    new Painter(g2).paint()
--  }
--
--  private class Painter(g2: Graphics2D) {
--    def paint() {
--      val initialTransform = g2.getTransform()
--      setupRendering()
--      clearWidgetBackground()
--      setupGlobalTransform()
--      clearWorldBackground()
--      drawGround()
--      drawStats(initialTransform)
--      realWorld.state match {
--        case FLYING => drawLander(drawFlame = true)
--        case LANDED => drawLander(drawFlame = false)
--        case OUT => drawQuestionMarks()
--        case CRASHED => drawExplosion()
--      }
--    }
--
--    def setupRendering() {
--      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
--    }
--
--    def clearWidgetBackground() = {
--      g2.setColor(Color.gray)
--      g2.fill(new Rectangle2D.Double(0, 0, getWidth, getHeight))
--    }
--
--    def setupGlobalTransform() = {
--      val scale = (getWidth.toDouble / realWorld.width) min (getHeight.toDouble / realWorld.height)
--      val translateX = (getWidth - realWorld.width * scale) / 2
--      val translateY = (getHeight + realWorld.height * scale) / 2
--      g2.translate(translateX, translateY)
--      g2.scale(scale, -scale)
--    }
--
--    def clearWorldBackground() = {
--      g2.setColor(Color.black);
--      g2.fill(new Rectangle2D.Double(0, 0, realWorld.width, realWorld.height));
--    }
--
--    /** Sets the line width to 1px no matter the transform, and the color to white. */
--    def resetPen() {
--      val transform = g2.getTransform();
--      val scale = (transform.getScaleX() min transform.getScaleY()).abs;
--      g2.setStroke(new BasicStroke((1 / scale).toFloat))
--      g2.setColor(Color.white)
--    }
--
--    def drawPath(path: List[Point], fill: Boolean) {
--      if (!path.isEmpty) {
--        val polyLine = new GeneralPath(Path2D.WIND_EVEN_ODD, path.length)
--        polyLine.moveTo(path.head.x, path.head.y)
--        for (point <- path.tail) {
--          polyLine.lineTo(point.x, point.y)
--        }
--        if (fill) {
--          g2.fill(polyLine)
--        } else {
--          g2.draw(polyLine)
--        }
--      }
--    }
--
--    def drawText(text: String, x: Double, y: Double) {
--      val oldTransform = g2.getTransform()
--      g2.translate(x, y)
--      g2.scale(1, -1)
--      g2.drawString(text, 0, 0)
--      g2.setTransform(oldTransform)
--    }
--
--    def drawGround() = {
--      resetPen()
--      drawPath(realWorld.ground, fill = false)
--    }
--
--    def randomScaleFactor() = 1 + Random.nextDouble() * 0.2
--
--    def drawLander(drawFlame: Boolean) = {
--      val oldTransform = g2.getTransform()
--      g2.translate(realWorld.position.x, realWorld.position.y)
--      g2.scale(6, 6)  // the lander shape is small
--      resetPen()
--      g2.rotate(realWorld.angleRadian - PI/2)
--      LanderWorldView.LANDER_SHAPE.foreach(drawPath(_, fill = false))
--      val thrust = realWorld.thrust
--      if (drawFlame && thrust > 0) {
--        val controlX = (0.4 + thrust * 0.1) * randomScaleFactor()
--        val endY = (-2 * thrust) * randomScaleFactor()
--        val controlY = (endY + 3) / 2
--        g2.draw(new QuadCurve2D.Double(-0.25, 3, -controlX, controlY, 0, endY))
--        g2.draw(new QuadCurve2D.Double(0.25, 3, controlX, controlY, 0, endY))
--      }
--      g2.setTransform(oldTransform)
--    }
--
--    def drawExplosion() = {
--      val oldTransform = g2.getTransform()
--      g2.translate(realWorld.position.x, realWorld.position.y)
--      g2.scale(15, 15)  // the explosion shape is small
--      resetPen()
--      drawPath(LanderWorldView.EXPLOSION_SHAPE, fill = true)
--      g2.setTransform(oldTransform)
--    }
--
--    def drawQuestionMarks() = {
--      val x = realWorld.position.x
--      val y = realWorld.position.y
--      val textX = if (x >= realWorld.width) realWorld.width - 100 else if (x <= 0) 5 else x
--      val textY = if (y >= realWorld.height) realWorld.height - 40 else if (y <= 0) 5 else y - 30
--      g2.setColor(Color.WHITE)
--      g2.setFont(new Font(Font.MONOSPACED, Font.BOLD, 40))
--      drawText("???", textX, textY)
--    }
--
--    def drawStats(initialTransform: AffineTransform) {
--      g2.setColor(Color.LIGHT_GRAY)
--      g2.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 30))
--      drawText(f"x: ${realWorld.position.x}%.2f", 5, realWorld.height - 30)
--      drawText(f"y: ${realWorld.position.y}%.2f", 5, realWorld.height - 2 * 30)
--      drawText(f"speed x: ${realWorld.speed.x}%.2f", 5, realWorld.height - 3 * 30)
--      drawText(f"speed y: ${realWorld.speed.y}%.2f", 5, realWorld.height - 4 * 30)
--      drawText(f"angle: ${realWorld.angle}%.2f°", 5, realWorld.height - 5 * 30)
--      drawText(f"thrust: ${realWorld.thrust}", 5, realWorld.height - 6 * 30)
--      drawText(f"fuel: ${realWorld.fuel}", 5, realWorld.height - 7 * 30)
--
--      if (mouseIn) {
--        val deltaTransform = new AffineTransform(g2.getTransform())
--        deltaTransform.invert()
--        deltaTransform.concatenate(initialTransform)
--        val coord = deltaTransform.transform(new Point2D.Double(mousePos.x, mousePos.y), null)
--        drawText(f"x: ${coord.getX.round}", realWorld.width - 130, realWorld.height - 30)
--        drawText(f"y: ${coord.getY.round}", realWorld.width - 130, realWorld.height - 2 * 30)
--      }
--    }
--  }
--}
-Index: b/src/lessons/lander/Main.fr.html
-===================================================================
---- a/src/lessons/lander/Main.fr.html
-+++ /dev/null
-@@ -1,23 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Alunisseur</h1>
--
--<p>Dans cette leçon, vous pilotez un alunisseur dans des situations de plus en
--plus complexes.</p>
--
--<p>À chaque pas de la simulation, le joueur donne des commandes contrôlant
--l'angle et la poussée du module d'alunissage.</p>
--
--<p>Idées d'exercices à ajouter à la progression proposée :</p>
--<ul>
--  <li>Un alunisseur en position verticale au dessus d'un sol plat. Le joueur ne
--peut régler que la poussée (c'est fait).</li>
--  <li>Un alunisseur en position verticale pas au dessus d'un sol plat. Le joueur
--peut régler la poussée et l'angle (c'est fait).</li>
--  <li>Un alunisseur avec un angle et une vitesse difficile, pas au dessus d'un sol
--plat. Le joueur contrôle la poussée et l'angle.</li>
--  <li>Un alunisseur avec un angle et une vitesse difficile, pas au dessus d'un sol
--plat dans une configuration difficile. Le joueur contrôle la poussée et
--l'angle.</li>
--  <li>La même chose avec du vent ?</li>
--</ul>
-Index: b/src/lessons/lander/Main.html
-===================================================================
---- a/src/lessons/lander/Main.html
-+++ /dev/null
-@@ -1,21 +0,0 @@
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Lunar Lander</h1>
--
--<p>In this lesson you pilot a lunar landing module in increasingly complex
--situations.</p>
--
--<p>At each step of the simulation, the player issues a command controlling how
--much the angle and thrust of the lander should change</p>
--
--<p>Ideas concerning the progression of exercises:</p>
--<ul>
--  <li>A lander in vertical position above flat ground, the player can only
--control thrust (done)</li>
--  <li>A lander in vertical position not above flat ground, the player control
--thrust and angle (done)</li>
--  <li>A lander with difficult angle and speed not above flat ground, the
--player control thrust and angle</li>
--  <li>A lander with difficult angle and speed not above flat ground, with
--difficult ground, the player control thrust and angle</li>
--  <li>Same with wind?</li>
--</ul>
-Index: b/src/lessons/lander/Main.scala
-===================================================================
---- a/src/lessons/lander/Main.scala
-+++ /dev/null
-@@ -1,14 +0,0 @@
--package lessons.lander
--
--import plm.core.model.lesson.Lesson
--import lessons.lander.lvl1_lander_101.Lander101
--import lessons.lander.lvl2_locate_landing_zone.LocateLandingZone
--import lessons.lander.lvl3_fly_the_lander.FlyTheLander
--
--class Main extends Lesson {
--  override def loadExercises = {
--    addExercise(new Lander101(this));
--    addExercise(new LocateLandingZone(this));
--    addExercise(new FlyTheLander(this));
--  }
--}
-Index: b/src/lessons/lander/icon.svg
-===================================================================
---- a/src/lessons/lander/icon.svg
-+++ /dev/null
-@@ -1,104 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--
--<svg
--   xmlns:dc="http://purl.org/dc/elements/1.1/"
--   xmlns:cc="http://creativecommons.org/ns#"
--   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
--   xmlns:svg="http://www.w3.org/2000/svg"
--   xmlns="http://www.w3.org/2000/svg"
--   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
--   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
--   width="64"
--   height="64"
--   id="svg2"
--   version="1.1"
--   inkscape:version="0.48.4 r9939"
--   sodipodi:docname="lander.svg"
--   inkscape:export-filename="/home/polux/projects/PLM/src/lessons/lander/lander.png"
--   inkscape:export-xdpi="90"
--   inkscape:export-ydpi="90">
--  <defs
--     id="defs4" />
--  <sodipodi:namedview
--     id="base"
--     pagecolor="#ffffff"
--     bordercolor="#666666"
--     borderopacity="1.0"
--     inkscape:pageopacity="0.0"
--     inkscape:pageshadow="2"
--     inkscape:zoom="7.9195959"
--     inkscape:cx="29.558295"
--     inkscape:cy="29.181329"
--     inkscape:document-units="px"
--     inkscape:current-layer="layer1"
--     showgrid="true"
--     inkscape:window-width="1600"
--     inkscape:window-height="883"
--     inkscape:window-x="0"
--     inkscape:window-y="17"
--     inkscape:window-maximized="0">
--    <inkscape:grid
--       type="xygrid"
--       id="grid2985"
--       empspacing="5"
--       visible="true"
--       enabled="true"
--       snapvisiblegridlinesonly="true" />
--  </sodipodi:namedview>
--  <metadata
--     id="metadata7">
--    <rdf:RDF>
--      <cc:Work
--         rdf:about="">
--        <dc:format>image/svg+xml</dc:format>
--        <dc:type
--           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
--        <dc:title></dc:title>
--      </cc:Work>
--    </rdf:RDF>
--  </metadata>
--  <g
--     inkscape:label="Layer 1"
--     inkscape:groupmode="layer"
--     id="layer1"
--     transform="translate(0,-988.36215)">
--    <g
--       id="g3008"
--       transform="translate(2,8)">
--      <path
--         sodipodi:nodetypes="ccccccccc"
--         transform="translate(0,988.36215)"
--         inkscape:connector-curvature="0"
--         id="path2987"
--         d="m 20,4 20,0 5,5 0,15 -5,5 -20,0 -5,-5 0,-15 z"
--         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
--      <path
--         sodipodi:nodetypes="ccc"
--         transform="translate(0,988.36215)"
--         inkscape:connector-curvature="0"
--         id="path2989"
--         d="M 20,29 10,30 5,44"
--         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
--      <path
--         sodipodi:nodetypes="ccc"
--         transform="translate(0,988.36215)"
--         inkscape:connector-curvature="0"
--         id="path2993"
--         d="m 40,29 10,1 5,14"
--         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
--      <path
--         transform="translate(0,988.36215)"
--         inkscape:connector-curvature="0"
--         id="path3004"
--         d="m 0,44 10,0"
--         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
--      <path
--         transform="translate(0,988.36215)"
--         inkscape:connector-curvature="0"
--         id="path3006"
--         d="m 50,44 10,0"
--         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
--    </g>
--  </g>
--</svg>
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101.fr.html
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101.fr.html
-+++ /dev/null
-@@ -1,49 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Se poser pour les nuls</h1>
--
--<p>Bravo ! Vous avez gagné dans une boîte de céréales un voyage (aller simple)
--pour Mars. La NASA vous a même fourni un module d'excursion lunaire pour
--l'occasion, et c'est donc avec ce véhicule que vous voyagerez.</p>
--
--<p>Avant le décollage, vous devez vous entraîner sur simulateur aux bases de
--l'alunissage. Si tout se passe comme prévu, vous ne devriez pas avoir à
--voler en mode manuel, mais mieux vaut prévenir que guérir, comme ils disent.</p>
--
--<p>Votre mission est de <b>poser le module avec une vitesse verticale
--inférieure à 10 m/s</b>. Il y a deux façons d'influer sur la trajectoire du
--module : en modifiant son angle, ou en réglant la poussée de son
--moteur. Dans cette simulation, nous ne nous intéressons qu'à la poussée,
--exprimée en m/s².</p>
--
--<p>Vous devez écrire le [!python]corps de la fonction <code>step()</code>, qui
--sera appelée[/!][!scala|java|c]code qui sera appellé[/!] tous les dixièmes
--de seconde pendant la simulation. Il faut ajuster la poussée du moteur en
--utilisant la fonction <code>[!java]void [/!]setPousseeDesiree([!java]int
--[/!]poussee[!scala]:Integer[/!])</code> où <code>poussee</code> est un
--entier entre 0 et 4 (représentant une poussée entre 0 m/s² et 4 m/s²). Vous
--ne pouvez incrémenter ou décrémenter la poussée que de 1 entre deux pas de
--la simulation. Ainsi, si la poussée du moteur est actuellement de 2 et que
--vous demandez 4, vous n'aurez que 3 à la prochaine étape. Si vous demandez
--une valeur inférieure à 0 (ou supérieure à 4), tout se passera comme si vous
--aviez demandé 0 (ou 4).</p>
--
--<p>Afin de prendre des décisions informées, vous pouvez demander des
--informations sur l'état actuel du module. Dans cette simulation, vous ne
--serez probablement intéressé que par sa position verticale (accessible grâce
--à <code>[!java]double [/!]getY()[!scala]:Double[/!]</code>) et sa vitesse
--verticale (accessible grâce à <code>[!java]double
--[/!]getVitesseY()[!scala]:Double[/!]</code>). Vous pouvez également demander
--la poussée actuelle du moteur (avec <code>[!java]int
--[/!]getPoussee()[!scala]:Integer[/!]</code>) si vous avez oublié ce que vous
--avez demandé. Rappelez vous que la gravité martienne est de 3.711 m/s², cela
--peut vous être utile.</p>
--
--<p>Une dernière chose : le module est plutôt petit, et vous n'avez pas tant de
--carburant que cela. À chaque pas de simulation, il consomme autant d'unité
--de carburant que la poussée actuelle du moteur. Si vous tombez en panne
--sèche, vous serez en chute libre alors attention ! Vous pouvez consulter le
--niveau du réservoir avec <code>[!java]int
--[/!]getFuel()[!scala]:Integer[/!]</code>.</p>
--
--<p>Bon courage !</p>
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101.html
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101.html
-+++ /dev/null
-@@ -1,41 +0,0 @@
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Lander 101</h1>
--
--<p>Congratulations! You won a (one-way) trip to Mars in a cereal box. NASA was
--kind enough to donate the Lunar Excursion Module for this mission, so
--that's what you'll be flying.</p>
--
--<p>Before you take off, you must go through some basic landing simulation. You
--shouldn't have to fly the lander if all goes as planned but, as they say,
--"better safe than sorry".</p>
--
--<p>Your mission is to <b>land the lander with a vertical speed of at most 10
--m/s.</b> There are two ways you can influence the lander's course: by adjusting
--its angle or by adjusting its thrust. In this simulation we only care about
--adjusting the thrust, expressed in m/s².</p>
--
--<p>The [!python]<code>step()</code> function[/!][!scala|java|c]code[/!] that you 
--should write now will be called every 0.1 second during the simulation. It should 
--set the desired thrust of the next simulation step, by calling 
--<code>[!java]void [/!]setDesiredThrust([!java]int [/!]desiredThrust[!scala]:Integer[/!])</code> 
--where <code>desiredThrust</code> is some integer between 0 and 4 (that is, a thrust 
--between 0 m/s² and 4 m/s²). You can only increment or decrement the thrust by 1 
--between two simulation steps, so if the current thrust is 2 and you ask for 4, 
--you'll only get 3 in the next step. If you ask for less than 0 (resp. more than 4), 
--everything will be as if you had asked for 0 (resp. 4).</p>
--
--<p>In order to take informed decisions, you can query the lander's state. In
--this simulation you'll probably be interested in its vertical position:
--<code>[!java]double [/!]getY()[!scala]:Double[/!]</code>, and its vertical speed: 
--<code>[!java]double [/!]getSpeedY()[!scala]:Double[/!]</code>. You can also ask for 
--the thrust via <code>[!java]int [/!]getThrust()[!scala]:Integer[/!]</code> in case 
--you don't remember what you asked for. Remember that Mars' gravity is 3.711 m/s², 
--it might come in handy.</p>
--
--<p>One last thing: the lander is pretty small so you don't have much fuel. At
--each step of the simulation the lander consumes as many fuel units as the
--current thrust. Once you run out of fuel you're in free fall so beware! You can
--consult the remaining amount of available fuel units using 
--<code>[!java]int [/!]getFuel()[!scala]:Integer[/!]</code>.</p>
--
--<p>Good luck!</p>
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101.it.html
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101.it.html
-+++ /dev/null
-@@ -1,45 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Lander 101</h1>
--
--<p>Congratulations! You won a (one-way) trip to Mars in a cereal box. NASA was
--kind enough to donate the Lunar Excursion Module for this mission, so that's
--what you'll be flying.</p>
--
--<p>Before you take off, you must go through some basic landing simulation. You
--shouldn't have to fly the lander if all goes as planned but, as they say,
--"better safe than sorry".</p>
--
--<p>Your mission is to <b>land the lander with a vertical speed of at most 10
--m/s.</b> There are two ways you can influence the lander's course: by
--adjusting its angle or by adjusting its thrust. In this simulation we only
--care about adjusting the thrust, expressed in m/s².</p>
--
--<p>The [!python]<code>step()</code> function[/!][!scala|java|c]code[/!] that
--you should write now will be called every 0.1 second during the
--simulation. It should set the desired thrust of the next simulation step, by
--calling <code>[!java]void [/!]setDesiredThrust([!java]int
--[/!]desiredThrust[!scala]:Integer[/!])</code> where
--<code>desiredThrust</code> is some integer between 0 and 4 (that is, a
--thrust between 0 m/s² and 4 m/s²). You can only increment or decrement the
--thrust by 1 between two simulation steps, so if the current thrust is 2 and
--you ask for 4, you'll only get 3 in the next step. If you ask for less than
--0 (resp. more than 4), everything will be as if you had asked for 0
--(resp. 4).</p>
--
--<p>In order to take informed decisions, you can query the lander's state. In
--this simulation you'll probably be interested in its vertical position:
--<code>[!java]double [/!]getY()[!scala]:Double[/!]</code>, and its vertical
--speed: <code>[!java]double [/!]getSpeedY()[!scala]:Double[/!]</code>. You
--can also ask for the thrust via <code>[!java]int
--[/!]getThrust()[!scala]:Integer[/!]</code> in case you don't remember what
--you asked for. Remember that Mars' gravity is 3.711 m/s², it might come in
--handy.</p>
--
--<p>One last thing: the lander is pretty small so you don't have much fuel. At
--each step of the simulation the lander consumes as many fuel units as the
--current thrust. Once you run out of fuel you're in free fall so beware! You
--can consult the remaining amount of available fuel units using
--<code>[!java]int [/!]getFuel()[!scala]:Integer[/!]</code>.</p>
--
--<p>Buona fortuna!</p>
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101.pt_BR.html
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101.pt_BR.html
-+++ /dev/null
-@@ -1,45 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Lander 101</h1>
--
--<p>Congratulations! You won a (one-way) trip to Mars in a cereal box. NASA was
--kind enough to donate the Lunar Excursion Module for this mission, so that's
--what you'll be flying.</p>
--
--<p>Before you take off, you must go through some basic landing simulation. You
--shouldn't have to fly the lander if all goes as planned but, as they say,
--"better safe than sorry".</p>
--
--<p>Your mission is to <b>land the lander with a vertical speed of at most 10
--m/s.</b> There are two ways you can influence the lander's course: by
--adjusting its angle or by adjusting its thrust. In this simulation we only
--care about adjusting the thrust, expressed in m/s².</p>
--
--<p>The [!python]<code>step()</code> function[/!][!scala|java|c]code[/!] that
--you should write now will be called every 0.1 second during the
--simulation. It should set the desired thrust of the next simulation step, by
--calling <code>[!java]void [/!]setDesiredThrust([!java]int
--[/!]desiredThrust[!scala]:Integer[/!])</code> where
--<code>desiredThrust</code> is some integer between 0 and 4 (that is, a
--thrust between 0 m/s² and 4 m/s²). You can only increment or decrement the
--thrust by 1 between two simulation steps, so if the current thrust is 2 and
--you ask for 4, you'll only get 3 in the next step. If you ask for less than
--0 (resp. more than 4), everything will be as if you had asked for 0
--(resp. 4).</p>
--
--<p>In order to take informed decisions, you can query the lander's state. In
--this simulation you'll probably be interested in its vertical position:
--<code>[!java]double [/!]getY()[!scala]:Double[/!]</code>, and its vertical
--speed: <code>[!java]double [/!]getSpeedY()[!scala]:Double[/!]</code>. You
--can also ask for the thrust via <code>[!java]int
--[/!]getThrust()[!scala]:Integer[/!]</code> in case you don't remember what
--you asked for. Remember that Mars' gravity is 3.711 m/s², it might come in
--handy.</p>
--
--<p>One last thing: the lander is pretty small so you don't have much fuel. At
--each step of the simulation the lander consumes as many fuel units as the
--current thrust. Once you run out of fuel you're in free fall so beware! You
--can consult the remaining amount of available fuel units using
--<code>[!java]int [/!]getFuel()[!scala]:Integer[/!]</code>.</p>
--
--<p>Boa Sorte!</p>
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101.scala
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101.scala
-+++ /dev/null
-@@ -1,17 +0,0 @@
--package lessons.lander.lvl1_lander_101
--
--import plm.core.model.lesson.ExerciseTemplated
--import plm.core.model.lesson.Lesson
--import lessons.lander.universe.DelegatingLanderWorld
--import lessons.lander.universe.Point
--import lessons.lander.universe.LanderEntity
--import lessons.lander.universe.Configurations._
--import Math.PI
--import scala.collection.JavaConversions._
--import lessons.lander.universe.LanderWorld
--import plm.universe.World
--
--class Lander101(lesson: Lesson) extends ExerciseTemplated(lesson, null) {
--  tabName = "Lander"
--  setup(SIMPLE_TERRAIN_TRIVIAL_CONFIG)
--}
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101Entity.java
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101Entity.java
-+++ /dev/null
-@@ -1,14 +0,0 @@
--package lessons.lander.lvl1_lander_101;
--
--import lessons.lander.universe.LanderEntity;
--
--public class Lander101Entity extends LanderEntity {
--  @Override
--  public void step() {
--    /* BEGIN TEMPLATE */
--    /* BEGIN SOLUTION */
--    setDesiredThrust(getSpeedY() < -9 ? 4 : 3);
--    /* END SOLUTION */
--    /* END TEMPLATE */
--  }
--}
-Index: b/src/lessons/lander/lvl1_lander_101/Lander101Entity.py
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/Lander101Entity.py
-+++ /dev/null
-@@ -1,13 +0,0 @@
--# BEGIN TEMPLATE
--def step():
--# BEGIN SOLUTION
--    if getSpeedY() < -9:
--        setDesiredThrust(4)
--    else:
--        setDesiredThrust(3)
--# END SOLUTION
--# END TEMPLATE 
--
--while isFlying():
--  step()
--  simulateStep()
-Index: b/src/lessons/lander/lvl1_lander_101/ScalaLander101Entity.scala
-===================================================================
---- a/src/lessons/lander/lvl1_lander_101/ScalaLander101Entity.scala
-+++ /dev/null
-@@ -1,17 +0,0 @@
--package lessons.lander.lvl1_lander_101;
--
--import lessons.lander.universe._;
--
--class ScalaLander101Entity extends LanderEntity {
--	override def step() {
--		/* BEGIN TEMPLATE */
--		/* BEGIN SOLUTION */
--		if (getSpeedY() < -9) {
--			setDesiredThrust(4)
--		} else {
--			setDesiredThrust(3);
--		}
--		/* END SOLUTION */
--		/* END TEMPLATE */
--	}
--}
-Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.fr.html
-===================================================================
---- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.fr.html
-+++ /dev/null
-@@ -1,39 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h2>Repérer une zone plate</h2>
--
--<p>Après 200 jours de voyage intersidéral à manger des céréales, vous êtes
--enfin parvenu à la planète rouge. Il est enfin temps de se poser !</p>
--
--<p>Le module est en pilote automatique, et vous n'avez qu'à regarder autour de
--vous pour sélectionner une zone d'alunissage. Vous devez vous poser sur
--<b>une zone plate</b> si vous ne voulez pas vous scratcher. Vous indiquez au
--pilote automatique où se poser en modifiant la fonction
--<code>getLandingZone</code> de façon à ce qu'elle retourne [!java|scala]un
--Segment représentant la zone de votre choix.
--
--<p>Un Segment est composé de deux <code>Point</code>s, chacun composé de deux
--doubles. On construit un nouveau segment de la façon suivante :
--<code>Segment([!java]Point [/!]debut[!scala]:Point[/!], [!java]Point
--[/!]fin[!scala]:Point[/!])</code>. Pour créer de nouveaux points, il faut
--utiliser le constructeur <code>Point([!java]double [/!]x[!scala]:Double[/!],
--[!java]double [/!]y[!scala]:Double[/!])</code>. Les coordonnées d'un point
--sont accessibles grâce à ses méthodes <code>[!java]double
--[/!]x()[!scala]:Double[/!]</code> et <code>[!java]double
--[/!]y()[!scala]:Double[/!]</code>.</p>[/!] [!python]tuple de deux coordonnées X délimitant la zone de votre
--choix.[/!]
--
--<p>Pour déterminer la zone cible, vous devez appeler
--<code>[!java]List<Point> [/!]getSol()[!scala]:List[Point][/!]</code>,
--qui retourne les points qui composent la surface sous la forme d'une list de
--[!java|scala]<code>Point</code>[/!] [!python]tuples (x,y)[/!].</p>
--
--<p>Une dernière chose : votre fonction doit retourner une zone valide dans
--toutes les situations, pas seulement celle que l'on voit en ce moment. C'est
--que votre code sera utilisé dans ce cas, mais également dans la
--configuration que nous avions dans l'exercice précédent. Comme d'habitude,
--vous pouvez voir les autres mondes en les sélectionnant dans le combobox au
--dessus de la vue du monde.</p>
--
--<p>Bon alunissage ! N'oubliez pas de mettre votre combinaison spatiale en
--sortant.</p>
-Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.html
-===================================================================
---- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.html
-+++ /dev/null
-@@ -1,34 +0,0 @@
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h2>Locate a Landing Zone</h2>
--
--<p>After 200 days of traveling space and eating cereals you finally reach
--Mars. Time to land at last!</p>
--
--<p>The lander is on autopilot and all you have to do is look around and tell it
--where to land. The lander must <b>land on a flat zone</b> it you want to remain
--in one piece. You indicate the lander where to land by modifying the
--<code>getLandingZone</code> function so that it returns a 
--[!java|scala]<code>Segment</code> representing the zone of your choice.
--
--<p>A segment is composed of two <code>Point</code>s, each of them composed of
--two <code>double</code>s. A segment is built via the 
--<code>Segment([!java]Point [/!]start[!scala]:Point[/!], [!java]Point [/!]end[!scala]:Point[/!])</code> constructor. 
--A point is built via the <code>Point([!java]double [/!]x[!scala]:Double[/!], [!java]double [/!]y[!scala]:Double[/!])</code> constructor. A point's coordinates are accessible via its
--<code>[!java]double [/!]x()[!scala]:Double[/!]</code> and
--<code>[!java]double [/!]y()[!scala]:Double[/!]</code> methods.</p>[/!]
--
--[!python]tuple of two X coordinates representing the zone of your choice.[/!]
--
--<p>In order to determine which zone to return, you'll need to call
--<code>[!java]List<Point> [/!]getGround()[!scala]List[Point][/!]</code>, which returns 
--the vertices of the ground's profile as a list of 
--[!java|scala]<code>Point</code>[/!] [!python]tuples (x,y)[/!].</p>
--
--<p>One more thing: your function should return a valid flat zone in any kind of
--situation, not just for the currently visualized one. That's because it will
--be not only tested against that world, but also against the one we had in the
--previous exercise. As usual, you can see the other existing worlds with the
--appropriate combobox.</p>
--
--<p>Have a safe landing! Don't forget to put on your space suit on your way
--out.</p>
-Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.scala
-===================================================================
---- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.scala
-+++ /dev/null
-@@ -1,19 +0,0 @@
--package lessons.lander.lvl2_locate_landing_zone
--
--import plm.core.model.lesson.ExerciseTemplated
--import plm.core.model.lesson.Lesson
--import lessons.lander.universe.DelegatingLanderWorld
--import lessons.lander.universe.Point
--import lessons.lander.universe.LanderEntity
--import lessons.lander.universe.Configurations._
--import Math.PI
--import scala.collection.JavaConversions._
--import lessons.lander.universe.LanderWorld
--import plm.universe.World
--
--class LocateLandingZone(lesson: Lesson) extends ExerciseTemplated(lesson, null) {
--  tabName = "Lander"
--  setup(Array(
--      CHALLENGING_TERRAIN_SIMPLE_CONFIG,
--      SIMPLE_TERRAIN_TRIVIAL_CONFIG))
--}
-Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.java
-===================================================================
---- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.java
-+++ /dev/null
-@@ -1,57 +0,0 @@
--package lessons.lander.lvl2_locate_landing_zone;
--
--import java.util.Iterator;
--
--import lessons.lander.universe.LanderEntity;
--import lessons.lander.universe.Point;
--import lessons.lander.universe.Segment;
--
--public class LocateLandingZoneEntity extends LanderEntity {
--  /* BEGIN TEMPLATE */
--  public Segment getLandingZone() {
--    /* return new Segment(new Point(0,0), new Point(0,0)); */
--    /* BEGIN SOLUTION */
--    Iterator<Point> ground = getGround().iterator();
--    Point lastPoint = ground.next();
--    while (ground.hasNext()) {
--      Point point = ground.next();
--      if (lastPoint.y() == point.y()) {
--        return new Segment(lastPoint, point);
--      }
--      lastPoint = point;
--    }
--    return null;
--    /* END SOLUTION */
--  }
--  /* END TEMPLATE */
--
--  /* BEGIN HIDDEN */
--  double targetStart = 0;
--  double targetEnd = 0;
--
--  @Override
--  public void initialize() {
--    Segment landingZone = getLandingZone();
--    targetStart = landingZone.start().x();
--    targetEnd = landingZone.end().x();
--  }
--
--  @Override
--  public void step() {
--    if (getX() < targetStart) {
--      setDesiredAngle(-30);
--    } else if (getX() > targetEnd) {
--      setDesiredAngle(30);
--    } else {
--      if (getSpeedX() > 5) {
--        setDesiredAngle(25);
--      } else if (getSpeedX() < -5) {
--        setDesiredAngle(-25);
--      } else {
--        setDesiredAngle(0);
--      }
--    }
--    setDesiredThrust(getSpeedY() < -9 ? 4 : 3);
--  }
--  /* END HIDDEN */
--}
-Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.py
-===================================================================
---- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.py
-+++ /dev/null
-@@ -1,43 +0,0 @@
--# BEGIN TEMPLATE
--def getLandingZone():
--    # BEGIN SOLUTION
--    lastPoint = getGround()[0]
--    for point in getGround():
--        if (point != lastPoint):
--            if lastPoint[1] == point[1]:
--                return (lastPoint[0],point[0])
--        lastPoint = point
--    # END SOLUTION
--# END TEMPLATE 
--
--targetStart = 0;
--targetEnd = 0;
--
--def initialize():
--    global targetStart
--    global targetEnd
--    (targetStart, targetEnd) = getLandingZone()
--    if (targetStart > targetEnd):
--        print ("Your starting point is after your ending point ("+str(targetStart)+">"+str(targetEnd)+"). Bad things will happen")
--
--def step():
--    if (getX() < targetStart):
--        setDesiredAngle(-30)
--    elif (getX() > targetEnd):
--        setDesiredAngle(30)
--    elif (getSpeedX() > 5):
--        setDesiredAngle(25)
--    elif (getSpeedX() < -5):
--        setDesiredAngle(-25)
--    else:
--        setDesiredAngle(0);
--        
--    if (getSpeedY() <-9):
--        setDesiredThrust(4)
--    else:
--        setDesiredThrust(3)
--
--initialize()
--while isFlying():
--  step()
--  simulateStep()
-Index: b/src/lessons/lander/lvl2_locate_landing_zone/ScalaLocateLandingZoneEntity.scala
-===================================================================
---- a/src/lessons/lander/lvl2_locate_landing_zone/ScalaLocateLandingZoneEntity.scala
-+++ /dev/null
-@@ -1,54 +0,0 @@
--package lessons.lander.lvl2_locate_landing_zone;
--
--import java.util.Iterator;
--import scala.collection.JavaConversions._
--
--import lessons.lander.universe._;
--
--class ScalaLocateLandingZoneEntity extends LanderEntity {
--  /* BEGIN TEMPLATE */
--  def getLandingZone():Segment = {
--    /* BEGIN SOLUTION */
--    var lastPoint:Point = getGround.get(0);
--    for (point <- getGround()) {
--      if (point != lastPoint) { // Avoid the loop when point is on the first element
--        if (point.y == lastPoint.y)
--          return new Segment(lastPoint,point)
--      }
--      lastPoint = point
--    }
--    return null;
--    /* END SOLUTION */
--  }
--  /* END TEMPLATE */
--
--  var targetStart = 0.0;
--  var targetEnd = 0.0;
--
--  override def initialize() {
--    var landingZone = getLandingZone();
--    targetStart = landingZone.start.x;
--    targetEnd = landingZone.end.x;
--  }
--
--  override def step() {
--    if (getX() < targetStart) {
--      setDesiredAngle(-30);
--    } else if (getX() > targetEnd) {
--      setDesiredAngle(30);
--    } else {
--      if (getSpeedX() > 5) {
--        setDesiredAngle(25);
--      } else if (getSpeedX() < -5) {
--        setDesiredAngle(-25);
--      } else {
--        setDesiredAngle(0);
--      }
--    }
--    
--    if (getSpeedY() < -9)
--      setDesiredThrust(4)
--    else
--      setDesiredThrust(3)
--  }
--}
-Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.fr.html
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.fr.html
-+++ /dev/null
-@@ -1,41 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Aux commandes du module</h1>
--
--<p>Après 30 jours à regarder des cailloux en mangeant des céréales, vous
--décidez qu'il est temps d'aller explorer d'autres coins de cette planète.</p>
--
--<p>Vous volez un moment, avant de réaliser soudain que vous êtes presque à
--court d'essence. Le pilote automatique est malheureusement inutile dans ce
--genre de situation périlleuse, et vous allez devoir vous poser en mode
--manuel. Votre mission et de vous <b>poser sur une zone plate, avec une
--vitesse verticale inférieure à 10 m/s, une vitesse horizontale inférieure à
--5 m/s et un angle de 0°</b>.</p>
--
--<p>Vous devez définir deux fonctions : <code>[!java]void
--[/!]initialize()</code> et <code>[!java]void
--[/!]step()</code>. <code>initialize()</code> est appelée au moment où l'on
--appuie sur le bouton «Exécuter». Vous pouvez l'utiliser pour choisir une
--zone plate. Comme avant, <code>step()</code> est appelée tous les dixièmes
--de seconde pour vous permettre d'ajuster la poussée (avec la fonction
--<code>[!java]void [/!]setPousseedesiree([!java]int
--[/!]poussee[!scala]:Integer[/!])</code>). Vous pouvez également contrôler
--l'angle du module avec la fonction <code>[!java]void
--[/!]setAngleDesire([!java]double [/!]angle[!scala]:Double[/!])</code>. Un
--angle de O° dénote une position verticale, avec le sommet du module dirigé
--vers le haut. C'est l'angle avec lequel vous devez vous poser. Un angle
--positif indique que le module penche vers la gauche tandis qu'un angle
--négatif indique au contraire qu'il penche à droite. Il est impossible de se
--pencher à plus de ±90°, et on ne peut pas pencher le module de plus de ±5°
--en une fois.</p>
--
--<p>Comme dans les exercices précédents, <code>[!java]List<Point>
--[/!]getSol()[!scala]:List[Point][/!]</code> retourne les points qui
--composent l'horizon. Le manuel de référence de votre module est disponible
--dans la documentation (Aide/À propos de ce monde).</p>
--
--<p>Comme d'habitude, votre programme doit se poser sans heurt dans toutes les
--situations que nous avons rencontré jusqu'à présent, ainsi que dans ce
--nouveau cas.</p>
--
--<p>Bonne chance. Essayez de ne pas vous scratcher ;)</p>
-Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.html
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.html
-+++ /dev/null
-@@ -1,33 +0,0 @@
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Fly the Lander!</h1>
--
--<p>After 30 days of staring at rocks and eating cereals you decide it's time to
--go explore other parts of the planet.</p>
--
--<p>You fly for a while and suddenly realize you're almost out of fuel.
--Unfortunately you're in a delicate situation and the autopilot is helpless.
--You will have to pilot the lander yourself. Your mission is to <b>land the
--lander on a flat zone with a vertical speed less than 10 m/s, an horizontal
--speed less than 5 m/s and an angle of 0°.</b></p>
--
--<p>You must define two functions: <code>[!java]void [/!]initialize()</code> and 
--<code>[!java]void [/!]step()</code>. <code>initialize()</code> is called once just 
--after you press "Run". You can use it to chose some flat zone. As before, 
--<code>step()</code> is called every 0.1 second and is used for adjusting the 
--lander's thrust and angle. As in the first exercise the lander's thrust is adjusted 
--via <code>[!java]void [/!]setDesiredThrust([!java]int [/!]desiredThrust[!scala]:Integer[/!])</code>. 
--But you can also control its angle via 
--<code>[!java]void [/!]setDesiredAngle([!java]double [/!]desiredAngle[!scala]:Double[/!])</code>. 
--An angle of 0° denotes a vertical position where the "head" of the lander points up. 
--This is the angle you must land with. A positive angle denotes a left-leaning lander, 
--a negative angle a right-leaning one. You cannot lean more than by ±90°, and the angle can vary by
--at most ±5° in one step.</p>
--
--<p>As in the previous exercise, <code>[!java]List<Point> [/!]getGround()[!scala]:List[Point][/!]</code> returns
--the vertices of the ground's profile from left to right. 
--Please refer to the documentation (Help/About this world) for a reference manual of your lunar lander.</p>
--
--<p>As before, your program must safely land the lander in all the situations
--encountered so far in addition to this new one.</p>
--
--<p>Good luck, try not to crash!</p>
-Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.pt_BR.html
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.pt_BR.html
-+++ /dev/null
-@@ -1,37 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h1>Fly the Lander!</h1>
--
--<p>After 30 days of staring at rocks and eating cereals you decide it's time to
--go explore other parts of the planet.</p>
--
--<p>You fly for a while and suddenly realize you're almost out of fuel.
--Unfortunately you're in a delicate situation and the autopilot is helpless.
--You will have to pilot the lander yourself. Your mission is to <b>land the
--lander on a flat zone with a vertical speed less than 10 m/s, an horizontal
--speed less than 5 m/s and an angle of 0°.</b></p>
--
--<p>You must define two functions: <code>[!java]void [/!]initialize()</code> and
--<code>[!java]void [/!]step()</code>. <code>initialize()</code> is called
--once just after you press "Run". You can use it to chose some flat zone. As
--before, <code>step()</code> is called every 0.1 second and is used for
--adjusting the lander's thrust and angle. As in the first exercise the
--lander's thrust is adjusted via <code>[!java]void
--[/!]setDesiredThrust([!java]int
--[/!]desiredThrust[!scala]:Integer[/!])</code>.  But you can also control its
--angle via <code>[!java]void [/!]setDesiredAngle([!java]double
--[/!]desiredAngle[!scala]:Double[/!])</code>.  An angle of 0° denotes a
--vertical position where the "head" of the lander points up.  This is the
--angle you must land with. A positive angle denotes a left-leaning lander, a
--negative angle a right-leaning one. You cannot lean more than by ±90°, and
--the angle can vary by at most ±5° in one step.</p>
--
--<p>As in the previous exercise, <code>[!java]List<Point>
--[/!]getGround()[!scala]:List[Point][/!]</code> returns the vertices of the
--ground's profile from left to right.  Please refer to the documentation
--(Help/About this world) for a reference manual of your lunar lander.</p>
--
--<p>As before, your program must safely land the lander in all the situations
--encountered so far in addition to this new one.</p>
--
--<p>Boa sorte, tente não cair!</p>
-Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.scala
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.scala
-+++ /dev/null
-@@ -1,20 +0,0 @@
--package lessons.lander.lvl3_fly_the_lander
--
--import plm.core.model.lesson.ExerciseTemplated
--import plm.core.model.lesson.Lesson
--import lessons.lander.universe.DelegatingLanderWorld
--import lessons.lander.universe.Point
--import lessons.lander.universe.LanderEntity
--import lessons.lander.universe.Configurations._
--import Math.PI
--import scala.collection.JavaConversions._
--import lessons.lander.universe.LanderWorld
--import plm.universe.World
--
--class FlyTheLander(lesson: Lesson) extends ExerciseTemplated(lesson, null) {
--  tabName = "Lander"
--  setup(Array(
--      SIMPLE_TERRAIN_CHALLENGING_CONFIG,
--      CHALLENGING_TERRAIN_SIMPLE_CONFIG,
--      SIMPLE_TERRAIN_TRIVIAL_CONFIG))
--}
-Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.java
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.java
-+++ /dev/null
-@@ -1,48 +0,0 @@
--package lessons.lander.lvl3_fly_the_lander;
--
--import java.util.List;
--
--import lessons.lander.universe.LanderEntity;
--import lessons.lander.universe.Point;
--
--public class FlyTheLanderEntity extends LanderEntity {
--	/* BEGIN TEMPLATE */
--	/* BEGIN HIDDEN */
--	double targetStart;
--	double targetEnd;
--	/* END HIDDEN */
--	public void initialize() {
--		/* BEGIN HIDDEN */
--		List<Point> ground = getGround();
--		Point lastPoint = ground.get(0);
--		for (Point point: ground) {
--			if (point!=lastPoint && lastPoint.y() == point.y()) {
--				targetStart = lastPoint.x();
--				targetEnd = point.x();
--				return;
--			}
--			lastPoint = point;
--		}
--		/* END HIDDEN */
--	}
--
--	public void step() {
--		/* BEGIN SOLUTION */
--		if (getX() < targetStart) {
--			setDesiredAngle(-30);
--		} else if (getX() > targetEnd) {
--			setDesiredAngle(30);
--		} else {
--			if (getSpeedX() > 5) {
--				setDesiredAngle(25);
--			} else if (getSpeedX() < -5) {
--				setDesiredAngle(-25);
--			} else {
--				setDesiredAngle(0);
--			}
--		}
--		setDesiredThrust(getSpeedY() < -9 ? 4 : 3);
--		/* END SOLUTION */
--	}
--	/* END TEMPLATE */
--}
-Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.py
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.py
-+++ /dev/null
-@@ -1,45 +0,0 @@
--# BEGIN HIDDEN
--(startPos,endPos) = (0,0)
--# END HIDDEN
--
--# BEGIN TEMPLATE
--def initialize():
--    pass
--# BEGIN SOLUTION
--    global startPos
--    global endPos
--    lastPoint = getGround()[0]
--    for point in getGround():
--        if (point != lastPoint):
--            if lastPoint[1] == point[1]:
--                (startPos,endPos) = (lastPoint[0],point[0])
--        lastPoint = point
--# END SOLUTION
--
--def step():
--    pass
--# BEGIN HIDDEN
--    if (getX() < startPos):
--        setDesiredAngle(-30)
--    elif (getX() > endPos):
--        setDesiredAngle(30)
--    elif (getSpeedX() > 5):
--        setDesiredAngle(25)
--    elif (getSpeedX() < -5):
--        setDesiredAngle(-25)
--    else:
--        setDesiredAngle(0);
--        
--    if (getSpeedY() <-9):
--        setDesiredThrust(4)
--    else:
--        setDesiredThrust(3)
--
--# END HIDDEN
--
--# END TEMPLATE
--
--initialize()
--while isFlying():
--  step()
--  simulateStep()
-Index: b/src/lessons/lander/lvl3_fly_the_lander/ScalaFlyTheLanderEntity.scala
-===================================================================
---- a/src/lessons/lander/lvl3_fly_the_lander/ScalaFlyTheLanderEntity.scala
-+++ /dev/null
-@@ -1,53 +0,0 @@
--package lessons.lander.lvl3_fly_the_lander;
--
--import java.util.Iterator;
--import scala.collection.JavaConversions._
--
--import lessons.lander.universe._;
--
--class ScalaFlyTheLanderEntity extends LanderEntity {
--  /* BEGIN TEMPLATE */
--  /* BEGIN HIDDEN */
--  var targetStart=0.0
--  var targetEnd=0.0
--  /* END HIDDEN */
--  override def initialize() {
--    /* BEGIN HIDDEN */
--    var lastPoint:Point = getGround.get(0);
--    for (point <- getGround()) {
--      if (point != lastPoint) { // Avoid the loop when point is on the first element
--        if (point.y == lastPoint.y) {
--          targetStart = lastPoint.x
--          targetEnd = point.x
--        }
--      }
--      lastPoint = point
--    }
--    /* END HIDDEN */
--  }
--
--  override def step() {
--    /* BEGIN SOLUTION */
--    if (getX() < targetStart) {
--      setDesiredAngle(-30);
--    } else if (getX() > targetEnd) {
--      setDesiredAngle(30);
--    } else {
--      if (getSpeedX() > 5) {
--        setDesiredAngle(25);
--      } else if (getSpeedX() < -5) {
--        setDesiredAngle(-25);
--      } else {
--        setDesiredAngle(0);
--      }
--    }
--    
--    if (getSpeedY() < -9) {
--    	setDesiredThrust(4)
--    } else {
--    	setDesiredThrust(3);
--    }
--    /* END SOLUTION */
--  }
--  /* END TEMPLATE */
--}
-Index: b/src/lessons/lander/short_desc.fr.html
-===================================================================
---- a/src/lessons/lander/short_desc.fr.html
-+++ /dev/null
-@@ -1,9 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h3>Alunisseur</h3>
--
--<p>Dans cette leçon, vous pilotez un alunisseur dans des situations de plus en
--plus complexes.</p>
--
--<p>Vous êtes supposé maîtriser les bases de la programmation et posséder
--quelques notions de mécanique du point avant de tenter cette leçon.</p>
-Index: b/src/lessons/lander/short_desc.html
-===================================================================
---- a/src/lessons/lander/short_desc.html
-+++ /dev/null
-@@ -1,7 +0,0 @@
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h3>Lunar Lander</h3>
--
--<p>In this lesson you pilot a lunar landing module in increasingly complex
--situations.</p>
--
--<p>This lesson assumes some basic programming and physics skills.</p>
-Index: b/src/lessons/lander/universe/DelegatingLanderWorld.fr.html
-===================================================================
---- a/src/lessons/lander/universe/DelegatingLanderWorld.fr.html
-+++ /dev/null
-@@ -1,48 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h2>Alunisseur</h2>
--
--<p>Dans cet univers, vous contrôlez un module d'alunissage. À chaque pas de la
--simulation, vous avez accès à la position du module, sa vitesse, son angle
--et la poussée de son moteur. Vous devez alors décider de l'angle et de la
--poussée pour l'étape suivante. </p>
--
--<h2>Fonctions fournies</h2>
--
--<pre>[!java|c]double [/!]getX()[!scala]:Double[/!]
--[!java|c]double [/!]getY()[!scala]:Double[/!]</pre>
--Retourne la position en X et Y du module d'alunissage.
--<pre>[!java|c]double [/!]getVitesseX()[!scala]:Double[/!]
--[!java|c]double [/!]getVitesseY()[!scala]:Double[/!]</pre>
--Obtenir les vitesses horizontale et verticale du module.
--
--<pre>[!java|c]double [/!]getAngle()[!scala]:Double[/!]
--[!java|c]void [/!]setAngleDesire([!java|c]double [/!]angle[!scala]:Double[/!])</pre>
--Retourne ou fixe l'angle du module d'alunissage.<br/>
--Un angle de O° dénote une position verticale, avec le sommet du module
--dirigé vers le haut. C'est l'angle avec lequel vous devez vous poser. Un
--angle positif indique que le module penche vers la gauche tandis qu'un angle
--négatif indique au contraire qu'il penche à droite. Il est impossible de se
--pencher à plus de ±90°, et on ne peut pas pencher le module de plus de ±5°
--en une fois.
--
--<pre>[!java|c]int [/!]getPoussee()[!scala]:Int[/!]
--[!java|c]void [/!]setPousseeDesiree([!java|c]int [/!]poussée[!scala]:Int[/!])</pre>
--Retourne ou fixe la poussée du module. <br/>Vous ne pouvez incrémenter ou décrémenter la poussée que d'une unité à
--chaque fois. Si votre poussée actuelle est de 2 et que vous demandez une
--poussée de 4, vous n'obtiendrez que 3 au prochain pas de temps. Si vous
--demandez moins que 0 (ou plus que 4), tout se passera comme si vous
--demandiez 0 (ou 4).
--
--<pre>[!java|c]int [/!]getFuel()[!scala]:Int[/!]</pre>
--Obtient la quantité de fuel restant dans le réservoir. À chaque pas de
--simulation, le module consomme entre 0 et 4 unités de fuel, en fonction de
--sa poussée. Une fois que vous avez utilisé tout votre carburant, vous êtes
--en chute libre alors prenez garde !
--
--<pre>[!java]List<Point> [/!]getSol()[! scala]:List[Point][/!]</pre>
--Obtenir les points du sol de gauche à droite. [!java|scala]Vous pouvez
--retrouver les coordonnées X et Y de chaque point avec les méthodes
--correspondantes de votre point : <code>p.x()</code> et
--<code>p.y()</code>.[/!] [!python]Chaque point est un tableau de deux entiers
--représentant respectivement les coordonnées X et Y de chaque point.[/!]
-\ No newline at end of file
-Index: b/src/lessons/lander/universe/DelegatingLanderWorld.html
-===================================================================
---- a/src/lessons/lander/universe/DelegatingLanderWorld.html
-+++ /dev/null
-@@ -1,44 +0,0 @@
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h2>Lunar Lander</h2>
--
--<p>In this universe you pilot a lunar lander. At each simulation step you're
--given the lander's position, speed, angle and thrust and must issue a command
--adjusting its angle and thrust.</p>
--
--<h2>Provided functions</h2>
--
--<pre>[!java|c]double [/!]getX()[!scala]:Double[/!]
--[!java|c]double [/!]getY()[!scala]:Double[/!]</pre>
--Get the X and Y position of the lander.
--<pre>[!java|c]double [/!]getSpeedX()[!scala]:Double[/!]
--[!java|c]double [/!]getSpeedY()[!scala]:Double[/!]</pre>
--Get the horizontal and vertical speed of the lander.
--
--<pre>[!java|c]double [/!]getAngle()[!scala]:Double[/!]
--[!java|c]void [/!]setDesiredAngle([!java|c]double [/!]desiredAngle[!scala]:Double[/!])</pre>
--Get or set the angle of the lander.<br/>
--An angle of 0° denotes a vertical position where the "head" of the lander points up. 
--This is the angle you must land with. A positive angle denotes a left-leaning lander, 
--a negative angle a right-leaning one. You cannot lean more than by ±90°, and the angle can vary by
--at most ±5° in one step.
--
--<pre>[!java|c]int [/!]getThrust()[!scala]:Int[/!]
--[!java|c]void [/!]setDesiredThrust([!java|c]int [/!]thrust[!scala]:Int[/!])</pre>
--Get or set the thrust of the lander. <br/>You can only 
--increment or decrement the thrust by 1 between two simulation steps, so if the 
--current thrust is 2 and you ask for 4, you'll only get 3 in the next step. If 
--you ask for less than 0 (resp. more than 4), everything will be as if you had 
--asked for 0 (resp. 4).
--
--<pre>[!java|c]int [/!]getFuel()[!scala]:Int[/!]</pre>
--Get the remaining fuel in the lander.  At each step of the simulation the lander 
--consumes as many fuel units as the current thrust. Once you run out of fuel you're 
--in free fall so beware!
--
--<pre>[!java]List<Point> [/!]getGround()[! scala]:List[Point][/!]</pre>
--Get the vertices of the ground's profile from left to right. 
--[!java|scala]You can retrieve the X and Y coordinates of each point
--with the corresponding methods of your point: <code>p.x()</code> and
--<code>p.y()</code>.[!/]
--[!python]Each point is an array of two integers denoting respectively
--the X and Y coordinates of that point.[/!]
-\ No newline at end of file
-Index: b/src/lessons/lander/universe/DelegatingLanderWorld.java
-===================================================================
---- a/src/lessons/lander/universe/DelegatingLanderWorld.java
-+++ /dev/null
-@@ -1,71 +0,0 @@
--package lessons.lander.universe;
--
--import javax.script.ScriptEngine;
--import javax.script.ScriptException;
--import javax.swing.ImageIcon;
--
--import plm.core.lang.ProgrammingLanguage;
--import plm.core.ui.WorldView;
--import plm.universe.World;
--import scala.collection.immutable.List;
--
--public class DelegatingLanderWorld extends World {
--
--  final LanderWorld realWorld;
--
--  public DelegatingLanderWorld(String name, int width, int height,
--      List<Point> ground, Point position, Point speed, double angle, int thrust, int fuel) {
--    super(name);
--    realWorld = new LanderWorld(this);
--    realWorld.width_$eq(width);
--    realWorld.height_$eq(height);
--    realWorld.ground_$eq(ground);
--    realWorld.position_$eq(position);
--    realWorld.speed_$eq(speed);
--    realWorld.angle_$eq(angle);
--    realWorld.thrust_$eq(thrust);
--    realWorld.fuel_$eq(fuel);
--  }
--
--  public DelegatingLanderWorld(DelegatingLanderWorld world) {
--    super(world.getName());
--    realWorld = new LanderWorld(this);
--    reset(world);
--  }
--
--  @Override
--  public ImageIcon getIcon() {
--    return realWorld.getIcon();
--  }
--
--  @Override
--  public void setupBindings(ProgrammingLanguage lang, ScriptEngine engine) throws ScriptException {
--    realWorld.setupBindings(lang, engine);
--  }
--
--  @Override
--  public boolean winning(World target) {
--    return realWorld.winning(target);
--  }
--
--  @Override
--  public String diffTo(World world) {
--    return realWorld.diffTo(world);
--  }
--
--  @Override
--  public void reset(World initialWorld) {
--    realWorld.reset(((DelegatingLanderWorld) initialWorld).realWorld);
--    super.reset(initialWorld);
--  }
--
--  @Override
--  public WorldView getView() {
--    return realWorld.getView();
--  }
--
--  @Override
--  public String toString() {
--    return realWorld.toString();
--  }
--}
-Index: b/src/lessons/lander/universe/DelegatingLanderWorld.pt_BR.html
-===================================================================
---- a/src/lessons/lander/universe/DelegatingLanderWorld.pt_BR.html
-+++ /dev/null
-@@ -1,43 +0,0 @@
--
--<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
--<h2>Lunar Lander</h2>
--
--<p>In this universe you pilot a lunar lander. At each simulation step you're
--given the lander's position, speed, angle and thrust and must issue a
--command adjusting its angle and thrust.</p>
--
--<h2>Provided functions</h2>
--
--<pre>[!java|c]double [/!]getX()[!scala]:Double[/!]
--[!java|c]double [/!]getY()[!scala]:Double[/!]</pre>
--Obter (Get) as posições X e Y do "lander".
--<pre>[!java|c]double [/!]getVelocidadeX()[!scala]:Double[/!]
--[!java|c]double [/!]getVelocidadeY()[!scala]:Double[/!]</pre>
--Get the horizontal and vertical speed of the lander.
--
--<pre>[!java|c]double [/!]getÂngulo()[!scala]:Double[/!]
--[!java|c]void [/!]setÂnguloDesejado([!java|c]double [/!]ÂnguloDesejado[!scala]:Double[/!])</pre>
--Get or set the angle of the lander.<br/>
--An angle of 0° denotes a vertical position where the "head" of the lander
--points up.  This is the angle you must land with. A positive angle denotes a
--left-leaning lander, a negative angle a right-leaning one. You cannot lean
--more than by ±90°, and the angle can vary by at most ±5° in one step.
--
--<pre>[!java|c]int [/!]getImpulso()[!scala]:Int[/!]
--[!java|c]void [/!]setImpulsoDesejado([!java|c]int [/!]thrust[!scala]:Int[/!])</pre>
--Get or set the thrust of the lander. <br/>You can only increment or decrement the thrust by 1 between two simulation
--steps, so if the current thrust is 2 and you ask for 4, you'll only get 3 in
--the next step. If you ask for less than 0 (resp. more than 4), everything
--will be as if you had asked for 0 (resp. 4).
--
--<pre>[!java|c]int [/!]getCombustível()[!scala]:Int[/!]</pre>
--Get the remaining fuel in the lander.  At each step of the simulation the
--lander consumes as many fuel units as the current thrust. Once you run out
--of fuel you're in free fall so beware!
--
--<pre>[!java]List<Point> [/!]getChão()[! scala]:List[Point][/!]</pre>
--Get the vertices of the ground's profile from left to right.
--[!java|scala]You can retrieve the X and Y coordinates of each point with the
--corresponding methods of your point: <code>p.x()</code> and
--<code>p.y()</code>.[!/] [!python]Each point is an array of two integers
--denoting respectively the X and Y coordinates of that point.[/!]
-\ No newline at end of file
-Index: b/src/plm/core/ui/ChooseLessonDialog.java
-===================================================================
---- a/src/plm/core/ui/ChooseLessonDialog.java
-+++ b/src/plm/core/ui/ChooseLessonDialog.java
-@@ -78,7 +78,7 @@ public class ChooseLessonDialog extends
- 				{"lessons/welcome", "lessons/maze", "lessons/turmites", "lessons/turtleart"},
- 				{"lessons/sort/basic", "lessons/sort/dutchflag", "lessons/sort/baseball", "lessons/sort/pancake"},
- 				{"lessons/recursion/cons", "lessons/recursion", "lessons/recursion/hanoi" },
--				{"lessons/lightbot", "lessons/bat/string1", "lessons/lander" },
-+				{"lessons/lightbot", "lessons/bat/string1" },
- 		    }); 
- 	
- 
-Index: b/src/plm/test/ExoTest.java
-===================================================================
---- a/src/plm/test/ExoTest.java
-+++ b/src/plm/test/ExoTest.java
-@@ -39,7 +39,7 @@ public class ExoTest {
- 		"lessons.sort.basic", "lessons.sort.dutchflag", "lessons.sort.baseball", "lessons.sort.pancake", 
- 		"lessons.recursion.cons", "lessons.recursion", "lessons.recursion.hanoi",
- 		// "lessons.lightbot", // Well, testing this requires testing the swing directly I guess
--		"lessons.bat.string1", "lessons.lander",
-+		"lessons.bat.string1",
- 		};
- 
- 	@BeforeClass
-@@ -122,7 +122,7 @@ public class ExoTest {
- 			// For compiled languages, we mutate to the compiled entity. 
- 			// For script languages, we mutate to the correction entity.
- 			StudentOrCorrection what = StudentOrCorrection.CORRECTION;
--			if (lang == Game.JAVA || lang == Game.SCALA || lang == Game.C)
-+			if (lang == Game.JAVA || lang == Game.C)
- 				what = StudentOrCorrection.STUDENT;
- 			exo.mutateEntities(WorldKind.CURRENT, what);
- 			
-@@ -157,14 +157,7 @@ public class ExoTest {
- 	public void testJavaEntity() {
- 		testCorrectionEntity(Game.JAVA);
- 	}
--	
--	@Test(timeout=30000) // The compiler sometimes takes time to kick in 
--	public void testScalaEntity() {
--		if (!exo.getProgLanguages().contains(Game.SCALA)) 
--			fail("Exercise "+exo.getId()+" does not support scala");
--		testCorrectionEntity(Game.SCALA);
--	}
--	
-+		
- //	@Test(timeout=30000) // The compiler sometimes takes time to kick in 
- 	public void testCEntity() {
- 		if (!exo.getProgLanguages().contains(Game.C)) 
-Index: b/src/plm/test/LessonTest.java
-===================================================================
---- a/src/plm/test/LessonTest.java
-+++ b/src/plm/test/LessonTest.java
-@@ -30,7 +30,7 @@ public class LessonTest {
- 		"lessons.sort.basic", "lessons.sort.dutchflag", "lessons.sort.baseball", "lessons.sort.pancake", 
- 		"lessons.recursion.cons", "lessons.recursion", "lessons.recursion.hanoi",
- 		// "lessons.lightbot", // Well, testing this requires testing the swing directly I guess
--		"lessons.bat.string1", "lessons.lander",
-+		"lessons.bat.string1",
- 		};
- 	
- 	private String lessonName;
-@@ -82,13 +82,7 @@ public class LessonTest {
- 		Lesson lesson = loadLesson(Game.JAVA);
- 		assertTrue("An error arose while loading lesson "+lesson.getName()+"...", lesson.getLoadingOutcomeState() == LoadingOutcome.SUCCESS);
- 	}
--	
--	@Test
--	public void testScalaLesson() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
--		Lesson lesson = loadLesson(Game.SCALA);
--		assertTrue("An error arose while loading lesson "+lesson.getName()+"...", lesson.getLoadingOutcomeState() == LoadingOutcome.SUCCESS);
--	}
--	
-+		
- 	@Test
- 	public void testPythonLesson() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
- 		Lesson lesson = loadLesson(Game.PYTHON);
-Index: b/src/plm/core/lang/LangScala.java
-===================================================================
---- a/src/plm/core/lang/LangScala.java
-+++ /dev/null
-@@ -1,247 +0,0 @@
--package plm.core.lang;
--
--import java.util.HashMap;
--import java.util.LinkedList;
--import java.util.List;
--import java.util.Map;
--import java.util.Vector;
--
--import plm.core.PLMCompilerException;
--import plm.core.model.Game;
--import plm.core.model.LogWriter;
--import plm.core.model.lesson.ExecutionProgress;
--import plm.core.model.lesson.Exercise;
--import plm.core.model.lesson.Exercise.StudentOrCorrection;
--import plm.core.ui.ResourcesCache;
--import plm.universe.Entity;
--import scala.Option;
--import scala.collection.JavaConverters;
--import scala.reflect.internal.util.BatchSourceFile;
--import scala.reflect.internal.util.Position;
--import scala.reflect.internal.util.SourceFile;
--import scala.reflect.io.VirtualDirectory;
--import scala.reflect.io.VirtualFile;
--import scala.tools.nsc.Global;
--import scala.tools.nsc.Global.Run;
--import scala.tools.nsc.Settings;
--import scala.tools.nsc.interpreter.AbstractFileClassLoader;
--import scala.tools.nsc.reporters.AbstractReporter;
--
--public class LangScala extends JVMCompiledLang {
--
--	ScalaCompiler compiler = new ScalaCompiler();
--	
--	public LangScala() {
--		super("Scala","scala",ResourcesCache.getIcon("img/lang_scala.png"));
--	}
--
--	@Override
--	public void compileExo(Exercise exo, LogWriter out, StudentOrCorrection whatToCompile) 
--			throws PLMCompilerException {
--		/* Make sure each run generate a new package to avoid that the loader cache prevent the reloading of the newly generated class */
--		packageNameSuffix++;
--		runtimePatterns.put("\\$package", 
--				"package "+packageName()+";import java.awt.Color;");
--
--		List<plm.core.model.session.SourceFile> sfs = exo.getSourceFilesList(this);
--		if (sfs == null || sfs.isEmpty()) {
--			String msg = exo.getName()+": No source to compile";
--			System.err.println(msg);
--			PLMCompilerException e = new PLMCompilerException(msg, null, null);
--			exo.lastResult = ExecutionProgress.newCompilationError(e.getMessage());				
--			throw e;
--		}
--
--		try {
--			compiler.reset();
--			for (plm.core.model.session.SourceFile sf : sfs) {
--				compiler.compile(className(sf.getName()), sf.getCompilableContent(runtimePatterns,whatToCompile), sf.getOffset());
--			}
--		} catch (PLMCompilerException e) {
--			System.err.println(Game.i18n.tr("Compilation error:"));
--			System.err.println(e.getMessage());
--			exo.lastResult = ExecutionProgress.newCompilationError(e.getMessage());
--
--			throw e;
--		}
--		
--	}
--	
--	/** Converts {@code "foo.bar.baz"} to {@code "foo.bar.Scalabaz"}. */
--	@Override
--	public String nameOfCorrectionEntity(Exercise exo){
--		String path = super.nameOfCorrectionEntity(exo);
--		
--		String[] components = path.split("\\.");
--		StringBuilder result = new StringBuilder();
--		int last = components.length - 1;
--		for (int i = 0; i < last; i++) {
--			result.append(components[i] + ".");
--		}
--		result.append("Scala" + components[last]);
--		return result.toString();
--	}
--
--	@Override
--	protected Entity mutateEntity(String newClassName)
--			throws InstantiationException, IllegalAccessException,
--			ClassNotFoundException {
--		return (Entity) compiler.findClass(className(newClassName)).newInstance();
--	}
--}
--
--/** In memory compiler of scala code. 
-- *  This is highly inspired of https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala */
--class ScalaCompiler {
--	
--	private PLMReporter reporter;
--	private Settings settings;
--	private Map<String, Class<?>> cache = new HashMap<String, Class<?>>();
--	private Global global;
--	private VirtualDirectory target;
--	private ClassLoader classLoader = new AbstractFileClassLoader(target, this.getClass().getClassLoader());
--	
--	public ScalaCompiler() {
--		super();
--		settings = new Settings();
--		settings.nowarnings().tryToSetFromPropertyValue("true"); // warnings seem to be exceptions, and we don't want them to mess with us
--
--		Option<VirtualDirectory> noAncestor = scala.Option$.MODULE$.apply(null);
--		target = new VirtualDirectory("(memory)", noAncestor);
--		settings.outputDirs().setSingleOutput(target);
--		
--		settings.usejavacp().tryToSetFromPropertyValue("true");
--		//settings.usemanifestcp().tryToSetFromPropertyValue("true");
--		reporter = new PLMReporter(settings);
--		global = new Global(settings,reporter);
--	}
--
--	public void reset() {
--		reporter.reset();
--		reporter.setOffset(0);
--		target.clear();
--		cache = new HashMap<String, Class<?>>();
--		classLoader = new AbstractFileClassLoader(target, this.getClass().getClassLoader());
--	}
--
--	public void compile(String name,String content,int offset) throws PLMCompilerException {
--		if (Game.getInstance().isDebugEnabled()) 
--			System.out.println("Compiline souce "+name+" to scala (offset:"+offset+"):\n"+content);
--		
--		Run compiler = global.new Run();
--		List<SourceFile> sources = new LinkedList<SourceFile>();
--		
--		sources.add(new BatchSourceFile(new VirtualFile(name) , content.toCharArray()));
--		reporter.setOffset(offset);
--		
--		compiler.compileSources(JavaConverters.asScalaBufferConverter(sources).asScala().toList());
--		
--		if (Game.getInstance().isDebugEnabled() && reporter.hasErrors())
--			System.out.println("Here is the scala source code of "+name+" (offset:"+offset+"): "+content);
--		reporter.throwExceptionOnNeed();
--	}
--	public Class<?> findClass(String className) {
--		synchronized (this) {
--			if (!cache.containsKey(className)) {
--				Class<?> res;
--				try {
--					res = classLoader.loadClass(className);
--				} catch (ClassNotFoundException e) {
--					res = null;
--				}
--				cache.put(className, res);
--			}
--
--			return cache.get(className);			
--		}
--	}
--	
--	class PLMReporter extends AbstractReporter {
--		final static int INFO = 0;
--		final static int WARNING = 1;
--		final static int ERROR = 2;
--		int offset=0;
--		Vector<String> messages = new Vector<String>();
--		Settings settings;
--
--		public PLMReporter(Settings s) {
--			settings = s;
--		}
--		public void setOffset(int _offset) {
--			this.offset = _offset;
--		}
--		@Override
--		public Settings settings() {
--			return settings;
--		}
--		@Override
--		public void displayPrompt() { 
--			/* Don't do that, pal. */ 
--		}
--		@Override
--		public void display(Position pos, String message, Severity _severity) {
--			String severityName = _severity.toString(); 
--			String label = "";
--			int severity = -1;
--			if (severityName.equals("INFO") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity at 0"))
--				severity = INFO;
--			if (severityName.equals("WARNING") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity at 1")) {
--				severity = WARNING;
--				label= "warning: ";
--			}
--			if (severityName.equals("ERROR") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity at 2")) {
--				severity = ERROR;
--				label = "error: ";
--			}
--			if (severity == -1)
--				throw new RuntimeException("Got an unknown severity: "+severityName+". Please adapt the PLM to this new version of scala (or whatever).");
--			if (severity == INFO && !Game.getInstance().isDebugEnabled()) 
--				return;
--
--			int lineNum = -1;
--			try {
--				lineNum = pos.line() - offset;
--			} catch (Throwable t) {
--				// That's fine if the line number is not defined.
--			}
--
--			String name = pos.source().path();
--			int lastDot = name.lastIndexOf('.');
--			if (lastDot != -1)
--				name = name.substring(lastDot+1);
--			String msg = name+(lineNum == -1? "": ":"+lineNum) +": "+label+message;
--
--			// Append the line content and a position marker, if possible
--			if (pos != null && pos.isDefined()) {
--				msg += "\n"+pos.inUltimateSource(pos.source()).lineContent()+"\n";
--				for (int i=0;i<pos.column()-1;i++)
--					msg += " ";
--				msg += "^";
--			}
--
--			messages.add(msg);
--		}
--		public void throwExceptionOnNeed() throws PLMCompilerException {
--			if (hasErrors()) {
--				StringBuffer sb = new StringBuffer();
--				for (String s : messages)
--					sb.append(s);
--				throw new PLMCompilerException(sb.toString(), null, null);
--			}
--		}
--		@Override
--		public void reset() {
--			super.reset();
--			messages.removeAllElements();
--		}
--		
--		/* These methods are mandated by scala 2.11, but I dunno what to do with it, so ignore that for now */
--		public int count(Object o) {
--			return 0;
--		}
--		public void resetCount(Object o) {}
--		public void info0(Position arg0, String arg1, Object arg2, boolean arg3) {
--			// TODO Auto-generated method stub
--		}
--	}
--}
-\ No newline at end of file
-Index: b/src/plm/core/model/Game.java
-===================================================================
---- a/src/plm/core/model/Game.java
-+++ b/src/plm/core/model/Game.java
-@@ -43,7 +43,6 @@ import plm.core.lang.LangJava;
- import plm.core.lang.LangLightbot;
- import plm.core.lang.LangPython;
- import plm.core.lang.LangRuby;
--import plm.core.lang.LangScala;
- import plm.core.lang.ProgrammingLanguage;
- import plm.core.model.lesson.Exercise;
- import plm.core.model.lesson.Exercise.WorldKind;
-@@ -99,14 +98,13 @@ public class Game implements IWorldView
- 
- 	public static final ProgrammingLanguage JAVA =       new LangJava();
- 	public static final ProgrammingLanguage PYTHON =     new LangPython();
--	public static final ProgrammingLanguage SCALA =      new LangScala();
- 	public static final ProgrammingLanguage C =          new LangC();
- 	//public static final ProgrammingLanguage JAVASCRIPT = new ProgrammingLanguage("JavaScript","js",ResourcesCache.getIcon("img/lang_javascript.png"));
- 	public static final ProgrammingLanguage RUBY =       new LangRuby();
- 	public static final ProgrammingLanguage LIGHTBOT =   new LangLightbot();
- 	
- 	public static final ProgrammingLanguage[] programmingLanguages = new ProgrammingLanguage[] {
--		JAVA, PYTHON, SCALA, RUBY, LIGHTBOT, C // TODO: re-add JAVASCRIPT to this list once it works at least a bit
-+		JAVA, PYTHON, RUBY, LIGHTBOT, C // TODO: re-add JAVASCRIPT to this list once it works at least a bit
- 	}; 
- 	private ProgrammingLanguage programmingLanguage = JAVA;
- 
-@@ -164,10 +162,6 @@ public class Game implements IWorldView
- 		i18n = I18nFactory.getI18n(getClass(),"org.plm.i18n.Messages",FileUtils.getLocale(), I18nFactory.FALLBACK);
- 		loadProperties();
- 
--		if (checkScala())
--			System.err.println(i18n.tr("Scala is usable on your machine. Congratulations."));
--		else
--			System.err.println(i18n.tr("Please install Scala version 2.10 or higher to use it in the PLM."));
- 		if (checkPython())
- 			System.err.println(i18n.tr("Jython is usable on your machine. Congratulations."));
- 		else
-@@ -180,17 +174,13 @@ public class Game implements IWorldView
- 		String defaultProgrammingLanguage = Game.getProperty(PROP_PROGRAMING_LANGUAGE,Game.JAVA.getLang(),true);
- 		if (!defaultProgrammingLanguage.equalsIgnoreCase(Game.JAVA.getLang()) &&
- 				!defaultProgrammingLanguage.equalsIgnoreCase(Game.PYTHON.getLang()) &&
--				!defaultProgrammingLanguage.equalsIgnoreCase(Game.SCALA.getLang()) && 
- 				!defaultProgrammingLanguage.equalsIgnoreCase(Game.C.getLang())) 
- 			System.err.println(i18n.tr("Warning, the default programming language is neither ''Java'' nor ''python'' or ''Scala'' or ''C'' but {0}.\n"+
- 					"   This language will be used to setup the worlds, possibly leading to severe issues for the exercises that don''t expect it.\n" +
- 					"   It is safer to change the current language, and restart the PLM before proceeding.\n"+
- 					"   Alternatively, the property {1} can be changed in your configuration file ({2}/plm.properties)",defaultProgrammingLanguage,PROP_PROGRAMING_LANGUAGE, getSavingLocation()));
- 
--		if (defaultProgrammingLanguage.equalsIgnoreCase(Game.SCALA.getLang()) && !canScala) {
--			System.err.println(i18n.tr("The default programming language is Scala, but your scala installation is not usable. Switching to Java instead.\n"));
--			setProgramingLanguage(JAVA);
--		} else if (defaultProgrammingLanguage.equalsIgnoreCase(Game.PYTHON.getLang()) && !canPython) {
-+	        if (defaultProgrammingLanguage.equalsIgnoreCase(Game.PYTHON.getLang()) && !canPython) {
- 			System.err.println(i18n.tr("The default programming language is python, but your python installation is not usable. Switching to Java instead.\n"));
- 			setProgramingLanguage(JAVA);
- 		} else if (defaultProgrammingLanguage.equalsIgnoreCase(Game.C.getLang()) && !canC) {
-@@ -231,35 +221,7 @@ public class Game implements IWorldView
- 
- 	@SuppressWarnings({ "rawtypes", "unchecked" })
- 	private boolean checkScala() {
--		String[] resources = new String[] {"/scala/tools/nsc/Interpreter", "/scala/ScalaObject", "/scala/reflect/io/AbstractFile"};
--		String[] hints     = new String[] {"scala-compiler.jar",           "scala-library.jar",  "scala-reflect.jar"};
--		for (int i=0;i<resources.length;i++) {
--			scalaError = canResolve(resources[i],hints[i]);
--			if (!scalaError.isEmpty()) {
--				System.err.println(scalaError);
--				return canScala;
--			}
--		}
--
--		String version = null;
--		try {
--			Class props = Class.forName("scala.util.Properties");
--			Method meth = props.getMethod("versionString", new Class[] {});
--			version = (String) meth.invoke(props);
--		} catch (Exception e) {
--			scalaError = i18n.tr("Error {0} while retrieving the Scala version: {1}", e.getClass().getName() ,e.getLocalizedMessage());
--			System.err.println( scalaError );
--			return canScala;
--		}
--
--		if (version.contains("version 2.10") || version.contains("version 2.11")) {
--			canScala = true;
--			return canScala;
--		} else {
--			scalaError = i18n.tr("Scala is too ancient. Found {0} while I need 2.10 or higher.",version);
--			System.err.println(scalaError);
--			return canScala;
--		}
-+	        return false;
- 	}
- 
- 	public boolean canPython = false;
-@@ -972,11 +934,6 @@ public class Game implements IWorldView
- 
- 		if (isValidProgLanguage(newLanguage)) {
- 			//System.out.println("Switch programming language to "+newLanguage);
--			if (newLanguage.equals(Game.SCALA) && !canScala) {
--				JOptionPane.showMessageDialog(null, i18n.tr("Please install Scala version 2.10 or higher to use it in the PLM.\n\n")+scalaError ,
--						i18n.tr("Scala is missing"), JOptionPane.ERROR_MESSAGE); 
--				return;
--			}
- 			if (newLanguage.equals(Game.PYTHON) && !canPython) {
- 				JOptionPane.showMessageDialog(null, i18n.tr("Please install jython and its dependencies to use the python programming language in the PLM.\n\n")+pythonError,
- 						i18n.tr("Python is missing"), JOptionPane.ERROR_MESSAGE); 
-@@ -999,7 +956,7 @@ public class Game implements IWorldView
- 			}
- 			this.programmingLanguage = newLanguage;
- 			fireProgLangChange(newLanguage);
--			if (newLanguage.equals(Game.JAVA) || newLanguage.equals(Game.PYTHON) || newLanguage.equals(Game.SCALA) || newLanguage.equals(Game.C)) // Only save it if it's stable enough
-+			if (newLanguage.equals(Game.JAVA) || newLanguage.equals(Game.PYTHON) || newLanguage.equals(Game.C)) // Only save it if it's stable enough
- 				setProperty(PROP_PROGRAMING_LANGUAGE, newLanguage.getLang());
- 			return;
- 		}
-Index: b/src/plm/core/model/lesson/ExerciseTemplated.java
-===================================================================
---- a/src/plm/core/model/lesson/ExerciseTemplated.java
-+++ b/src/plm/core/model/lesson/ExerciseTemplated.java
-@@ -212,7 +212,7 @@ public abstract class ExerciseTemplated
- 		String initialContent = templateHead.toString() + templateTail.toString();
- 		String skelContent;
- 		String headContent;
--		if (lang == Game.PYTHON || lang == Game.SCALA || lang == Game.C) { 
-+		if (lang == Game.PYTHON || lang == Game.C) { 
- 			skelContent = skel.toString();
- 			headContent = head.toString();
- 		} else {
-@@ -358,7 +358,7 @@ public abstract class ExerciseTemplated
- 						System.out.println("Found suitable templating entity "+lang.nameOfCorrectionEntity(this)+" in "+lang);
- 
- 				} catch (NoSuchEntityException e) {
--					if (lang.equals(Game.PYTHON) || lang.equals(Game.SCALA) || lang.equals(Game.JAVA)) 
-+					if (lang.equals(Game.PYTHON) || lang.equals(Game.JAVA)) 
- 						System.out.println("No templating entity found: "+e);
- 						
- 					if (getProgLanguages().contains(lang)) 
-Index: b/src/plm/universe/bat/BatTest.java
-===================================================================
---- a/src/plm/universe/bat/BatTest.java
-+++ b/src/plm/universe/bat/BatTest.java
-@@ -165,9 +165,7 @@ public class BatTest {
- 	}
- 	private void displayParameter(Object o, StringBuffer sb, ProgrammingLanguage pl) {
- 		if (o == null) {
--			if (pl == Game.SCALA)
--				sb.append("Nil");
--			else if (pl == Game.PYTHON)
-+			if (pl == Game.PYTHON)
- 				sb.append("None");
- 			else
- 				sb.append("null");
-@@ -175,8 +173,6 @@ public class BatTest {
- 		} else if (o instanceof String[]) {
- 			if (pl.equals(Game.JAVA)) {
- 				sb.append("{");
--			} else if (pl.equals(Game.SCALA)) {
--				sb.append("Array(");
- 			} else if (pl.equals(Game.PYTHON)) { 
- 				sb.append("[");
- 			} else {
-@@ -191,8 +187,6 @@ public class BatTest {
- 			sb.deleteCharAt(sb.length()-1);
- 			if (pl.equals(Game.JAVA)) {
- 				sb.append("}");
--			} else if (pl.equals(Game.SCALA)) {
--				sb.append(")");
- 			} else if (pl.equals(Game.PYTHON)) { 
- 				sb.append("]");
- 			} else {
-@@ -204,8 +198,6 @@ public class BatTest {
- 			
- 			if (pl.equals(Game.JAVA)) {
- 				sb.append("{");
--			} else if (pl.equals(Game.SCALA)) {
--				sb.append("Array(");
- 			} else if (pl.equals(Game.PYTHON)) { // Python
- 				sb.append("[");
- 			} else {
-@@ -231,8 +223,6 @@ public class BatTest {
- 			}
- 			if (pl.equals(Game.JAVA)) {
- 				sb.append("}");
--			} else if (pl.equals(Game.SCALA)) {
--				sb.append(")");
- 			} else if (pl.equals(Game.PYTHON)) { 
- 				sb.append("]");
- 			} else {
-@@ -240,7 +230,7 @@ public class BatTest {
- 			}
- 		} else if (o instanceof Boolean) {
- 			Boolean b = (Boolean) o;
--			if (pl.equals(Game.JAVA) || pl.equals(Game.SCALA)) {
-+			if (pl.equals(Game.JAVA)) {
- 				sb.append(b ? "true":"false");
- 			} else if (pl.equals(Game.PYTHON)) { 
- 				sb.append(b ? "True" : "False");
-@@ -296,8 +286,6 @@ public class BatTest {
- 			displayParameter(o, sb, Game.getProgrammingLanguage());
- 			return sb.toString();
- 		} else {
--			if (Game.getProgrammingLanguage() == Game.SCALA)
--				return "Nil";
- 			if (Game.getProgrammingLanguage() == Game.PYTHON)
- 				return "None";
- 			return "null";
-Index: b/src/plm/test/simple/test/ScalaSimpleExerciseTest.java
-===================================================================
---- a/src/plm/test/simple/test/ScalaSimpleExerciseTest.java
-+++ /dev/null
-@@ -1,52 +0,0 @@
--package plm.test.simple.test;
--
--import plm.core.model.Game;
--
--public class ScalaSimpleExerciseTest extends JVMCompiledSimpleExerciseTest {
--	
--	public ScalaSimpleExerciseTest() {
--		super(Game.SCALA);
--	}
--	
--	@Override
--	public String generateSyntaxErrorCode() {
--		return "zqkdçajdé\"\"";
--	}
--
--	@Override
--	public String generateVariableErrorCode() {
--		return "toto += 1;\n";
--	}
--
--	@Override
--	public String generateNullPointerErrorCode() {
--		return "override def run() {\n"
--				+ "  var s:String = null;\n"
--				+ "  println(s.length());\n"
--				+ "}";
--	}
--
--	@Override
--	public String generateOutOfBoundsErrorCode() {
--		return "override def run() {\n"
--				+ "  var t:Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\n"
--				+ "  println(t(42));\n"
--				+ "}";
--	}
--
--	@Override
--	public String generateWrongCode() {
--		return "override def run() {\n"
--				+ "  world.asInstanceOf[SimpleWorld].setObjectif(false);\n"
--				+ "}";
--	}
--
--	@Override
--	public String generateSolutionFollowedByError() {
--		return "override def run() {\n"
--				+ "  world.asInstanceOf[SimpleWorld].setObjectif(true);\n"
--				+ "  var t:Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\n"
--				+ "  println(t(42));\n"
--				+ "}";
--	}
--}
-Index: b/src/plm/core/lang/JVMCompiledLang.java
-===================================================================
---- a/src/plm/core/lang/JVMCompiledLang.java
-+++ b/src/plm/core/lang/JVMCompiledLang.java
-@@ -48,15 +48,6 @@ public abstract class JVMCompiledLang ex
- 					ent = (Entity)getClass().getClassLoader().loadClass(newClassName).newInstance(); 
- 				} catch (Exception e2) {
- 					if (whatToMutate == StudentOrCorrection.STUDENT) {
--						if (Game.getProgrammingLanguage() == Game.SCALA)
--							throw new PLMCompilerException(Game.i18n.tr(
--									  "Your entity failed to start. Did you forgot to put your code within a method?\n\n"
--									+ "This problem often arises when the exercise expects you to put all the code within a \n"
--									+ "method e.g. run(), but you put some statements (e.g. forward()) outside of any method.\n\n"
--									+ "The easiest solution to sort it out is to copy all your code (Ctrl-A Ctrl-C), use the \n"
--									+ "'Exercise/Revert' menu to reset the template, and paste (Ctrl-V) your code within the\n"
--									+ "provided method."));
--						else
- 							throw new PLMCompilerException(Game.i18n.tr("Your entity failed to start. Your constructor seems to be broken, but I have no clue."));
- 					} else {
- 						throw new PLMEntityNotFound("Cannot find an entity of name "+className(newClassName)+" or "+newClassName+". Broken lesson.", e2);
-Index: b/src/plm/core/model/lesson/ExerciseTemplatingEntity.java
-===================================================================
---- a/src/plm/core/model/lesson/ExerciseTemplatingEntity.java
-+++ b/src/plm/core/model/lesson/ExerciseTemplatingEntity.java
-@@ -83,19 +83,7 @@ public abstract class ExerciseTemplating
- 		javaFile.setCorrection("$package "+template+" @SuppressWarnings(\"unchecked\") public void run(BatTest t) {\n"+javaFile.getTemplate()+"}\n"+javaFile.getCorrection()+" }");
- 		javaFile.setTemplate  ("$package "+template+" @SuppressWarnings(\"unchecked\") public void run(BatTest t) {  "+javaFile.getTemplate()+"}    $body }");
- 		//System.out.println("New template: "+sf.getTemplate());
--		
--		if (getProgLanguages().contains(Game.SCALA)) {
--			SourceFile scalaFile = sourceFiles.get(Game.SCALA).get(0);
--			String header = "$package\n"
--					+ "import plm.universe.bat.{BatEntity,BatWorld,BatTest}; \n"
--					+ "import plm.universe.World; \n"
--					+ "import scala.collection.JavaConverters._;\n"
--					+ "class "+entName+" extends BatEntity { ";
--			
--			scalaFile.setCorrection(header+scalaFile.getCorrection()+" }");
--			scalaFile.setTemplate  (header+scalaFile.getTemplate()  +" }");
--		}
--		
-+				
- 		computeAnswer();
- 		setSetup(true);
- 	}
-@@ -114,8 +102,6 @@ public abstract class ExerciseTemplating
- 	protected void templateScala(String entName, String[] types, String initialCode, String correction) {
- 		if (isSetup())
- 			throw new RuntimeException("The exercise "+getName()+" is already setup, too late to add a programming language template.");
--		if (this.getProgLanguages().contains(Game.SCALA))
--			throw new RuntimeException("The exercise "+getName()+" has two Scala templates. Please fix this bug.");
- 		
- 		StringBuffer skeleton = new StringBuffer(" val res = ");
- 		skeleton.append(entName);
-@@ -146,9 +132,6 @@ public abstract class ExerciseTemplating
- 		skeleton.append("  case e:java.lang.ClassCastException => t.setResult(res)\n"); // primitive types cannot be converted to java, but I don't care (and cannot test whether res is a primitive type)
- 		skeleton.append("}\n");
- 		
--		newSource(Game.SCALA, entName, initialCode, "\n   override def run(t: BatTest) {\n"+skeleton+"\n   }\n$body",14,
--				                                    "\n   override def run(t: BatTest) {\n"+skeleton+"\n   }\n"+initialCode+correction);
--		addProgLanguage(Game.SCALA);
- 	}
- 	public boolean isSetup() {
- 		return isSetup;
-Index: b/src/plm/core/ui/editor/MissionEditor.java
-===================================================================
---- a/src/plm/core/ui/editor/MissionEditor.java
-+++ b/src/plm/core/ui/editor/MissionEditor.java
-@@ -110,7 +110,6 @@ public class MissionEditor extends JFram
- 		selectorAll.setSelected(true);
- 		final JCheckBox selectorC = new JCheckBox("C");
- 		final JCheckBox selectorJava = new JCheckBox("Java");
--		final JCheckBox selectorScala = new JCheckBox("Scala");
- 		final JCheckBox selectorPython = new JCheckBox("Python");
- 
- 		final ItemListener il = new ItemListener() {
-@@ -129,9 +128,6 @@ public class MissionEditor extends JFram
- 					if(selectorJava.isSelected()){
- 						l.add(Game.JAVA);
- 					}
--					if(selectorScala.isSelected()){
--						l.add(Game.SCALA);
--					}
- 					if(selectorPython.isSelected()){
- 						l.add(Game.PYTHON);
- 					}
-@@ -162,7 +158,6 @@ public class MissionEditor extends JFram
- 		selectorAll.addItemListener(il);
- 		selectorC.addItemListener(il);
- 		selectorJava.addItemListener(il);
--		selectorScala.addItemListener(il);
- 		selectorPython.addItemListener(il);
- 
- 		editor = new JEditorPane();
-@@ -183,7 +178,6 @@ public class MissionEditor extends JFram
- 		box.add(selectorAll);
- 		box.add(selectorC);
- 		box.add(selectorJava);
--		box.add(selectorScala);
- 		box.add(selectorPython);
- 
- 		rightDisplay.add(box, BorderLayout.NORTH);
-Index: b/src/plm/core/ui/JavaEditorPanel.java
-===================================================================
---- a/src/plm/core/ui/JavaEditorPanel.java
-+++ b/src/plm/core/ui/JavaEditorPanel.java
-@@ -31,8 +31,6 @@ public class JavaEditorPanel extends RTe
-             codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
-         } else if (lang.equals(Game.PYTHON)) {
-             codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON);
--        } else if (lang.equals(Game.SCALA)) {
--            codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SCALA);
-         } else if (lang.equals(Game.C)) {
-             codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_C);
-         } else {
-Index: b/src/plm/universe/bat/BatExercise.java
-===================================================================
---- a/src/plm/universe/bat/BatExercise.java
-+++ b/src/plm/universe/bat/BatExercise.java
-@@ -98,7 +98,7 @@ public abstract class BatExercise extend
- 		}
- 
- 		for (ProgrammingLanguage pl : getProgLanguages()) {
--			if (!pl.equals(Game.JAVA) && !pl.equals(Game.SCALA)) 
-+			if (!pl.equals(Game.JAVA))
- 				worlds.get(0).getEntity(0).setScript(pl, corrections.get(pl));
- 		}
- 		
-Index: b/src/plm/test/simple/test/AllSimpleExerciseTests.java
-===================================================================
---- a/src/plm/test/simple/test/AllSimpleExerciseTests.java
-+++ b/src/plm/test/simple/test/AllSimpleExerciseTests.java
-@@ -5,7 +5,7 @@ import org.junit.runners.Suite;
- import org.junit.runners.Suite.SuiteClasses;
- 
- @RunWith(Suite.class)
-- at SuiteClasses({ JavaSimpleExerciseTest.class, ScalaSimpleExerciseTest.class, PythonSimpleExerciseTest.class })
-+ at SuiteClasses({ JavaSimpleExerciseTest.class, PythonSimpleExerciseTest.class })
- public class AllSimpleExerciseTests {
- 
- }
diff --git a/debian/patches/series b/debian/patches/series
index d6eccd6..135fdba 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,4 +1,3 @@
 system-ant-tasks
-no-scala
 no-github
 translate

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/plm.git



More information about the pkg-java-commits mailing list