const ecs = new Ecs();
const groups = {
  MODEL: 'MODEL',
  GRAPHICS: 'GRAPHICS',
};
const comps = {
  POSITION: 'position',
  VELOCITY: 'velocity',
  RECTANGLE: 'rectangle',
  INPUT: 'input',
  PLAYER_CONTROLLED: 'playerControlled',
  AI_CONTROLLED: 'aiControlled',
  COLOR: 'color',
};
const keyCodeToName = {//translate keyCode to key string
  "32": "SPACE",
  "38": "UP",
  "40": "DOWN",
  "37": "LEFT",
  "39": "RIGHT"
};
const view = {
  canvas: document.querySelector('canvas'),
  ctx: document.querySelector('canvas').getContext("2d"),
};

//components
ecs.registerComponent(comps.POSITION, function(x = 0, y = 0) {
  this.x = x;
  this.y = y;
});

ecs.registerComponent(comps.VELOCITY, function(x = 0, y = 0) {
  this.x = x;
  this.y = y;
});

ecs.registerComponent(comps.RECTANGLE, function(width = 5, height = 5) {
  this.width = width;
  this.height = height;
});

ecs.registerComponent(comps.INPUT, function() {
  this.UP = false;
  this.DOWN = false;
  this.LEFT = false;
  this.RIGHT = false;
  this.SPACE = false;
});

ecs.registerComponent(comps.PLAYER_CONTROLLED);

ecs.registerComponent(comps.COLOR);

ecs.registerComponent(comps.HIDDEN);

ecs.registerComponent(comps.AI_CONTROLLED);

//systems
ecs.registerSystem({//move entities with velocity
  group: groups.MODEL,
  has: [comps.POSITION, comps.VELOCITY],
  pre(dt) {

  },
  forEach(entity, dt){//iterates all entities with position and velocity component
    const { position, velocity } = entity;
    position.x += velocity.x * dt;
    position.y += velocity.y * dt;
  }
});

ecs.registerSystem({
  group: groups.GRAPHICS,
  has: [comps.POSITION, comps.RECTANGLE, comps.COLOR],
  not: [comps.HIDDEN],
  pre(view) {
    view.canvas.width = view.canvas.width;
  },
  forEach(entity, view) {
    const { x, y } = entity.position;
    const { width, height } = entity.rectangle;
    const { ctx } = view;
    ctx.fillStyle = entity.color.value;
    ctx.fillRect(x, y, width, height);
  }
})

ecs.registerSystem({
  group: groups.MODEL,
  has: [comps.INPUT, comps.PLAYER_CONTROLLED],
  mounted() {//called once system is created
    document.addEventListener("keydown", e => {//keydown event
      const key = keyCodeToName[e.keyCode];
      //TODO: DO something
    });

    document.addEventListener("keyup",function (e) {//keyup event

    });
  }
});

function createMeteorite() {
  ecs.createEntity()
    .add(comps.POSITION, Math.random() * view.canvas.width, 0)
    .add(comps.VELOCITY, 50, 50)
    .add(comps.RECTANGLE, 20, 20)
    .add(comps.COLOR, "orange");
}

function createSnowFlake() {
  ecs.createEntity()
    .add(comps.POSITION, Math.random() * view.canvas.width * 2 - view.canvas.width, 0)
    .add(comps.VELOCITY, 0, 5)
    .add(comps.RECTANGLE, 1, 2)
    .add(comps.COLOR, "white");
}

function loop() {
  createSnowFlake()
  Math.random() > 0.9 && createMeteorite()
  const dt = 0.016;
  ecs.runGroup(groups.MODEL, dt);
  ecs.runGroup(groups.GRAPHICS, view);
  requestAnimationFrame(loop);
}

loop();

@@ -567,16 +567,41 @@
 %0D%0A%7D;%0D%0A%0D%0A
+window.onload = loop;%0D%0A%0D%0A
 //compon
@@ -1439,22 +1439,38 @@
 forEach(
-entity
+%7B position, velocity %7D
 , dt)%7B//
@@ -1533,52 +1533,8 @@
 nt%0D%0A
-    const %7B position, velocity %7D = entity;%0D%0A
     
@@ -1748,20 +1748,26 @@
 %0D%0A  pre(
-view
+%7B canvas %7D
 ) %7B%0D%0A   
@@ -1767,21 +1767,16 @@
  %7B%0D%0A    
-view.
 canvas.w
@@ -1782,21 +1782,16 @@
 width = 
-view.
 canvas.w
@@ -1817,20 +1817,47 @@
 ach(
-entity, view
+%7B position, rectangle, color %7D, %7B ctx %7D
 ) %7B%0D
@@ -1878,23 +1878,16 @@
 , y %7D = 
-entity.
 position
@@ -1919,23 +1919,16 @@
 ght %7D = 
-entity.
 rectangl
@@ -1935,35 +1935,8 @@
 e;%0D%0A
-    const %7B ctx %7D = view;%0D%0A
     
@@ -1955,15 +1955,8 @@
 e = 
-entity.
 colo
@@ -2020,386 +2020,8 @@
 %0D%0A%0D%0A
-ecs.registerSystem(%7B%0D%0A  group: groups.MODEL,%0D%0A  has: %5Bcomps.INPUT, comps.PLAYER_CONTROLLED%5D,%0D%0A  mounted() %7B//called once system is created%0D%0A    document.addEventListener(%22keydown%22, e =%3E %7B//keydown event%0D%0A      const key = keyCodeToName%5Be.keyCode%5D;%0D%0A      //TODO: DO something%0D%0A    %7D);%0D%0A%0D%0A    document.addEventListener(%22keyup%22,function (e) %7B//keyup event%0D%0A%0D%0A    %7D);%0D%0A  %7D%0D%0A%7D);%0D%0A%0D%0A
 func
@@ -2502,16 +2502,37 @@
 op() %7B%0D%0A
+  const dt = 0.016;%0D%0A
   create
@@ -2542,16 +2542,17 @@
 wFlake()
+;
 %0D%0A  Math
@@ -2587,36 +2587,16 @@
 eorite()
-%0D%0A  const dt = 0.016
 ;%0D%0A  ecs
@@ -2704,15 +2704,4 @@
 %0A%7D%0D%0A
-%0D%0Aloop();%0D%0A

Update example