/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Database = Container.expand(function (id) { var self = Container.call(this); var databaseGraphics = self.attachAsset('database', { anchorX: 0.5, anchorY: 0.5 }); var idText = new Text2("DB " + id, { size: 48, fill: 0x000000 }); idText.anchor.set(0.5, 0.5); idText.y = -245; self.addChild(idText); var countText = new Text2("0/10", { size: 40, fill: 0xFFFFFF }); countText.anchor.set(0.5, 0.5); countText.y = 255; self.addChild(countText); self.id = id; self.numbers = []; self.maxCapacity = 10; self.storedCubes = []; self.addNumber = function (number) { if (self.numbers.length < self.maxCapacity) { self.numbers.push(number); totalNumbersInDB++; totalCubesStored++; // Create cube for visual representation var cube = new StoredCube(number); var row = Math.floor((self.numbers.length - 1) / 5); var col = (self.numbers.length - 1) % 5; cube.x = -160 + col * 80; cube.y = 163 - row * 80; // Start from bottom and build up self.storedCubes.push(cube); self.addChild(cube); self.updateDisplay(); return true; } return false; }; self.removeNumber = function (value) { for (var i = 0; i < self.numbers.length; i++) { if (self.numbers[i] === value) { self.numbers.splice(i, 1); totalNumbersInDB--; // Remove corresponding cube if (self.storedCubes[i]) { self.storedCubes[i].destroy(); self.storedCubes.splice(i, 1); } // Reposition remaining cubes for (var j = 0; j < self.storedCubes.length; j++) { var row = Math.floor(j / 5); var col = j % 5; self.storedCubes[j].x = -160 + col * 80; self.storedCubes[j].y = 163 - row * 80; } self.updateDisplay(); return true; } } return false; }; self.hasNumber = function (value) { return self.numbers.indexOf(value) !== -1; }; self.updateDisplay = function () { countText.setText(self.numbers.length + "/10"); if (self.numbers.length >= self.maxCapacity) { databaseGraphics.tint = 0xFF0000; } else { databaseGraphics.tint = 0xFFFFFF; } }; return self; }); var Number = Container.expand(function (value) { var self = Container.call(this); var numberGraphics = self.attachAsset('number', { anchorX: 0.5, anchorY: 0.5 }); var numberText = new Text2(value.toString(), { size: 64, fill: 0xFFFFFF }); numberText.anchor.set(0.5, 0.5); self.addChild(numberText); self.value = value; self.speed = 2; self.isDragging = false; self.isStopped = false; self.update = function () { if (!self.isDragging && !self.isStopped) { // Check if should stop at hash background if (self.y >= conveyorStopY) { self.y = conveyorStopY; self.isStopped = true; } else { // Check collision with object below var blocked = false; for (var i = 0; i < numbers.length; i++) { var other = numbers[i]; if (other !== self && other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) { blocked = true; break; } } for (var i = 0; i < queries.length; i++) { var other = queries[i]; if (other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) { blocked = true; break; } } if (!blocked) { self.y += self.speed; } } } }; self.down = function (x, y, obj) { self.isDragging = true; draggedNumber = self; }; return self; }); var Query = Container.expand(function (value) { var self = Container.call(this); var queryGraphics = self.attachAsset('query', { anchorX: 0.5, anchorY: 0.5 }); var queryText = new Text2("SELECT: " + value, { size: 48, fill: 0x000000 }); queryText.anchor.set(0.5, 0.5); self.addChild(queryText); self.value = value; self.speed = 1.5; self.isStopped = false; self.update = function () { if (!self.isStopped) { // Check if should stop at hash background if (self.y >= conveyorStopY) { self.y = conveyorStopY; self.isStopped = true; } else { // Check collision with object below var blocked = false; for (var i = 0; i < numbers.length; i++) { var other = numbers[i]; if (other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) { blocked = true; break; } } for (var i = 0; i < queries.length; i++) { var other = queries[i]; if (other !== self && other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) { blocked = true; break; } } if (!blocked) { self.y += self.speed; } } } }; return self; }); var SortButton = Container.expand(function (database) { var self = Container.call(this); var buttonGraphics = self.attachAsset('sortButton', { anchorX: 0.5, anchorY: 0.5 }); self.database = database; self.down = function (x, y, obj) { if (LK.getScore() >= 50) { // Deduct score LK.setScore(LK.getScore() - 50); scoreText.setText("Score: " + LK.getScore()); // Sort database numbers self.database.numbers.sort(function (a, b) { return a - b; }); // Update cube positions for (var i = 0; i < self.database.storedCubes.length; i++) { var row = Math.floor(i / 5); var col = i % 5; self.database.storedCubes[i].x = -160 + col * 80; self.database.storedCubes[i].y = 163 - row * 80; // Update cube value display self.database.storedCubes[i].text.setText(self.database.numbers[i].toString()); self.database.storedCubes[i].value = self.database.numbers[i]; } // Increment sorted cubes counter cubesSortedCount += self.database.storedCubes.length; // Check if we should change hash rule (every 5 cubes sorted) if (cubesSortedCount >= 5) { cubesSortedCount = 0; // Reset counter changeHashFunction(); } LK.getSound('sort').play(); } else { LK.getSound('error').play(); } }; return self; }); var StoredCube = Container.expand(function (value) { var self = Container.call(this); var cubeGraphics = self.attachAsset('number', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); var cubeText = new Text2(value.toString(), { size: 38, fill: 0xFFFFFF }); cubeText.anchor.set(0.5, 0.5); self.addChild(cubeText); self.value = value; self.text = cubeText; // Store reference to text object self.isDragging = false; self.down = function (x, y, obj) { self.isDragging = true; draggedStoredCube = self; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 }); /**** * Game Code ****/ var conveyor = game.attachAsset('conveyor', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); var databases = []; var numbers = []; var queries = []; var draggedNumber = null; var draggedStoredCube = null; // Hash functions var hashFunctions = [{ name: "x % 6", func: function func(x) { return x % 6; } }, { name: "x % 5", func: function func(x) { return x % 5; } }, { name: "(x / 2) % 6", func: function func(x) { return Math.floor(x / 2) % 6; } }, { name: "(x + 1) % 4", func: function func(x) { return (x + 1) % 4; } }, { name: "x % 4", func: function func(x) { return x % 4; } }, { name: "(x + 5) % 5", func: function func(x) { return (x + 5) % 5; } }, { name: "(x + 2) % 6", func: function func(x) { return (x + 2) % 6; } }, { name: "(x + 1) % 4", func: function func(x) { return (x + 1) % 4; } }, { name: "(x + 3) % 5", func: function func(x) { return (x + 3) % 5; } }, { name: "(x - 1) % 6", func: function func(x) { return Math.abs(x - 1) % 6; } }, { name: "(x - 3) % 2", func: function func(x) { return Math.floor(Math.abs(x - 3) % 2); } }, { name: "(x + 4) % 3", func: function func(x) { return (x + 4) % 3; } }, { name: "x / 5", func: function func(x) { return Math.floor(x / 5); } }, { name: "(x + 5) % 6", func: function func(x) { return (x + 5) % 6; } }, { name: "(x / 2) % 6", func: function func(x) { return Math.floor(x / 2) % 6; } }, { name: "x / 4", func: function func(x) { return Math.floor(x / 4); } }, { name: "(x + x) % 4", func: function func(x) { return Math.floor((x + x) % 4); } }, { name: "(x - 2) % 5", func: function func(x) { return Math.abs(x - 2) % 5; } }, { name: "(x / 3) % 5", func: function func(x) { return Math.floor(x / 3) % 5; } }, { name: "(x / 3) % 6", func: function func(x) { return Math.floor(x / 3) % 6; } }, { name: "(x + 6) % 6", func: function func(x) { return Math.floor((x + 6) % 4); } }, { name: "(x - 3) % 5", func: function func(x) { return Math.abs(x - 3) % 5; } }, { name: "(x / 2) % 6", func: function func(x) { return Math.floor(x / 2) % 6; } }, { name: "(x + 7) % 5", func: function func(x) { return Math.floor((x + 7) % 5); } }, { name: "(x - 6) % 6", func: function func(x) { return Math.abs(x - 6) % 6; } }, { name: "(x - 4) % 6", func: function func(x) { return Math.floor(Math.abs(x - 4) % 6); } }, { name: "x % 6", func: function func(x) { return Math.floor(x % 6); } }, { name: "(x - 6) % 6", func: function func(x) { return Math.abs(x - 6) % 6; } }]; var currentHashIndex = Math.floor(Math.random() * hashFunctions.length); var currentHash = hashFunctions[currentHashIndex]; // Create databases for (var i = 0; i < 6; i++) { var db = new Database(i); if (i < 3) { // Left side databases db.x = 300; db.y = 600 + i * 700; } else { // Right side databases db.x = 1748; db.y = 600 + (i - 3) * 700; } databases.push(db); game.addChild(db); // Add sort button for each database var sortButton = new SortButton(db); if (i < 3) { // Left side databases - button on the right sortButton.x = db.x + 350; sortButton.y = db.y; } else { // Right side databases - button on the left sortButton.x = db.x - 350; sortButton.y = db.y; } game.addChild(sortButton); // Add price text under sort button var priceText = new Text2("50pts", { size: 32, fill: 0xFFFFFF }); priceText.anchor.set(0.5, 0.5); priceText.x = sortButton.x; priceText.y = sortButton.y + 130; game.addChild(priceText); } // UI Elements var hashBackground = game.attachAsset('hashBackground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2600 }); var hashText = new Text2("Hash Rule: " + currentHash.name, { size: 96, fill: 0xFFFFFF }); hashText.anchor.set(0.5, 0.5); hashText.x = 1024; hashText.y = 2600; game.addChild(hashText); var scoreText = new Text2("Score: 0", { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var gameSpeed = 1; var numberSpawnRate = 230; // Faster spawn until 15 numbers var querySpawnRate = 1100; var hashChangeRate = 1800; var totalNumbersInDB = 0; var conveyorStopY = 2480; // Y position where items stop at hash background var cubesSortedCount = 0; // Track how many cubes have been sorted var totalCubesStored = 0; // Track total cubes stored in databases var totalQueriesAnswered = 0; // Track total queries answered correctly var totalSortingAttempts = 0; // Track total sorting attempts var successfulSortingAttempts = 0; // Track successful sorting attempts var stuckElements = []; // Track elements that are stuck var stuckStartTime = null; // Time when 9+ elements first became stuck var STUCK_THRESHOLD = 9; // Number of stuck elements needed for game over var STUCK_DURATION = 120; // 2 seconds at 60 FPS // Game timers var numberTimer = 0; var queryTimer = 0; var hashTimer = 0; function spawnNumber() { var value = Math.floor(Math.random() * 20) + 1; var number = new Number(value); number.x = 1024; number.y = -50; numbers.push(number); game.addChild(number); } function spawnQuery() { // Only spawn queries if total DB count is at least 10 if (totalNumbersInDB < 10) { return; } // Get all numbers currently stored in databases var availableNumbers = []; for (var i = 0; i < databases.length; i++) { for (var j = 0; j < databases[i].numbers.length; j++) { availableNumbers.push(databases[i].numbers[j]); } } // Only spawn query if there are numbers in databases if (availableNumbers.length > 0) { var randomIndex = Math.floor(Math.random() * availableNumbers.length); var value = availableNumbers[randomIndex]; var query = new Query(value); query.x = 1024; query.y = -50; queries.push(query); game.addChild(query); } } function changeHashFunction() { // Select random hash function var newHashIndex = Math.floor(Math.random() * hashFunctions.length); // Make sure we don't pick the same hash function while (newHashIndex === currentHashIndex && hashFunctions.length > 1) { newHashIndex = Math.floor(Math.random() * hashFunctions.length); } currentHashIndex = newHashIndex; currentHash = hashFunctions[currentHashIndex]; hashText.setText("Hash Rule: " + currentHash.name); // Flash the hash text tween(hashText, { tint: 0xFF0000 }, { duration: 200 }); tween(hashText, { tint: 0xFFFFFF }, { duration: 200 }); } function getCorrectDatabase(value) { var dbIndex = currentHash.func(value); return databases[dbIndex]; } function handleNumberDrop(number) { var correctDb = getCorrectDatabase(number.value); var closestDb = null; var minDistance = Infinity; // Find closest database for (var i = 0; i < databases.length; i++) { var distance = Math.sqrt(Math.pow(number.x - databases[i].x, 2) + Math.pow(number.y - databases[i].y, 2)); if (distance < minDistance) { minDistance = distance; closestDb = databases[i]; } } if (closestDb && minDistance < 300) { totalSortingAttempts++; if (closestDb === correctDb) { // Correct placement if (closestDb.addNumber(number.value)) { successfulSortingAttempts++; LK.setScore(LK.getScore() + 10); scoreText.setText("Score: " + LK.getScore()); LK.getSound('sort').play(); // Remove number from game var index = numbers.indexOf(number); if (index > -1) { numbers.splice(index, 1); } number.destroy(); return true; } else { // Database full LK.getSound('error').play(); LK.showGameOver(); return false; } } else { // Wrong placement LK.getSound('error').play(); LK.setScore(Math.max(0, LK.getScore() - 5)); scoreText.setText("Score: " + LK.getScore()); } } return false; } function handleQueryFulfillment(number) { var closestQuery = null; var minDistance = Infinity; // Find closest query for (var i = 0; i < queries.length; i++) { var distance = Math.sqrt(Math.pow(number.x - queries[i].x, 2) + Math.pow(number.y - queries[i].y, 2)); if (distance < minDistance) { minDistance = distance; closestQuery = queries[i]; } } if (closestQuery && minDistance < 200) { if (closestQuery.value === number.value) { // Correct query fulfillment LK.setScore(LK.getScore() + 20); scoreText.setText("Score: " + LK.getScore()); LK.getSound('query').play(); totalQueriesAnswered++; // Remove query and number var queryIndex = queries.indexOf(closestQuery); if (queryIndex > -1) { queries.splice(queryIndex, 1); } closestQuery.destroy(); // Find and remove from database var correctDb = getCorrectDatabase(number.value); correctDb.removeNumber(number.value); var numberIndex = numbers.indexOf(number); if (numberIndex > -1) { numbers.splice(numberIndex, 1); } number.destroy(); return true; } } return false; } function handleStoredCubeQueryFulfillment(cube) { var closestQuery = null; var minDistance = Infinity; // Find closest query for (var i = 0; i < queries.length; i++) { var distance = Math.sqrt(Math.pow(cube.x - queries[i].x, 2) + Math.pow(cube.y - queries[i].y, 2)); if (distance < minDistance) { minDistance = distance; closestQuery = queries[i]; } } if (closestQuery && minDistance < 200) { if (closestQuery.value === cube.value) { // Correct query fulfillment LK.setScore(LK.getScore() + 20); scoreText.setText("Score: " + LK.getScore()); LK.getSound('query').play(); totalQueriesAnswered++; // Remove query var queryIndex = queries.indexOf(closestQuery); if (queryIndex > -1) { queries.splice(queryIndex, 1); } closestQuery.destroy(); // Find and remove cube from database for (var j = 0; j < databases.length; j++) { if (databases[j].removeNumber(cube.value)) { break; } } return true; } } return false; } game.move = function (x, y, obj) { if (draggedNumber) { draggedNumber.x = x; draggedNumber.y = y; } if (draggedStoredCube) { draggedStoredCube.x = x; draggedStoredCube.y = y; } }; game.up = function (x, y, obj) { if (draggedNumber) { var handled = false; // Try to fulfill query first if (!handleQueryFulfillment(draggedNumber)) { // Try to place in database handled = handleNumberDrop(draggedNumber); } // Reset position if not handled if (!handled) { draggedNumber.x = 1024; draggedNumber.y = draggedNumber.y; } draggedNumber.isDragging = false; draggedNumber = null; } if (draggedStoredCube) { var handled = false; // Try to fulfill query with stored cube if (handleStoredCubeQueryFulfillment(draggedStoredCube)) { handled = true; } // Reset position if not handled if (!handled) { // Find parent database and reset position for (var i = 0; i < databases.length; i++) { for (var j = 0; j < databases[i].storedCubes.length; j++) { if (databases[i].storedCubes[j] === draggedStoredCube) { var row = Math.floor(j / 5); var col = j % 5; draggedStoredCube.x = -160 + col * 80; draggedStoredCube.y = 163 - row * 80; break; } } } } draggedStoredCube.isDragging = false; draggedStoredCube = null; } }; game.update = function () { // Update timers numberTimer++; queryTimer++; hashTimer++; // Adjust number spawn rate based on total DB count - slow down as game progresses var currentNumberSpawnRate = totalNumbersInDB < 15 ? 230 : Math.min(460 + (totalNumbersInDB - 15) * 20, 690); // Much faster spawn rate after 400 points if (LK.getScore() >= 400) { currentNumberSpawnRate = Math.floor(currentNumberSpawnRate / 3); } // Spawn numbers if (numberTimer >= currentNumberSpawnRate / gameSpeed) { spawnNumber(); numberTimer = 0; } // Spawn queries with increased rate after 15 numbers var currentQuerySpawnRate = totalNumbersInDB >= 15 ? 950 : querySpawnRate; // Much faster spawn rate after 400 points if (LK.getScore() >= 400) { currentQuerySpawnRate = Math.floor(currentQuerySpawnRate / 3); } if (queryTimer >= currentQuerySpawnRate / gameSpeed) { spawnQuery(); queryTimer = 0; } // Change hash function if (hashTimer >= hashChangeRate) { changeHashFunction(); hashTimer = 0; } // Check for game over condition - items stacked above 33% of assembly line (50% more space) var conveyorTriggerPoint = 200; // Almost at the top of the page var itemsAboveTrigger = 0; for (var i = 0; i < numbers.length; i++) { if (numbers[i].y < conveyorTriggerPoint && numbers[i].isStopped) { itemsAboveTrigger++; } } for (var i = 0; i < queries.length; i++) { if (queries[i].y < conveyorTriggerPoint && queries[i].isStopped) { itemsAboveTrigger++; } } if (itemsAboveTrigger > 0) { // Display statistics before game over var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, { size: 60, fill: 0xFFFFFF }); statsText.anchor.set(0.5, 0.5); statsText.x = 1024; statsText.y = 1366; game.addChild(statsText); // Create black background sized for score display var blackBackground = game.attachAsset('conveyor', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: statsText.width + 40, height: statsText.height + 40, scaleX: 1, scaleY: 1 }); blackBackground.tint = 0x000000; game.addChild(blackBackground); // Move stats text to front game.addChild(statsText); // Show stats for 5 seconds before game over LK.setTimeout(function () { LK.showGameOver(); }, 5000); return; } // Update numbers for (var i = numbers.length - 1; i >= 0; i--) { var number = numbers[i]; // Check if number went off screen if (number.y > 2800) { number.destroy(); numbers.splice(i, 1); continue; } // Check database overflow for (var j = 0; j < databases.length; j++) { if (databases[j].numbers.length >= databases[j].maxCapacity) { // Display statistics before game over var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, { size: 60, fill: 0xFFFFFF }); statsText.anchor.set(0.5, 0.5); statsText.x = 1024; statsText.y = 1366; game.addChild(statsText); // Create black background sized for score display var blackBackground = game.attachAsset('conveyor', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: statsText.width + 40, height: statsText.height + 40, scaleX: 1, scaleY: 1 }); blackBackground.tint = 0x000000; game.addChild(blackBackground); // Move stats text to front game.addChild(statsText); // Show stats for 5 seconds before game over LK.setTimeout(function () { LK.showGameOver(); }, 5000); return; } } } // Update queries for (var i = queries.length - 1; i >= 0; i--) { var query = queries[i]; // Check if query went off screen if (query.y > 2800) { query.destroy(); queries.splice(i, 1); // Penalty for missed query LK.setScore(Math.max(0, LK.getScore() - 10)); scoreText.setText("Score: " + LK.getScore()); } } // Check for game over condition - more than 11 items on assembly line var totalItemsOnLine = numbers.length + queries.length; if (totalItemsOnLine > 11) { // Display statistics before game over var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, { size: 60, fill: 0xFFFFFF }); statsText.anchor.set(0.5, 0.5); statsText.x = 1024; statsText.y = 1366; game.addChild(statsText); // Create black background sized for score display var blackBackground = game.attachAsset('conveyor', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: statsText.width + 40, height: statsText.height + 40, scaleX: 1, scaleY: 1 }); blackBackground.tint = 0x000000; game.addChild(blackBackground); // Move stats text to front game.addChild(statsText); // Show stats for 5 seconds before game over LK.setTimeout(function () { LK.showGameOver(); }, 5000); return; } // Track stuck elements for game over condition stuckElements = []; // Check for stuck numbers for (var i = 0; i < numbers.length; i++) { var number = numbers[i]; if (number.isStopped) { stuckElements.push(number); } } // Check for stuck queries for (var i = 0; i < queries.length; i++) { var query = queries[i]; if (query.isStopped) { stuckElements.push(query); } } // Check if we have 9 or more stuck elements if (stuckElements.length >= STUCK_THRESHOLD) { if (stuckStartTime === null) { stuckStartTime = LK.ticks; // Start timing } else if (LK.ticks - stuckStartTime >= STUCK_DURATION) { // 9+ elements have been stuck for more than 2 seconds // Display statistics before game over var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, { size: 60, fill: 0xFFFFFF }); statsText.anchor.set(0.5, 0.5); statsText.x = 1024; statsText.y = 1366; game.addChild(statsText); // Create black background sized for score display var blackBackground = game.attachAsset('conveyor', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: statsText.width + 40, height: statsText.height + 40, scaleX: 1, scaleY: 1 }); blackBackground.tint = 0x000000; game.addChild(blackBackground); // Move stats text to front game.addChild(statsText); // Show stats for 5 seconds before game over LK.setTimeout(function () { LK.showGameOver(); }, 5000); return; } } else { stuckStartTime = null; // Reset timer if less than 9 elements are stuck } // Increase game speed over time if (LK.ticks % 1800 === 0) { gameSpeed = Math.min(gameSpeed + 0.1, 3); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Database = Container.expand(function (id) {
var self = Container.call(this);
var databaseGraphics = self.attachAsset('database', {
anchorX: 0.5,
anchorY: 0.5
});
var idText = new Text2("DB " + id, {
size: 48,
fill: 0x000000
});
idText.anchor.set(0.5, 0.5);
idText.y = -245;
self.addChild(idText);
var countText = new Text2("0/10", {
size: 40,
fill: 0xFFFFFF
});
countText.anchor.set(0.5, 0.5);
countText.y = 255;
self.addChild(countText);
self.id = id;
self.numbers = [];
self.maxCapacity = 10;
self.storedCubes = [];
self.addNumber = function (number) {
if (self.numbers.length < self.maxCapacity) {
self.numbers.push(number);
totalNumbersInDB++;
totalCubesStored++;
// Create cube for visual representation
var cube = new StoredCube(number);
var row = Math.floor((self.numbers.length - 1) / 5);
var col = (self.numbers.length - 1) % 5;
cube.x = -160 + col * 80;
cube.y = 163 - row * 80; // Start from bottom and build up
self.storedCubes.push(cube);
self.addChild(cube);
self.updateDisplay();
return true;
}
return false;
};
self.removeNumber = function (value) {
for (var i = 0; i < self.numbers.length; i++) {
if (self.numbers[i] === value) {
self.numbers.splice(i, 1);
totalNumbersInDB--;
// Remove corresponding cube
if (self.storedCubes[i]) {
self.storedCubes[i].destroy();
self.storedCubes.splice(i, 1);
}
// Reposition remaining cubes
for (var j = 0; j < self.storedCubes.length; j++) {
var row = Math.floor(j / 5);
var col = j % 5;
self.storedCubes[j].x = -160 + col * 80;
self.storedCubes[j].y = 163 - row * 80;
}
self.updateDisplay();
return true;
}
}
return false;
};
self.hasNumber = function (value) {
return self.numbers.indexOf(value) !== -1;
};
self.updateDisplay = function () {
countText.setText(self.numbers.length + "/10");
if (self.numbers.length >= self.maxCapacity) {
databaseGraphics.tint = 0xFF0000;
} else {
databaseGraphics.tint = 0xFFFFFF;
}
};
return self;
});
var Number = Container.expand(function (value) {
var self = Container.call(this);
var numberGraphics = self.attachAsset('number', {
anchorX: 0.5,
anchorY: 0.5
});
var numberText = new Text2(value.toString(), {
size: 64,
fill: 0xFFFFFF
});
numberText.anchor.set(0.5, 0.5);
self.addChild(numberText);
self.value = value;
self.speed = 2;
self.isDragging = false;
self.isStopped = false;
self.update = function () {
if (!self.isDragging && !self.isStopped) {
// Check if should stop at hash background
if (self.y >= conveyorStopY) {
self.y = conveyorStopY;
self.isStopped = true;
} else {
// Check collision with object below
var blocked = false;
for (var i = 0; i < numbers.length; i++) {
var other = numbers[i];
if (other !== self && other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) {
blocked = true;
break;
}
}
for (var i = 0; i < queries.length; i++) {
var other = queries[i];
if (other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) {
blocked = true;
break;
}
}
if (!blocked) {
self.y += self.speed;
}
}
}
};
self.down = function (x, y, obj) {
self.isDragging = true;
draggedNumber = self;
};
return self;
});
var Query = Container.expand(function (value) {
var self = Container.call(this);
var queryGraphics = self.attachAsset('query', {
anchorX: 0.5,
anchorY: 0.5
});
var queryText = new Text2("SELECT: " + value, {
size: 48,
fill: 0x000000
});
queryText.anchor.set(0.5, 0.5);
self.addChild(queryText);
self.value = value;
self.speed = 1.5;
self.isStopped = false;
self.update = function () {
if (!self.isStopped) {
// Check if should stop at hash background
if (self.y >= conveyorStopY) {
self.y = conveyorStopY;
self.isStopped = true;
} else {
// Check collision with object below
var blocked = false;
for (var i = 0; i < numbers.length; i++) {
var other = numbers[i];
if (other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) {
blocked = true;
break;
}
}
for (var i = 0; i < queries.length; i++) {
var other = queries[i];
if (other !== self && other.y > self.y && other.y < self.y + 200 && Math.abs(other.x - self.x) < 100) {
blocked = true;
break;
}
}
if (!blocked) {
self.y += self.speed;
}
}
}
};
return self;
});
var SortButton = Container.expand(function (database) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('sortButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.database = database;
self.down = function (x, y, obj) {
if (LK.getScore() >= 50) {
// Deduct score
LK.setScore(LK.getScore() - 50);
scoreText.setText("Score: " + LK.getScore());
// Sort database numbers
self.database.numbers.sort(function (a, b) {
return a - b;
});
// Update cube positions
for (var i = 0; i < self.database.storedCubes.length; i++) {
var row = Math.floor(i / 5);
var col = i % 5;
self.database.storedCubes[i].x = -160 + col * 80;
self.database.storedCubes[i].y = 163 - row * 80;
// Update cube value display
self.database.storedCubes[i].text.setText(self.database.numbers[i].toString());
self.database.storedCubes[i].value = self.database.numbers[i];
}
// Increment sorted cubes counter
cubesSortedCount += self.database.storedCubes.length;
// Check if we should change hash rule (every 5 cubes sorted)
if (cubesSortedCount >= 5) {
cubesSortedCount = 0; // Reset counter
changeHashFunction();
}
LK.getSound('sort').play();
} else {
LK.getSound('error').play();
}
};
return self;
});
var StoredCube = Container.expand(function (value) {
var self = Container.call(this);
var cubeGraphics = self.attachAsset('number', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var cubeText = new Text2(value.toString(), {
size: 38,
fill: 0xFFFFFF
});
cubeText.anchor.set(0.5, 0.5);
self.addChild(cubeText);
self.value = value;
self.text = cubeText; // Store reference to text object
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
draggedStoredCube = self;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var conveyor = game.attachAsset('conveyor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var databases = [];
var numbers = [];
var queries = [];
var draggedNumber = null;
var draggedStoredCube = null;
// Hash functions
var hashFunctions = [{
name: "x % 6",
func: function func(x) {
return x % 6;
}
}, {
name: "x % 5",
func: function func(x) {
return x % 5;
}
}, {
name: "(x / 2) % 6",
func: function func(x) {
return Math.floor(x / 2) % 6;
}
}, {
name: "(x + 1) % 4",
func: function func(x) {
return (x + 1) % 4;
}
}, {
name: "x % 4",
func: function func(x) {
return x % 4;
}
}, {
name: "(x + 5) % 5",
func: function func(x) {
return (x + 5) % 5;
}
}, {
name: "(x + 2) % 6",
func: function func(x) {
return (x + 2) % 6;
}
}, {
name: "(x + 1) % 4",
func: function func(x) {
return (x + 1) % 4;
}
}, {
name: "(x + 3) % 5",
func: function func(x) {
return (x + 3) % 5;
}
}, {
name: "(x - 1) % 6",
func: function func(x) {
return Math.abs(x - 1) % 6;
}
}, {
name: "(x - 3) % 2",
func: function func(x) {
return Math.floor(Math.abs(x - 3) % 2);
}
}, {
name: "(x + 4) % 3",
func: function func(x) {
return (x + 4) % 3;
}
}, {
name: "x / 5",
func: function func(x) {
return Math.floor(x / 5);
}
}, {
name: "(x + 5) % 6",
func: function func(x) {
return (x + 5) % 6;
}
}, {
name: "(x / 2) % 6",
func: function func(x) {
return Math.floor(x / 2) % 6;
}
}, {
name: "x / 4",
func: function func(x) {
return Math.floor(x / 4);
}
}, {
name: "(x + x) % 4",
func: function func(x) {
return Math.floor((x + x) % 4);
}
}, {
name: "(x - 2) % 5",
func: function func(x) {
return Math.abs(x - 2) % 5;
}
}, {
name: "(x / 3) % 5",
func: function func(x) {
return Math.floor(x / 3) % 5;
}
}, {
name: "(x / 3) % 6",
func: function func(x) {
return Math.floor(x / 3) % 6;
}
}, {
name: "(x + 6) % 6",
func: function func(x) {
return Math.floor((x + 6) % 4);
}
}, {
name: "(x - 3) % 5",
func: function func(x) {
return Math.abs(x - 3) % 5;
}
}, {
name: "(x / 2) % 6",
func: function func(x) {
return Math.floor(x / 2) % 6;
}
}, {
name: "(x + 7) % 5",
func: function func(x) {
return Math.floor((x + 7) % 5);
}
}, {
name: "(x - 6) % 6",
func: function func(x) {
return Math.abs(x - 6) % 6;
}
}, {
name: "(x - 4) % 6",
func: function func(x) {
return Math.floor(Math.abs(x - 4) % 6);
}
}, {
name: "x % 6",
func: function func(x) {
return Math.floor(x % 6);
}
}, {
name: "(x - 6) % 6",
func: function func(x) {
return Math.abs(x - 6) % 6;
}
}];
var currentHashIndex = Math.floor(Math.random() * hashFunctions.length);
var currentHash = hashFunctions[currentHashIndex];
// Create databases
for (var i = 0; i < 6; i++) {
var db = new Database(i);
if (i < 3) {
// Left side databases
db.x = 300;
db.y = 600 + i * 700;
} else {
// Right side databases
db.x = 1748;
db.y = 600 + (i - 3) * 700;
}
databases.push(db);
game.addChild(db);
// Add sort button for each database
var sortButton = new SortButton(db);
if (i < 3) {
// Left side databases - button on the right
sortButton.x = db.x + 350;
sortButton.y = db.y;
} else {
// Right side databases - button on the left
sortButton.x = db.x - 350;
sortButton.y = db.y;
}
game.addChild(sortButton);
// Add price text under sort button
var priceText = new Text2("50pts", {
size: 32,
fill: 0xFFFFFF
});
priceText.anchor.set(0.5, 0.5);
priceText.x = sortButton.x;
priceText.y = sortButton.y + 130;
game.addChild(priceText);
}
// UI Elements
var hashBackground = game.attachAsset('hashBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2600
});
var hashText = new Text2("Hash Rule: " + currentHash.name, {
size: 96,
fill: 0xFFFFFF
});
hashText.anchor.set(0.5, 0.5);
hashText.x = 1024;
hashText.y = 2600;
game.addChild(hashText);
var scoreText = new Text2("Score: 0", {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var gameSpeed = 1;
var numberSpawnRate = 230; // Faster spawn until 15 numbers
var querySpawnRate = 1100;
var hashChangeRate = 1800;
var totalNumbersInDB = 0;
var conveyorStopY = 2480; // Y position where items stop at hash background
var cubesSortedCount = 0; // Track how many cubes have been sorted
var totalCubesStored = 0; // Track total cubes stored in databases
var totalQueriesAnswered = 0; // Track total queries answered correctly
var totalSortingAttempts = 0; // Track total sorting attempts
var successfulSortingAttempts = 0; // Track successful sorting attempts
var stuckElements = []; // Track elements that are stuck
var stuckStartTime = null; // Time when 9+ elements first became stuck
var STUCK_THRESHOLD = 9; // Number of stuck elements needed for game over
var STUCK_DURATION = 120; // 2 seconds at 60 FPS
// Game timers
var numberTimer = 0;
var queryTimer = 0;
var hashTimer = 0;
function spawnNumber() {
var value = Math.floor(Math.random() * 20) + 1;
var number = new Number(value);
number.x = 1024;
number.y = -50;
numbers.push(number);
game.addChild(number);
}
function spawnQuery() {
// Only spawn queries if total DB count is at least 10
if (totalNumbersInDB < 10) {
return;
}
// Get all numbers currently stored in databases
var availableNumbers = [];
for (var i = 0; i < databases.length; i++) {
for (var j = 0; j < databases[i].numbers.length; j++) {
availableNumbers.push(databases[i].numbers[j]);
}
}
// Only spawn query if there are numbers in databases
if (availableNumbers.length > 0) {
var randomIndex = Math.floor(Math.random() * availableNumbers.length);
var value = availableNumbers[randomIndex];
var query = new Query(value);
query.x = 1024;
query.y = -50;
queries.push(query);
game.addChild(query);
}
}
function changeHashFunction() {
// Select random hash function
var newHashIndex = Math.floor(Math.random() * hashFunctions.length);
// Make sure we don't pick the same hash function
while (newHashIndex === currentHashIndex && hashFunctions.length > 1) {
newHashIndex = Math.floor(Math.random() * hashFunctions.length);
}
currentHashIndex = newHashIndex;
currentHash = hashFunctions[currentHashIndex];
hashText.setText("Hash Rule: " + currentHash.name);
// Flash the hash text
tween(hashText, {
tint: 0xFF0000
}, {
duration: 200
});
tween(hashText, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
function getCorrectDatabase(value) {
var dbIndex = currentHash.func(value);
return databases[dbIndex];
}
function handleNumberDrop(number) {
var correctDb = getCorrectDatabase(number.value);
var closestDb = null;
var minDistance = Infinity;
// Find closest database
for (var i = 0; i < databases.length; i++) {
var distance = Math.sqrt(Math.pow(number.x - databases[i].x, 2) + Math.pow(number.y - databases[i].y, 2));
if (distance < minDistance) {
minDistance = distance;
closestDb = databases[i];
}
}
if (closestDb && minDistance < 300) {
totalSortingAttempts++;
if (closestDb === correctDb) {
// Correct placement
if (closestDb.addNumber(number.value)) {
successfulSortingAttempts++;
LK.setScore(LK.getScore() + 10);
scoreText.setText("Score: " + LK.getScore());
LK.getSound('sort').play();
// Remove number from game
var index = numbers.indexOf(number);
if (index > -1) {
numbers.splice(index, 1);
}
number.destroy();
return true;
} else {
// Database full
LK.getSound('error').play();
LK.showGameOver();
return false;
}
} else {
// Wrong placement
LK.getSound('error').play();
LK.setScore(Math.max(0, LK.getScore() - 5));
scoreText.setText("Score: " + LK.getScore());
}
}
return false;
}
function handleQueryFulfillment(number) {
var closestQuery = null;
var minDistance = Infinity;
// Find closest query
for (var i = 0; i < queries.length; i++) {
var distance = Math.sqrt(Math.pow(number.x - queries[i].x, 2) + Math.pow(number.y - queries[i].y, 2));
if (distance < minDistance) {
minDistance = distance;
closestQuery = queries[i];
}
}
if (closestQuery && minDistance < 200) {
if (closestQuery.value === number.value) {
// Correct query fulfillment
LK.setScore(LK.getScore() + 20);
scoreText.setText("Score: " + LK.getScore());
LK.getSound('query').play();
totalQueriesAnswered++;
// Remove query and number
var queryIndex = queries.indexOf(closestQuery);
if (queryIndex > -1) {
queries.splice(queryIndex, 1);
}
closestQuery.destroy();
// Find and remove from database
var correctDb = getCorrectDatabase(number.value);
correctDb.removeNumber(number.value);
var numberIndex = numbers.indexOf(number);
if (numberIndex > -1) {
numbers.splice(numberIndex, 1);
}
number.destroy();
return true;
}
}
return false;
}
function handleStoredCubeQueryFulfillment(cube) {
var closestQuery = null;
var minDistance = Infinity;
// Find closest query
for (var i = 0; i < queries.length; i++) {
var distance = Math.sqrt(Math.pow(cube.x - queries[i].x, 2) + Math.pow(cube.y - queries[i].y, 2));
if (distance < minDistance) {
minDistance = distance;
closestQuery = queries[i];
}
}
if (closestQuery && minDistance < 200) {
if (closestQuery.value === cube.value) {
// Correct query fulfillment
LK.setScore(LK.getScore() + 20);
scoreText.setText("Score: " + LK.getScore());
LK.getSound('query').play();
totalQueriesAnswered++;
// Remove query
var queryIndex = queries.indexOf(closestQuery);
if (queryIndex > -1) {
queries.splice(queryIndex, 1);
}
closestQuery.destroy();
// Find and remove cube from database
for (var j = 0; j < databases.length; j++) {
if (databases[j].removeNumber(cube.value)) {
break;
}
}
return true;
}
}
return false;
}
game.move = function (x, y, obj) {
if (draggedNumber) {
draggedNumber.x = x;
draggedNumber.y = y;
}
if (draggedStoredCube) {
draggedStoredCube.x = x;
draggedStoredCube.y = y;
}
};
game.up = function (x, y, obj) {
if (draggedNumber) {
var handled = false;
// Try to fulfill query first
if (!handleQueryFulfillment(draggedNumber)) {
// Try to place in database
handled = handleNumberDrop(draggedNumber);
}
// Reset position if not handled
if (!handled) {
draggedNumber.x = 1024;
draggedNumber.y = draggedNumber.y;
}
draggedNumber.isDragging = false;
draggedNumber = null;
}
if (draggedStoredCube) {
var handled = false;
// Try to fulfill query with stored cube
if (handleStoredCubeQueryFulfillment(draggedStoredCube)) {
handled = true;
}
// Reset position if not handled
if (!handled) {
// Find parent database and reset position
for (var i = 0; i < databases.length; i++) {
for (var j = 0; j < databases[i].storedCubes.length; j++) {
if (databases[i].storedCubes[j] === draggedStoredCube) {
var row = Math.floor(j / 5);
var col = j % 5;
draggedStoredCube.x = -160 + col * 80;
draggedStoredCube.y = 163 - row * 80;
break;
}
}
}
}
draggedStoredCube.isDragging = false;
draggedStoredCube = null;
}
};
game.update = function () {
// Update timers
numberTimer++;
queryTimer++;
hashTimer++;
// Adjust number spawn rate based on total DB count - slow down as game progresses
var currentNumberSpawnRate = totalNumbersInDB < 15 ? 230 : Math.min(460 + (totalNumbersInDB - 15) * 20, 690);
// Much faster spawn rate after 400 points
if (LK.getScore() >= 400) {
currentNumberSpawnRate = Math.floor(currentNumberSpawnRate / 3);
}
// Spawn numbers
if (numberTimer >= currentNumberSpawnRate / gameSpeed) {
spawnNumber();
numberTimer = 0;
}
// Spawn queries with increased rate after 15 numbers
var currentQuerySpawnRate = totalNumbersInDB >= 15 ? 950 : querySpawnRate;
// Much faster spawn rate after 400 points
if (LK.getScore() >= 400) {
currentQuerySpawnRate = Math.floor(currentQuerySpawnRate / 3);
}
if (queryTimer >= currentQuerySpawnRate / gameSpeed) {
spawnQuery();
queryTimer = 0;
}
// Change hash function
if (hashTimer >= hashChangeRate) {
changeHashFunction();
hashTimer = 0;
}
// Check for game over condition - items stacked above 33% of assembly line (50% more space)
var conveyorTriggerPoint = 200; // Almost at the top of the page
var itemsAboveTrigger = 0;
for (var i = 0; i < numbers.length; i++) {
if (numbers[i].y < conveyorTriggerPoint && numbers[i].isStopped) {
itemsAboveTrigger++;
}
}
for (var i = 0; i < queries.length; i++) {
if (queries[i].y < conveyorTriggerPoint && queries[i].isStopped) {
itemsAboveTrigger++;
}
}
if (itemsAboveTrigger > 0) {
// Display statistics before game over
var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, {
size: 60,
fill: 0xFFFFFF
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 1366;
game.addChild(statsText);
// Create black background sized for score display
var blackBackground = game.attachAsset('conveyor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
width: statsText.width + 40,
height: statsText.height + 40,
scaleX: 1,
scaleY: 1
});
blackBackground.tint = 0x000000;
game.addChild(blackBackground);
// Move stats text to front
game.addChild(statsText);
// Show stats for 5 seconds before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 5000);
return;
}
// Update numbers
for (var i = numbers.length - 1; i >= 0; i--) {
var number = numbers[i];
// Check if number went off screen
if (number.y > 2800) {
number.destroy();
numbers.splice(i, 1);
continue;
}
// Check database overflow
for (var j = 0; j < databases.length; j++) {
if (databases[j].numbers.length >= databases[j].maxCapacity) {
// Display statistics before game over
var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, {
size: 60,
fill: 0xFFFFFF
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 1366;
game.addChild(statsText);
// Create black background sized for score display
var blackBackground = game.attachAsset('conveyor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
width: statsText.width + 40,
height: statsText.height + 40,
scaleX: 1,
scaleY: 1
});
blackBackground.tint = 0x000000;
game.addChild(blackBackground);
// Move stats text to front
game.addChild(statsText);
// Show stats for 5 seconds before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 5000);
return;
}
}
}
// Update queries
for (var i = queries.length - 1; i >= 0; i--) {
var query = queries[i];
// Check if query went off screen
if (query.y > 2800) {
query.destroy();
queries.splice(i, 1);
// Penalty for missed query
LK.setScore(Math.max(0, LK.getScore() - 10));
scoreText.setText("Score: " + LK.getScore());
}
}
// Check for game over condition - more than 11 items on assembly line
var totalItemsOnLine = numbers.length + queries.length;
if (totalItemsOnLine > 11) {
// Display statistics before game over
var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, {
size: 60,
fill: 0xFFFFFF
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 1366;
game.addChild(statsText);
// Create black background sized for score display
var blackBackground = game.attachAsset('conveyor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
width: statsText.width + 40,
height: statsText.height + 40,
scaleX: 1,
scaleY: 1
});
blackBackground.tint = 0x000000;
game.addChild(blackBackground);
// Move stats text to front
game.addChild(statsText);
// Show stats for 5 seconds before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 5000);
return;
}
// Track stuck elements for game over condition
stuckElements = [];
// Check for stuck numbers
for (var i = 0; i < numbers.length; i++) {
var number = numbers[i];
if (number.isStopped) {
stuckElements.push(number);
}
}
// Check for stuck queries
for (var i = 0; i < queries.length; i++) {
var query = queries[i];
if (query.isStopped) {
stuckElements.push(query);
}
}
// Check if we have 9 or more stuck elements
if (stuckElements.length >= STUCK_THRESHOLD) {
if (stuckStartTime === null) {
stuckStartTime = LK.ticks; // Start timing
} else if (LK.ticks - stuckStartTime >= STUCK_DURATION) {
// 9+ elements have been stuck for more than 2 seconds
// Display statistics before game over
var statsText = new Text2("Data Sorted: " + successfulSortingAttempts + "/" + totalSortingAttempts + "\nQueries Fulfilled: " + totalQueriesAnswered, {
size: 60,
fill: 0xFFFFFF
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 1366;
game.addChild(statsText);
// Create black background sized for score display
var blackBackground = game.attachAsset('conveyor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
width: statsText.width + 40,
height: statsText.height + 40,
scaleX: 1,
scaleY: 1
});
blackBackground.tint = 0x000000;
game.addChild(blackBackground);
// Move stats text to front
game.addChild(statsText);
// Show stats for 5 seconds before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 5000);
return;
}
} else {
stuckStartTime = null; // Reset timer if less than 9 elements are stuck
}
// Increase game speed over time
if (LK.ticks % 1800 === 0) {
gameSpeed = Math.min(gameSpeed + 0.1, 3);
}
};
DataBase, looks like a regular DB, circels one on each other, but with a thick heavy base under it that it stands on it. The base is a simple rectangle, and above the DB there is an empty sign. The whole picture is in ratio of 400 on 600. In-Game asset. 2d. High contrast. No shadows
Χ©ΧΧ Χ©Χ ΧΧΧΧ’ ΧΧ¦ΧΧ¨Χͺ Χ¨ΧΧΧΧ’ ΧͺΧΧΧͺ ΧΧΧ§ ΧΧΧ¨ΧΧΧ. In-Game asset. 2d. High contrast. No shadows
SQL query, in size of 320 on 200 At the top left write: SQL Query But The whole center of the rectangle is white and empty. In-Game asset. 2d. High contrast. No shadows
Sort square button, size 200 on 200 the button shows 2 rows of cubes, each row has 3 cubes. Each cube has a number on it. on the buttom row the numbers are: 1, 3, 7 The top row: 11, 12, 13. the cubes connect with arrows points from the left cube to the cube right to her at the buttom of the button, write SORT. In-Game asset. 2d. High contrast. No shadows