website/cours/6piles/pile.js
2025-10-07 21:27:09 +02:00

519 lines
22 KiB
JavaScript

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var CANVAS_ID = "myCanvas";
var BG_RECT = { x: 0, y: 0, w: 1050, h: 1050 };
var FPS = 30;
var FRAME_INTERVAL = 1000 / FPS;
var WAIT_TIME = 300;
var PROCESSING = false;
var GLOBAL_PROCESSING = false;
var LEARNING = false;
var canvas = document.getElementById(CANVAS_ID);
var ctx = canvas.getContext("2d");
canvas.width = BG_RECT.w;
canvas.height = BG_RECT.h;
var staticCanvas = document.createElement('canvas');
var staticCtx = staticCanvas.getContext("2d");
staticCanvas.width = BG_RECT.w;
staticCanvas.height = BG_RECT.h;
var animationFrameId;
var lastFrameTime = 0;
var callbacks = [];
var Pile = /** @class */ (function () {
function Pile() {
this.length = 0;
this.mem = [];
}
Pile.prototype.push = function (e) {
this.length++;
this.mem.push(e);
};
Pile.prototype.pop = function () {
this.length = this.length > 0 ? this.length - 1 : 0;
return this.mem.pop();
};
Pile.prototype.empty = function () {
this.mem = [];
this.length = 0;
};
Pile.prototype.draw = function (x, y) {
var w = 150;
var h = 200;
var e = 10;
var eh = 10;
// container
staticCtx.fillStyle = "#000000";
staticCtx.fillRect(x - w / 2, y - h, w, h);
staticCtx.fillStyle = "#ffffff";
staticCtx.fillRect(x - w / 2 + e, y - h, w - 2 * e, h - e);
// element
var ye = y - e - eh / 2;
for (var i = 0; i < this.length; i++) {
var ew = this.mem[i].value / 10 * (w - 2 * e);
staticCtx.fillStyle = this.mem[i].color;
staticCtx.fillRect(x - ew / 2, ye - i * eh - eh / 2, ew, eh);
}
};
return Pile;
}());
var File_t = /** @class */ (function () {
function File_t() {
this.head = new Pile();
this.b_head = new Pile();
this.tail = new Pile();
this.c_tail = new Pile();
this.b_1 = new Pile();
this.b_2 = new Pile();
this.stepLevel = 0;
this.count = 0;
}
File_t.prototype.emptyAll = function () {
this.b_head.empty();
this.b_1.empty();
this.b_2.empty();
this.c_tail.empty();
while (this.tail.length > 0) {
this.b_1.push(this.tail.pop());
}
while (this.b_1.length > 0) {
var e = this.b_1.pop();
this.tail.push(e);
this.c_tail.push(e);
}
};
File_t.prototype.push = function (e) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
console.log("Current step:", this.stepLevel, "\n");
if (!(this.head.length === 0 && this.tail.length === 0)) return [3 /*break*/, 1];
this.tail.push(e);
this.c_tail.push(e);
return [3 /*break*/, 5];
case 1:
if (!(this.stepLevel > 0)) return [3 /*break*/, 3];
this.head.push(e);
GLOBAL_PROCESSING = true;
return [4 /*yield*/, this.step()];
case 2:
_a.sent();
return [3 /*break*/, 5];
case 3:
this.head.push(e);
if (!(this.head.length === this.tail.length)) return [3 /*break*/, 5];
console.log("Begin Transfert\n");
this.stepLevel = 1;
GLOBAL_PROCESSING = true;
return [4 /*yield*/, this.step()];
case 4:
_a.sent();
_a.label = 5;
case 5: return [2 /*return*/];
}
});
});
};
File_t.prototype.pop = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(this.stepLevel > 2)) return [3 /*break*/, 2];
this.count++;
this.tail.pop();
GLOBAL_PROCESSING = true;
return [4 /*yield*/, this.step()];
case 1:
_a.sent();
return [3 /*break*/, 4];
case 2:
this.c_tail.pop();
this.tail.pop();
if (!(this.stepLevel > 0)) return [3 /*break*/, 4];
GLOBAL_PROCESSING = true;
return [4 /*yield*/, this.step()];
case 3:
_a.sent();
_a.label = 4;
case 4:
if (!(this.head.length === this.tail.length)) return [3 /*break*/, 6];
console.log("Begin Transfert\n");
this.stepLevel = 1;
return [4 /*yield*/, this.step()];
case 5:
_a.sent();
_a.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
File_t.prototype.step = function () {
return __awaiter(this, arguments, void 0, function (n) {
var e, e, e;
var _a, _b, _c, _d, _e, _f;
if (n === void 0) { n = 5; }
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
if (n <= 0) { // finit le nombre d'étape pour le moment
GLOBAL_PROCESSING = false;
return [2 /*return*/];
}
if (!!LEARNING) return [3 /*break*/, 2];
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, WAIT_TIME); })];
case 1:
_g.sent();
_g.label = 2;
case 2:
this.draw();
console.log("Transfer step:", this.stepLevel, "\n");
if (!(this.stepLevel === 1)) return [3 /*break*/, 5];
_a = [this.b_head, this.head], this.head = _a[0], this.b_head = _a[1];
this.stepLevel++;
if (!!LEARNING) return [3 /*break*/, 4];
return [4 /*yield*/, this.step(n)];
case 3:
_g.sent();
_g.label = 4;
case 4: return [3 /*break*/, 34];
case 5:
if (!(this.stepLevel === 2)) return [3 /*break*/, 13];
e = this.b_head.pop();
if (!(e === undefined)) return [3 /*break*/, 8];
this.stepLevel++;
if (!!LEARNING) return [3 /*break*/, 7];
return [4 /*yield*/, this.step(n)];
case 6:
_g.sent();
_g.label = 7;
case 7: return [3 /*break*/, 12];
case 8:
this.b_1.push(e);
this.b_2.push(e);
if (!!LEARNING) return [3 /*break*/, 10];
return [4 /*yield*/, this.step(n - 2)];
case 9:
_g.sent();
return [3 /*break*/, 12];
case 10: return [4 /*yield*/, this.step(n)];
case 11:
_g.sent();
_g.label = 12;
case 12: return [3 /*break*/, 34];
case 13:
if (!(this.stepLevel === 3)) return [3 /*break*/, 16];
_b = [this.b_2, this.b_head], this.b_head = _b[0], this.b_2 = _b[1];
this.stepLevel++;
if (!!LEARNING) return [3 /*break*/, 15];
return [4 /*yield*/, this.step(n)];
case 14:
_g.sent();
_g.label = 15;
case 15: return [3 /*break*/, 34];
case 16:
if (!(this.stepLevel === 4)) return [3 /*break*/, 24];
e = this.c_tail.pop();
if (!(e === undefined)) return [3 /*break*/, 19];
this.stepLevel++;
if (!!LEARNING) return [3 /*break*/, 18];
return [4 /*yield*/, this.step(n)];
case 17:
_g.sent();
_g.label = 18;
case 18: return [3 /*break*/, 23];
case 19:
this.b_2.push(e);
if (!!LEARNING) return [3 /*break*/, 21];
return [4 /*yield*/, this.step(n - 1)];
case 20:
_g.sent();
return [3 /*break*/, 23];
case 21: return [4 /*yield*/, this.step(n)];
case 22:
_g.sent();
_g.label = 23;
case 23: return [3 /*break*/, 34];
case 24:
if (!(this.stepLevel === 5)) return [3 /*break*/, 33];
if (this.b_2.length === this.count) { // ne pas compter les éléments déjà retirés
_c = [this.c_tail, this.b_1], this.b_1 = _c[0], this.c_tail = _c[1];
_d = [this.tail, this.b_head], this.b_head = _d[0], this.tail = _d[1];
this.stepLevel = 0;
this.emptyAll();
GLOBAL_PROCESSING = false;
this.count = 0;
return [2 /*return*/];
}
e = this.b_2.pop();
if (!(e === undefined)) return [3 /*break*/, 25];
this.stepLevel++;
if (!LEARNING) {
this.step(n);
}
return [3 /*break*/, 32];
case 25:
this.b_head.push(e);
this.b_1.push(e);
if (!(this.b_2.length === 0)) return [3 /*break*/, 28];
this.stepLevel++;
if (!!LEARNING) return [3 /*break*/, 27];
return [4 /*yield*/, this.step(n)];
case 26:
_g.sent();
_g.label = 27;
case 27: return [3 /*break*/, 32];
case 28:
if (!!LEARNING) return [3 /*break*/, 30];
return [4 /*yield*/, this.step(n - 2)];
case 29:
_g.sent();
return [3 /*break*/, 32];
case 30: return [4 /*yield*/, this.step(n)];
case 31:
_g.sent();
_g.label = 32;
case 32: return [3 /*break*/, 34];
case 33:
if (this.stepLevel === 6) { // dernier échange
_e = [this.c_tail, this.b_1], this.b_1 = _e[0], this.c_tail = _e[1];
_f = [this.tail, this.b_head], this.b_head = _f[0], this.tail = _f[1];
this.stepLevel = 0;
this.emptyAll();
GLOBAL_PROCESSING = false;
this.count = 0;
return [2 /*return*/];
}
_g.label = 34;
case 34: return [2 /*return*/];
}
});
});
};
File_t.prototype.draw = function () {
var ofs = 200;
var c = 525;
staticCtx.clearRect(0, 0, BG_RECT.w, BG_RECT.h);
// processing
if (PROCESSING) {
staticCtx.fillStyle = "#000000";
staticCtx.font = "40px garamond";
staticCtx.fillText("Échanges en cours", 390, 50);
}
// piles
this.head.draw(c - ofs, 300);
this.tail.draw(c + ofs, 300);
this.b_head.draw(c - ofs, 600);
this.c_tail.draw(c + ofs, 600);
this.b_1.draw(c - ofs, 900);
this.b_2.draw(c + ofs, 900);
// flèches entrée/sortie
var R = 80;
var ox = c - ofs - 150 / 2 - 5;
var oy = 100;
staticCtx.strokeStyle = "#000000";
staticCtx.beginPath();
staticCtx.moveTo(ox - R, oy);
staticCtx.quadraticCurveTo(ox, oy - R, ox + R, oy);
staticCtx.lineTo(ox + R, oy - 10);
staticCtx.moveTo(ox + R, oy);
staticCtx.lineTo(ox + R - 10, oy);
staticCtx.stroke();
ox = c + ofs + 150 / 2 + 5;
staticCtx.beginPath();
staticCtx.moveTo(ox - R, oy);
staticCtx.quadraticCurveTo(ox, oy - R, ox + R, oy);
staticCtx.lineTo(ox + R, oy - 10);
staticCtx.moveTo(ox + R, oy);
staticCtx.lineTo(ox + R - 10, oy);
staticCtx.stroke();
// explication touches
staticCtx.fillStyle = "#000000";
staticCtx.font = "40px garamond";
if (!LEARNING) {
if (!PROCESSING) {
staticCtx.fillText("'+' : empiler", c - ofs - 300, 150);
staticCtx.fillText("'-' : dépiler", c - ofs - 300, 242);
staticCtx.fillText("'a' : mode apprentissage (off)", c - ofs - 300, 335);
}
}
else {
if (!GLOBAL_PROCESSING) {
staticCtx.fillText("'+' : empiler", c - ofs - 300, 150);
staticCtx.fillText("'-' : dépiler", c - ofs - 300, 242);
staticCtx.fillText("'a' : mode apprentissage (on)", c - ofs - 300, 335);
}
else {
staticCtx.fillText("'Entrée' :", c - ofs - 300, 150);
staticCtx.fillText(" suivant", c - ofs - 300, 200);
staticCtx.fillText("'a' : mode apprentissage (on)", c - ofs - 300, 335);
}
}
// séparation
staticCtx.strokeStyle = "#ff0000";
staticCtx.beginPath();
staticCtx.moveTo(c - ofs - 200, 350);
staticCtx.lineTo(c + ofs + 200, 350);
staticCtx.stroke();
// flèches
console.log("step:", this.stepLevel, "\n");
staticCtx.strokeStyle = "#000000";
if (this.stepLevel === 2 || this.stepLevel === 3) {
this.drawArrow(c - ofs, 610, c - ofs, 700);
this.drawArrow(c - ofs, 610, c + ofs, 700);
}
else if (this.stepLevel == 5) {
this.drawArrow(c + ofs, 610, c + ofs, 700);
}
else if (this.stepLevel === 6) {
this.drawArrow(c + 100, 800, c - 100, 800);
this.drawArrow(c + 100, 800, c - ofs, 610);
}
ctx.clearRect(0, 0, BG_RECT.w, BG_RECT.h);
ctx.drawImage(staticCanvas, 0, 0);
};
File_t.prototype.drawArrow = function (x0, y0, x1, y1) {
staticCtx.beginPath();
staticCtx.moveTo(x0, y0);
staticCtx.lineTo(x1, y1);
var vx = x1 - x0;
var vy = y1 - y0;
var n = Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2));
if (n !== 0) {
var s2 = Math.sqrt(2) / 2;
vx /= -n;
vy /= -n;
var vx1 = s2 * vx + s2 * vy;
var vy1 = -s2 * vx + s2 * vy;
staticCtx.lineTo(x1 + vx1 * 10, y1 + vy1 * 10);
staticCtx.moveTo(x1, y1);
var vx2 = s2 * vx - s2 * vy;
var vy2 = s2 * vx + s2 * vy;
staticCtx.lineTo(x1 + vx2 * 10, y1 + vy2 * 10);
}
staticCtx.stroke();
};
return File_t;
}());
//animation de la file
var FILE = new File_t();
function drawFrame() {
FILE.draw();
}
function animationLoop(currentTime) {
animationFrameId = requestAnimationFrame(animationLoop);
var delaTime = currentTime - lastFrameTime;
if (delaTime < FRAME_INTERVAL)
return;
lastFrameTime = currentTime - (delaTime % FRAME_INTERVAL);
drawFrame();
}
function initEventListener() {
var _this = this;
var handlers = {
handleKeyDown: function (e) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(e.key === '+')) return [3 /*break*/, 3];
if (!(!PROCESSING && !GLOBAL_PROCESSING)) return [3 /*break*/, 2];
PROCESSING = true;
return [4 /*yield*/, FILE.push({
value: Math.floor(Math.random() * 10) + 1,
color: getRandomColor()
})];
case 1:
_a.sent();
PROCESSING = false;
_a.label = 2;
case 2: return [3 /*break*/, 10];
case 3:
if (!(e.key === "-")) return [3 /*break*/, 6];
if (!(!PROCESSING && !GLOBAL_PROCESSING)) return [3 /*break*/, 5];
PROCESSING = true;
return [4 /*yield*/, FILE.pop()];
case 4:
_a.sent();
PROCESSING = false;
_a.label = 5;
case 5: return [3 /*break*/, 10];
case 6:
if (!(e.key === "Enter")) return [3 /*break*/, 9];
if (!(LEARNING && !PROCESSING)) return [3 /*break*/, 8];
PROCESSING = true;
return [4 /*yield*/, FILE.step()];
case 7:
_a.sent();
PROCESSING = false;
_a.label = 8;
case 8: return [3 /*break*/, 10];
case 9:
if (e.key === "a") {
LEARNING = !LEARNING;
FILE.emptyAll();
FILE.stepLevel = 0;
FILE.count = 0;
PROCESSING = false;
GLOBAL_PROCESSING = false;
}
_a.label = 10;
case 10: return [2 /*return*/];
}
});
}); }
};
document.addEventListener('keydown', handlers.handleKeyDown);
callbacks.push(function () {
document.removeEventListener('keydown', handlers.handleKeyDown);
});
}
function getRandomColor() {
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
}
function initDisplay() {
initEventListener();
requestAnimationFrame(animationLoop);
window.cleanup = cleanup;
}
function cleanup() {
cancelAnimationFrame(animationFrameId);
callbacks.forEach(function (fn) { return fn(); });
}
if (typeof window !== 'undefined') {
initDisplay();
}