Commit c5ce8868 authored by Rick van der Wal's avatar Rick van der Wal
Browse files

Created experimental rules

parent bcbc9aef
......@@ -6,23 +6,53 @@ import lang::java::m3::Core;
import ClassHierarchy;
import StandardLocations;
import Util;
set[Message] allAssignmentSnakeRules(M3 model)
= aSnake_view_separated(model)
= aSnake_model_separated(model)
+ aSnake_view_separated(model)
+ aSnake_controller_separated(model)
;
// Check if World contains the timeline, in which case most model logic is most likely there too
set[Message] aSnake_model_separated(M3 model) = classDependsOn(model, "World", javafxAnimationTimeline);
set[Message] aSnake_view_separated(M3 model)
{
// Check if SnakeGame is the only class that uses JavaFX scene objects
return {};
// Check if SnakeGame itself doesn't contain things that should be in the model
// Check if no classes other than SnakeGame contain JavaFX shapes
// set[loc] shapeClasses =
// { |java+class:///javafx/scene/shape/Circle|
// , |java+class:///javafx/scene/shape/Rectangle|
// , |java+class:///javafx/scene/shape/Polygon|
// , |java+class:///javafx/scene/shape/Ellipse|
// , |java+class:///javafx/scene/shape/Line|
// , |java+class:///javafx/scene/shape/Arc|
// };
// set[loc] createdClasses =
// { findClass(model, "Main")
// , findClass(model, "Segment")
// , findClass(model, "Snake")
// , findClass(model, "Food")
// , findClass(model, "World")
// };
// return { error("<getName(model, shapeClass)> is part of the model and should be moved to SnakeGame", createdClass)
// | createdClass <- createdClasses
// , shapeClass <- shapeClasses
// , shapeClass in allTypeDependenciesLoc(model, createdClass)
// };
return { error("<allTypeDependenciesLoc(model, findClass(model, "Food"))>", findClass(model, "Main")) };
}
set[Message] aSnake_controller_separated(M3 model)
{
// Check if InputHandler is the only class that uses JavaFX EventListeners
// This is more difficult because other classes can add event listeners to scenes
// using a lambda, in which case they don't need the EventListener import
return {};
// Check if InputHandler itself doesn't contain things that should be in the model
// Check if InputHandler is the only class that uses JavaFX EventHandler
// This is difficult because other classes can add event handlers to scenes using a lambda, in which case they don't need the EventHandler import, this won't work then
set[loc] createdClasses =
{ findClass(model, "Main")
, findClass(model, "World")
};
return { error("<getName(model, javafxEventEventHandler)> is part of the controller and should be moved to InputHandler", createdClass)
| createdClass <- createdClasses
, javafxEventEventHandler in allTypeDependenciesLoc(model, createdClass)
};
}
......@@ -18,6 +18,7 @@ import AssignmentExpressionsRules;
import AssignmentSlidingGameRules;
import AssignmentQuadtreesRules;
import AssignmentPolynomialsRules;
import AssignmentSnakeRules;
import AssignmentPropositionalRules;
import AssignmentStreamsRules;
import AssignmentFileFinderMergeSortRules;
......
......@@ -31,4 +31,8 @@ public loc javaLangRunnable = |java+interface:///java/lang/Runnable|;
public loc javaUtilExecutorService = |java+interface:///java/util/concurrent/ExecutorService|;
public loc javaUtilLock = |java+interface:///java/util/concurrent/locks/Lock|;
public loc javaUtilCondition = |java+interface:///java/util/concurrent/locks/Condition|;
\ No newline at end of file
public loc javaUtilCondition = |java+interface:///java/util/concurrent/locks/Condition|;
public loc javafxAnimationTimeline = |java+class:///javafx/animation/Timeline|;
public loc javafxEventEventHandler = |java+interface:///javafx/event/EventHandler|;
public loc javafxSceneShapeCircle = |java+class:///javafx/scene/shape/Circle|;
......@@ -6,6 +6,8 @@ import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.scene.input.KeyEvent;
import javafx.event.EventHandler;
public class Main extends Application {
......@@ -25,20 +27,23 @@ public class Main extends Application {
Scene scene = new Scene(root);
scene.setOnKeyPressed(keyEvent -> {
Snake snake = world.getSnake();
switch (keyEvent.getCode()) {
case A:
snake.setDirection(snake.getDirection().rotateLeft());
break;
case D:
snake.setDirection(snake.getDirection().rotateRight());
break;
case S:
world.setRunning(!world.isRunning());
break;
}
keyEvent.consume();
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent keyEvent) {
Snake snake = world.getSnake();
switch (keyEvent.getCode()) {
case A:
snake.setDirection(snake.getDirection().rotateLeft());
break;
case D:
snake.setDirection(snake.getDirection().rotateRight());
break;
case S:
world.setRunning(!world.isRunning());
break;
}
keyEvent.consume();
}
});
primaryStage.setTitle("Snake");
......
......@@ -15,20 +15,21 @@ test bool aSnakeexampleSolution()
return isEmpty(errors);
}
test bool aSnakebaseClassesNotAbstract()
test bool aSnakegraphicsNotInView()
{
M3 model = loadTestProject("snake-graphics-not-in-view");
errors = allAssignmentSnakeRules(model);
return
{
{ "Rectangle is part of the model and should be moved to SnakeGame"
, "Circle is part of the model and should be moved to SnakeGame"
} == messages(errors);
}
test bool aSnakevariableNotExtendsOneArgExpr()
test bool aSnakeinputNotInController()
{
M3 model = loadTestProject("snake-input-not-in-controller");
errors = allAssignmentSnakeRules(model);
return
{
{ "EventHandler is part of the controller and should be moved to InputHandler"
} == messages(errors);
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment