diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-08-25 12:36:37 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-08-25 12:36:37 +0200 |
| commit | e5de70f2c1dcac767bd34a6b90ac1797a7acb433 (patch) | |
| tree | 25a8c8f339fb5b496b460391ee06a9effeb64855 /lib | |
| parent | 6b909d95ec07848136a6f337db28318c1cd46c60 (diff) | |
| parent | d7bc21d19e168f3a99f54e5ba4866ed49f1187f1 (diff) | |
Merge branch 'rust'
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/renderers/256_colors.js | 19 | ||||
| -rw-r--r-- | lib/renderers/ansi.js | 16 | ||||
| -rw-r--r-- | lib/renderers/fake_color.js | 12 | ||||
| -rw-r--r-- | lib/renderers/true_color.js | 19 | ||||
| -rw-r--r-- | lib/screens/circle.js | 36 | ||||
| -rw-r--r-- | lib/screens/gradients.js | 29 | ||||
| -rw-r--r-- | lib/screens/mirrors.js | 40 | ||||
| -rw-r--r-- | lib/screens/random.js | 29 | ||||
| -rw-r--r-- | lib/screens/sprinkles.js | 32 | ||||
| -rw-r--r-- | lib/tomato_sauce.js | 189 | ||||
| -rw-r--r-- | lib/util.js | 82 |
11 files changed, 0 insertions, 503 deletions
diff --git a/lib/renderers/256_colors.js b/lib/renderers/256_colors.js deleted file mode 100644 index f6e57d3..0000000 --- a/lib/renderers/256_colors.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -/** - * Returns a 256 color, see https://en.wikipedia.org/wiki/ANSI_escape_code#Colors - * for more info. - * - * @function 256ColorsRenderer - * @implements IRenderer - */ -module.exports = function (red, blue, green) { - - const redValue = Math.round(red * 5 / 255); - const blueValue = Math.round(blue * 5 / 255); - const greenValue = Math.round(green * 5 / 255); - - const colorNumber = 16 + 36 * redValue + 6 * greenValue + blueValue; - - return `\x1B[48;5;${colorNumber}m`; -}; diff --git a/lib/renderers/ansi.js b/lib/renderers/ansi.js deleted file mode 100644 index b3a461d..0000000 --- a/lib/renderers/ansi.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -/** - * Returns a basic ansi color, see https://en.wikipedia.org/wiki/ANSI_escape_code#Colors - * for more info. - * - * @function ANSIRenderer - * @implements IRenderer - */ -module.exports = function (red, blue, green) { - - const colorOffset = Math.round((red + blue + green) * 7 / (255 * 3)); - const colorNumber = 40 + colorOffset; - - return `\x1B[${colorNumber}m`; -}; diff --git a/lib/renderers/fake_color.js b/lib/renderers/fake_color.js deleted file mode 100644 index b03309c..0000000 --- a/lib/renderers/fake_color.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -/** - * Returns a malformed 24-bit ansi color - * - * @function FakeColorRenderer - * @implements IRenderer - */ -module.exports = function (red, blue, green) { - - return `\x1B[28;2;${Math.round(red)};${Math.round(green)};${Math.round(blue)}m`; -}; diff --git a/lib/renderers/true_color.js b/lib/renderers/true_color.js deleted file mode 100644 index 811d186..0000000 --- a/lib/renderers/true_color.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -// Returns an ANSI Code for True Color, see: -// https://en.wikipedia.org/wiki/ANSI_escape_code#Colors -// and look for 24-bit colors. Only looks good in supported terminals, -// otherwise looks like FakeColor. -/** - * Returns an ANSI code for 24-bit True Color, see - * https://en.wikipedia.org/wiki/ANSI_escape_code#Colors and look for - * 24-bit colors for more info. Only looks good in supported terminals, - * otherwise looks like FakeColor - * - * @function TrueColorRenderer - * @implements IRenderer - */ -module.exports = function (red, blue, green) { - - return `\x1B[48;2;${Math.round(red)};${Math.round(green)};${Math.round(blue)}m`; -}; diff --git a/lib/screens/circle.js b/lib/screens/circle.js deleted file mode 100644 index f5d37e3..0000000 --- a/lib/screens/circle.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -/** - * Draws concentric circles. Each ring has its own color. - * - * @function CircleScreen - * @implements IScreen - */ -module.exports = function (modulation, width, height, renderer) { - - let response = []; - - const circles = width > height ? height : width; - - for (let i = 0; i < circles; ++i) { - const centerX = Math.round(width / 2) + 1; - const centerY = Math.round(height / 2) + 1; - - const red = Math.floor(Math.random() * 255); - const blue = Math.floor(Math.random() * 255); - const green = Math.floor(Math.random() * 255); - - for (let j = 0; j < 180; ++j) { - const angle = 2 * j * (Math.PI / 180); - const x = Math.round(centerX + Math.sin(angle) * i); - const y = Math.round(centerY + Math.cos(angle) * i); - - if (x <= width && x > 0 && y <= height && y > 0) { - const position = `\x1B[${y};${x}H`; // Move cursor to y,x (CSI y;x H) - response += `${position}${renderer(red, blue, green)} `; - } - } - } - - return response; -}; diff --git a/lib/screens/gradients.js b/lib/screens/gradients.js deleted file mode 100644 index 2d4a2f0..0000000 --- a/lib/screens/gradients.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -/** - * Draws moving gradient boxes - * - * @function GradientsScreen - * @implements IScreen - */ -module.exports = function (modulation, width, height, renderer) { - - let response = ''; - - for (let i = 0; i < height; ++i) { - for (let j = 0; j < width; ++j) { - const red = ((modulation + i) * 255 / height) % 255; - const blue = ((modulation + j) * 255 / width) % 255; - const green = ((modulation + i * j) * 255 / (width * height)) % 255; - - response = response + renderer(red, blue, green); - response = response + ' '; - } - - if (i < height - 1) { - response = response + '\n'; - } - } - - return response; -}; diff --git a/lib/screens/mirrors.js b/lib/screens/mirrors.js deleted file mode 100644 index e842217..0000000 --- a/lib/screens/mirrors.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -/** - * Draws small moving gradient boxes and repeats them. - * - * @function MirrorsScreen - * @implements IScreen - */ -module.exports = function (modulation, width, height, renderer) { - - const response = []; - - const scale = 2 + Math.round(Math.random() * 4); - const scaledHeight = Math.floor(height / scale); - const scaledWidth = Math.floor(width / scale); - - for (let i = 0; i < scaledHeight; ++i) { - const row = []; - for (let j = 0; j < scaledWidth; ++j) { - const red = ((modulation + i) * 255 / height) % 255; - const blue = ((modulation + j) * 255 / width) % 255; - const green = ((modulation + i * j) * 255 / (width * height)) % 255; - - const cell = [renderer(red, blue, green), ' ']; - row.push(cell.join('')); - } - - let rowText = ''; - for (let j = 0; j < scale; ++j) { - rowText += row.reverse().join(''); - } - - for (let j = 1; j < scale; ++j) { - response[j * i] = rowText; - response[(height - 1 - (j * i))] = rowText; - } - } - - return response.join('\n'); -}; diff --git a/lib/screens/random.js b/lib/screens/random.js deleted file mode 100644 index 0cacea7..0000000 --- a/lib/screens/random.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -/** - * Draws random colors - * - * @function RandomScreen - * @implements IScreen - */ -module.exports = function (modulation, width, height, renderer) { - - let response = ''; - - for (let i = 0; i < height; ++i) { - for (let j = 0; j < width; ++j) { - const red = Math.floor(Math.random() * 255); - const blue = Math.floor(Math.random() * 255); - const green = Math.floor(Math.random() * 255); - - response = response + renderer(red, blue, green); - response = response + ' '; - } - - if (i < height - 1) { - response = response + '\n'; - } - } - - return response; -}; diff --git a/lib/screens/sprinkles.js b/lib/screens/sprinkles.js deleted file mode 100644 index f12200e..0000000 --- a/lib/screens/sprinkles.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -/** - * Draws random sprinkles in the screen each frame. Same color per - * frame. - * - * @function SprinklesScreen - * @implements IScreen - */ -module.exports = function (modulation, width, height, renderer) { - - let response = ''; - - const maxSprinkleCount = (width * height) / 2; - const minSprinkleCount = (width * height) / 8; - const sprinkleCount = Math.round(Math.random() * (maxSprinkleCount - minSprinkleCount)) + minSprinkleCount; - - const red = Math.floor(Math.random() * 255); - const blue = Math.floor(Math.random() * 255); - const green = Math.floor(Math.random() * 255); - - for (let i = 0; i < sprinkleCount; ++i) { - const x = Math.round(Math.random() * (width - 1)) + 1; - const y = Math.round(Math.random() * (height - 1)) + 1; - - const position = `\x1B[${y};${x}H`; // Move cursor to y,x (CSI y;x H) - - response += `${position}${renderer(red, blue, green)} `; - } - - return response; -}; diff --git a/lib/tomato_sauce.js b/lib/tomato_sauce.js deleted file mode 100644 index 4a65ea1..0000000 --- a/lib/tomato_sauce.js +++ /dev/null @@ -1,189 +0,0 @@ -'use strict'; - -const Net = require('net'); -const EventEmitter = require('events'); - -const Util = require('./util'); - -const internals = { - // Interpret as Command Sequences. - kEscape: new Buffer([0xFF, 0xF4, 0XFF, 0xFD, 0x06]), // IAC IP IAC DO TIMING_MARK - kNAWSRequest: new Buffer([0xFF, 0xFD, 0X1F]), // IAC DO NAWS - kNAWSResponse: new Buffer([0xFF, 0xFB, 0X1F, 0xFF, 0xFA, 0X1F]) // IAC WILL NAWS IAC SB NAWS -}; - -/** - * A function that represents a screen, it is called frequently and should - * return a string consisting of commands to run. - * - * @interface IScreen - * @type function - * @param {Number} modulation A number between 0 and 255 representing the current - * step of the modulation - * @param {Number} width The width of the screen - * @param {Number} height The height of the screen - * @param {IRenderer} renderer The renderer used to colorize the scfeen - * @return {String} The commands used to render the screen elements - */ - -/** - * A function that represents a renderer, it should take in a color in RGB and - * return a string with the appropriate code to colorize the terminal. - * - * @interface IRenderer - * @type function - * @param {Number} red The red component of the color between 0 and 255 - * @param {Number} green The green component of the color between 0 and 255 - * @param {Number} blue The green component of the color between 0 and 255 - * @return {String} The commands used to colorize the terminal - */ - -/** - * The main application for tomato sauce. Listens for connections and serves - * random combinations of screens and renderers - * - * The main entry point is the `#run()` function. - * - * It emits a listening event that contains the server information on - * the `server` key inside the `data` property of the event. - * - * It also emits an error event that contains the error information on - * the `error` key inside the `data` property of the event. - * - * @class TomatoSauce - * @extends EventEmitter - * - * @param {object} config the configuration object used to extend the properties. - * - * @property {Array<IScreen>} screens an array of screens available to serve - * @property {Array<IRenderer>} renderers an array of renderers available to colorize - * @property {Number} [port=9999] the port to listen on - * @property {Number} [frequency=333] how often to update the screen - * @property {Number} [modulation=5] number between 0-255 depicting current modulation step - */ -const TomatoSauce = class TomatoSauce extends EventEmitter { - - constructor(config = {}) { - - super(); - - this.screens = []; - this.renderers = []; - - // Defaults. - this.port = 9999; - this.frequency = 333; - this.modulation = 5; - - Object.assign(this, config); - } - - /** - * Main entry point, initializes the server and binds events for connections - * - * @function run - * @instance - * @memberof TomatoSauce - */ - run() { - - this._startServer(); - this._bindEvents(); - } - - // Creates a socket, server based on the configuration. Emits the - // listening event when ready. - - _startServer() { - - const server = Net.createServer(); - this.server = server; - server.listen(this.port, () => { - - this.emit('listening', { - data: { - server - } - }); - }); - } - - // Binds the connection and error events - - _bindEvents() { - - // Send the error event all the way up. - this.server.on('error', (error) => { - - this.emit('error', { - data: { - error - } - }); - }); - - // Send the error event all the way up. - this.server.on('connection', (socket) => { - - this._renderScreen(socket); - }); - } - - // Obtains viewport size, and initializes a random screen with a random - // renderer, setting the required interval to draw. - - _renderScreen(socket) { - - const connectionData = { - width: null, - height: null, - modulation: 0, - screen: this._getScreen(), - renderer: this._getRenderer(), - socket - }; - let interval = null; - - socket.write(internals.kNAWSRequest); - - socket.on('data', (data) => { - - if (data.slice(0, 6).compare(internals.kNAWSResponse) === 0) { - connectionData.width = Util.parse16BitBuffer(data.slice(6, 8)); - connectionData.height = Util.parse16BitBuffer(data.slice(8, 10)); - - socket.write('\x1B[2J'); // Clear the Screen (CSI 2 J) - interval = setInterval(this._writeMessage.bind(this, connectionData), this.frequency); - } - - if (data.compare(internals.kEscape) === 0) { - socket.write('\n'); - clearInterval(interval); - socket.end(); - } - }); - } - - // Resets the cursor, gets a frame and sends it to the socket. - - _writeMessage(connectionData) { - - const payload = connectionData.screen(connectionData.modulation, connectionData.width, connectionData.height, connectionData.renderer); - const message = `\x1B[1;1H${payload}`; // reset cursor position before payload - - connectionData.modulation = (connectionData.modulation + this.modulation) % 256; - connectionData.socket.write(message); - } - - _getScreen() { - - return Util.pickRandom(this.screens); - } - - _getRenderer() { - - return Util.pickRandom(this.renderers); - } -}; - -module.exports = TomatoSauce; diff --git a/lib/util.js b/lib/util.js deleted file mode 100644 index 65f14ae..0000000 --- a/lib/util.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -const Fs = require('fs'); -const Path = require('path'); - -/** - * Module containing utility functions - * - * @name Util - * @type Object - */ -const Util = { - - /** - * Parses a 16 bit number buffer - * - * @function parse16BitBuffer - * @memberof Util - * @param {Array<String>} buffer the buffer to parse - * @return {Number} the parsed value - */ - parse16BitBuffer(buffer) { - - return buffer[0] * 256 + buffer[1]; - }, - - /** - * Picks a random element from an array - * - * @function pickRandom - * @memberof Util - * @param {Array} array the array to use - * @return {Any} the picked element - */ - pickRandom(array) { - - return array[Math.floor(Math.random() * array.length)]; - }, - - /** - * For a gi ven path, requires all of the files and returns an array - * with the results. If the directory contains any non-requireable - * files, it will fail. - * - * @function loadFiles - * @memberof Util - * @param {String} path the path where the files are located - * @return {Array} the array of all the loaded modules - */ - loadFiles(path) { - - return new Promise((resolve, reject) => { - - Fs.readdir(path, (err, files) => { - - if (err) { - return reject(err); - } - - const loadedFiles = []; - - for (const file of files) { - const filePath = Path.join(path, file); - let loadedFile; - - try { - loadedFile = require(filePath); - } - catch (err) { - return reject(err); - } - - loadedFiles.push(loadedFile); - } - - resolve(loadedFiles); - }); - }); - } -}; - -module.exports = Util; |