[plm] 05/13: refresh patches
Martin Quinson
mquinson at moszumanska.debian.org
Sat Nov 1 07:28:06 UTC 2014
This is an automated email from the git hooks/post-receive script.
mquinson pushed a commit to branch debian
in repository plm.
commit 10ac7bd48ab19e099fbc457020fc971d7203047d
Author: Martin Quinson <martin.quinson at loria.fr>
Date: Fri Oct 24 20:33:48 2014 +0200
refresh patches
---
debian/patches/no-scala | 2171 ++++++++++++++++++++++++++++++++++-----
debian/patches/system-ant-tasks | 4 +-
2 files changed, 1939 insertions(+), 236 deletions(-)
diff --git a/debian/patches/no-scala b/debian/patches/no-scala
index 637c49b..d553738 100644
--- a/debian/patches/no-scala
+++ b/debian/patches/no-scala
@@ -1,246 +1,1951 @@
---
- src/plm/core/CompilerScala.java | 143 ----------------------------------
- src/plm/core/model/Game.java | 2
- src/plm/core/ui/PlmHtmlEditorKit.java | 16 ++-
- 3 files changed, 13 insertions(+), 148 deletions(-)
+ 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/ui/ChooseLessonDialog.java | 2
+ src/plm/test/ExoTest.java | 2
+ src/plm/test/LessonTest.java | 2
+ 39 files changed, 3 insertions(+), 1689 deletions(-)
-Index: b/src/plm/core/CompilerScala.java
+Index: b/src/lessons/lander/universe/Configurations.scala
===================================================================
---- a/src/plm/core/CompilerScala.java
-+++ b/src/plm/core/CompilerScala.java
-@@ -9,18 +9,6 @@
- import java.util.Vector;
-
- import plm.core.model.Game;
--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 CompilerScala {
-
-@@ -31,143 +19,16 @@
- return instance;
- }
-
-- 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());
--
- private CompilerScala() {
-- 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);
-+ /* Scala is too ancient in Debian (need 2.10), so kill that all */
- }
-
- 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 {
--
-- 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);
-- }
+--- 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)
-
-- return cache.get(className);
+- 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 */
- }
--
-- 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;
+-}
+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 @@
-
-- int lineNum = -1;
-- try {
-- lineNum = pos.line() - offset;
-- } catch (Throwable t) {
-- // That's fine if the line number is not defined.
-- }
+-<!-- 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>
-
-- 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 += "^";
-- }
+-<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>
-
-- 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);
+-<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;
- }
-- @Override
-- public void reset() {
-- super.reset();
-- messages.removeAllElements();
+- /* 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);
+- }
- }
-+ return null;
- }
- }
+- 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/plm/core/model/Game.java
-===================================================================
---- a/src/plm/core/model/Game.java
-+++ b/src/plm/core/model/Game.java
-@@ -93,7 +93,7 @@
- public static final ProgrammingLanguage RUBY = new ProgrammingLanguage("Ruby","rb",ResourcesCache.getIcon("img/lang_ruby.png"));
- public static final ProgrammingLanguage LIGHTBOT = new ProgrammingLanguage("lightbot","ignored",ResourcesCache.getIcon("img/lightbot_light.png"));
- public static final ProgrammingLanguage[] programmingLanguages = new ProgrammingLanguage[] {
-- JAVA, PYTHON, SCALA, RUBY, LIGHTBOT // TODO: re-add JAVASCRIPT to this list once it works at least a bit
-+ JAVA, PYTHON, RUBY, LIGHTBOT // TODO: re-add JAVASCRIPT to this list once it works at least a bit
- };
- private ProgrammingLanguage programmingLanguage = JAVA;
-
-Index: b/src/plm/core/ui/PlmHtmlEditorKit.java
-===================================================================
---- a/src/plm/core/ui/PlmHtmlEditorKit.java
-+++ b/src/plm/core/ui/PlmHtmlEditorKit.java
-@@ -68,18 +68,22 @@
-
- String res = in.replaceAll("\\[!thelang/?\\]", "[!java]Java[/!][!python]python[/!][!scala]Scala[/!]");
- res = res.replaceAll("\\[!configfile/?\\]", Game.getSavingLocation()+File.separator+"plm.properties".replaceAll("\\\\", "\\\\"));
-+ ProgrammingLanguage []theProgLangs = new ProgrammingLanguage[Game.getProgrammingLanguages().length+1];
-+ for (int i=0; i<Game.getProgrammingLanguages().length;i++)
-+ theProgLangs[i] = Game.getProgrammingLanguages()[i];
-+ theProgLangs[theProgLangs.length-1] = Game.SCALA;
-
- /* Display everything when in debug mode, with shiny colors */
- if (showAll) {
- // Process any block with one language first so that they can be nested in blocks with more than one language.
-- for (ProgrammingLanguage lang : Game.getProgrammingLanguages()) {
-+ for (ProgrammingLanguage lang : theProgLangs) {
- String l = lang.getLang().toLowerCase();
- res = res.replaceAll("(?s)\\[!"+l+"\\](.*?)\\[/!\\]",
- "<font color=\""+langColors.get(l)+"\">$1</font>");
- }
-- for (ProgrammingLanguage lang : Game.getProgrammingLanguages()) {
-+ for (ProgrammingLanguage lang : theProgLangs) {
- String l = lang.getLang().toLowerCase();
-- for (ProgrammingLanguage lang2 : Game.getProgrammingLanguages()) {
-+ for (ProgrammingLanguage lang2 : theProgLangs) {
- if (!lang2.equals(lang)) {
- String l2 = lang2.getLang().toLowerCase();
- res = res.replaceAll("(?s)\\[!"+l+"\\|"+l2+"\\](.*?)\\[/!\\]",
-@@ -98,7 +102,7 @@
- // Process any block with one language first so that they can be nested in blocks with more than one language.
- res = res.replaceAll( "(?s)\\[!"+cl+"\\](.*?)\\[/!\\]","$1");
- //System.out.println("Keep "+"(?s)\\[!"+cl+"\\](.*?)\\[/!\\]");
-- for (ProgrammingLanguage lang : Game.getProgrammingLanguages()) {
-+ for (ProgrammingLanguage lang : theProgLangs) {
- if (!lang.equals(currLang)) {
- String l = lang.getLang().toLowerCase();
-
-@@ -106,7 +110,7 @@
- //System.out.println("Kill "+"(?s)\\[!"+l+"\\](.*?)\\[/!\\]");
- }
- }
-- for (ProgrammingLanguage lang : Game.getProgrammingLanguages()) {
-+ for (ProgrammingLanguage lang : theProgLangs) {
- if (!lang.equals(currLang)) {
- String l = lang.getLang().toLowerCase();
-
-@@ -115,7 +119,7 @@
- res = res.replaceAll( "(?s)\\[!"+cl+"\\|"+l +"\\](.*?)\\[/!\\]", "$1");
- //System.out.println("Keep "+"(?s)\\[!"+cl+"\\|"+l +"\\](.*?)\\[/!\\]");
-
-- for (ProgrammingLanguage lang2 : Game.getProgrammingLanguages()) {
-+ for (ProgrammingLanguage lang2 : theProgLangs) {
- if (!lang2.equals(currLang) && !lang2.equals(lang)) {
- String l2 = lang2.getLang().toLowerCase();
- res = res.replaceAll( "(?s)\\[!"+l+"\\|"+l2+"\\](.*?)\\[/!\\]", "");
+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
+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;
diff --git a/debian/patches/system-ant-tasks b/debian/patches/system-ant-tasks
index d07f2bc..a322f75 100644
--- a/debian/patches/system-ant-tasks
+++ b/debian/patches/system-ant-tasks
@@ -2,11 +2,9 @@
build.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
-Index: b/build.xml
-===================================================================
--- a/build.xml
+++ b/build.xml
-@@ -163,7 +163,7 @@
+@@ -182,7 +182,7 @@
</propertyfile>
</target>
--
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