diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2026-01-21 22:40:55 +0100 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2026-01-21 22:40:55 +0100 |
| commit | 5d8dfe892a2ea89f706ee140c3bdcfd89fe03fda (patch) | |
| tree | 1acdfa5220cd13b7be43a2a01368e80d306473ca /examples/redis-unstable/src/lolwut5.c | |
| parent | c7ab12bba64d9c20ccd79b132dac475f7bc3923e (diff) | |
| download | crep-5d8dfe892a2ea89f706ee140c3bdcfd89fe03fda.tar.gz | |
Add Redis source code for testing
Diffstat (limited to 'examples/redis-unstable/src/lolwut5.c')
| -rw-r--r-- | examples/redis-unstable/src/lolwut5.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/examples/redis-unstable/src/lolwut5.c b/examples/redis-unstable/src/lolwut5.c new file mode 100644 index 0000000..29f0a2f --- /dev/null +++ b/examples/redis-unstable/src/lolwut5.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018-Present, Redis Ltd. + * All rights reserved. + * + * Licensed under your choice of (a) the Redis Source Available License 2.0 + * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the + * GNU Affero General Public License v3 (AGPLv3). + * + * ---------------------------------------------------------------------------- + * + * This file implements the LOLWUT command. The command should do something + * fun and interesting, and should be replaced by a new implementation at + * each new version of Redis. + */ + +#include "server.h" +#include "lolwut.h" +#include <math.h> + +/* Translate a group of 8 pixels (2x4 vertical rectangle) to the corresponding + * braille character. The byte should correspond to the pixels arranged as + * follows, where 0 is the least significant bit, and 7 the most significant + * bit: + * + * 0 3 + * 1 4 + * 2 5 + * 6 7 + * + * The corresponding utf8 encoded character is set into the three bytes + * pointed by 'output'. + */ +#include <stdio.h> +void lwTranslatePixelsGroup(int byte, char *output) { + int code = 0x2800 + byte; + /* Convert to unicode. This is in the U0800-UFFFF range, so we need to + * emit it like this in three bytes: + * 1110xxxx 10xxxxxx 10xxxxxx. */ + output[0] = 0xE0 | (code >> 12); /* 1110-xxxx */ + output[1] = 0x80 | ((code >> 6) & 0x3F); /* 10-xxxxxx */ + output[2] = 0x80 | (code & 0x3F); /* 10-xxxxxx */ +} + +/* Schotter, the output of LOLWUT of Redis 5, is a computer graphic art piece + * generated by Georg Nees in the 60s. It explores the relationship between + * caos and order. + * + * The function creates the canvas itself, depending on the columns available + * in the output display and the number of squares per row and per column + * requested by the caller. */ +lwCanvas *lwDrawSchotter(int console_cols, int squares_per_row, int squares_per_col) { + /* Calculate the canvas size. */ + int canvas_width = console_cols*2; + int padding = canvas_width > 4 ? 2 : 0; + float square_side = (float)(canvas_width-padding*2) / squares_per_row; + int canvas_height = square_side * squares_per_col + padding*2; + lwCanvas *canvas = lwCreateCanvas(canvas_width, canvas_height, 0); + + for (int y = 0; y < squares_per_col; y++) { + for (int x = 0; x < squares_per_row; x++) { + int sx = x * square_side + square_side/2 + padding; + int sy = y * square_side + square_side/2 + padding; + /* Rotate and translate randomly as we go down to lower + * rows. */ + float angle = 0; + if (y > 1) { + float r1 = (float)rand() / (float) RAND_MAX / squares_per_col * y; + float r2 = (float)rand() / (float) RAND_MAX / squares_per_col * y; + float r3 = (float)rand() / (float) RAND_MAX / squares_per_col * y; + if (rand() % 2) r1 = -r1; + if (rand() % 2) r2 = -r2; + if (rand() % 2) r3 = -r3; + angle = r1; + sx += r2*square_side/3; + sy += r3*square_side/3; + } + lwDrawSquare(canvas,sx,sy,square_side,angle,1); + } + } + + return canvas; +} + +/* Converts the canvas to an SDS string representing the UTF8 characters to + * print to the terminal in order to obtain a graphical representation of the + * logical canvas. The actual returned string will require a terminal that is + * width/2 large and height/4 tall in order to hold the whole image without + * overflowing or scrolling, since each Barille character is 2x4. */ +static sds renderCanvas(lwCanvas *canvas) { + sds text = sdsempty(); + for (int y = 0; y < canvas->height; y += 4) { + for (int x = 0; x < canvas->width; x += 2) { + /* We need to emit groups of 8 bits according to a specific + * arrangement. See lwTranslatePixelsGroup() for more info. */ + int byte = 0; + if (lwGetPixel(canvas,x,y)) byte |= (1<<0); + if (lwGetPixel(canvas,x,y+1)) byte |= (1<<1); + if (lwGetPixel(canvas,x,y+2)) byte |= (1<<2); + if (lwGetPixel(canvas,x+1,y)) byte |= (1<<3); + if (lwGetPixel(canvas,x+1,y+1)) byte |= (1<<4); + if (lwGetPixel(canvas,x+1,y+2)) byte |= (1<<5); + if (lwGetPixel(canvas,x,y+3)) byte |= (1<<6); + if (lwGetPixel(canvas,x+1,y+3)) byte |= (1<<7); + char unicode[3]; + lwTranslatePixelsGroup(byte,unicode); + text = sdscatlen(text,unicode,3); + } + if (y != canvas->height-1) text = sdscatlen(text,"\n",1); + } + return text; +} + +/* The LOLWUT command: + * + * LOLWUT [terminal columns] [squares-per-row] [squares-per-col] + * + * By default the command uses 66 columns, 8 squares per row, 12 squares + * per column. + */ +void lolwut5Command(client *c) { + long cols = 66; + long squares_per_row = 8; + long squares_per_col = 12; + + /* Parse the optional arguments if any. */ + if (c->argc > 1 && + getLongFromObjectOrReply(c,c->argv[1],&cols,NULL) != C_OK) + return; + + if (c->argc > 2 && + getLongFromObjectOrReply(c,c->argv[2],&squares_per_row,NULL) != C_OK) + return; + + if (c->argc > 3 && + getLongFromObjectOrReply(c,c->argv[3],&squares_per_col,NULL) != C_OK) + return; + + /* Limits. We want LOLWUT to be always reasonably fast and cheap to execute + * so we have maximum number of columns, rows, and output resolution. */ + if (cols < 1) cols = 1; + if (cols > 1000) cols = 1000; + if (squares_per_row < 1) squares_per_row = 1; + if (squares_per_row > 200) squares_per_row = 200; + if (squares_per_col < 1) squares_per_col = 1; + if (squares_per_col > 200) squares_per_col = 200; + + /* Generate some computer art and reply. */ + lwCanvas *canvas = lwDrawSchotter(cols,squares_per_row,squares_per_col); + sds rendered = renderCanvas(canvas); + rendered = sdscat(rendered, + "\nGeorg Nees - schotter, plotter on paper, 1968. Redis ver. "); + rendered = sdscat(rendered,REDIS_VERSION); + rendered = sdscatlen(rendered,"\n",1); + addReplyVerbatim(c,rendered,sdslen(rendered),"txt"); + sdsfree(rendered); + lwFreeCanvas(canvas); +} |
