I have the following code, basically it is doing a bruteforce on a key of a hash in the first 4 bytes. Then I loop through each of these positions to test all possible combinations. If I put this code inside the service it runs normally and takes about 200 seconds to find all possible combinations of the first 4 bytes.
But when you're doing long operations, it's good to have a queue to do this in the background. That's what I did, I added it to a nestjs queue with redis but inside the queue when I use for it seems that they are shuffled and they all end together in less than 5 seconds, besides that I don't find the correct combination. And if I use a forEach it either doesn't work or the program crashes during execution.
Basically the first 4 bytes are [192, 156, 127, 0, ...] but it doesn't find it when it's inside a queue. How can I make the background queue run normally as if it were in the service?
import * as crypto from 'crypto';
const DIFFICULTY = {
legendary: {
maxValues: [255, 255, 255, 1],
},
hard: {
maxValues: [255, 255, 255, 0],
},
medium: {
maxValues: [255, 255, 127, 0],
},
easy: {
maxValues: [255, 255, 64, 0],
},
};
#Processor('decrypt-queue')
export class DecryptConsumer {
constructor(
#InjectRepository(Chest) private readonly repository: Repository<Chest>,
) {}
#Process('decrypt-job')
async decryptJob(job: Job) {
const code = job.data;
await job.progress(50);
const chest = await this.repository.findOne({
where: {
code: code,
},
});
await this.repository.save({
...chest,
status: ChestStatus.Oppening,
});
const iv = Buffer.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const original = chest.key;
const range = ({
from = 0,
to,
step = 1,
length = Math.ceil((to - from) / step),
}): number[] => Array.from({ length }, (_, i) => from + i * step);
const first = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[0],
step: 1,
});
const second = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[1],
step: 1,
});
const third = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[2],
step: 1,
});
let four = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[3],
step: 1,
});
four = [0];
// first.forEach(async (i) => {
// second.forEach(async (j) => {
// third.forEach(async (k) => {
// four.forEach(async (l) => {
// console.log(i, j, k, l);
// if (
// i === original[0] &&
// j === original[1] &&
// k === original[2] &&
// l === original[3]
// ) {
// console.log(i, j, k, l, end());
// const decipher = await crypto.createDecipheriv(
// 'aes-128-cbc',
// Buffer.from([i, j, k, l, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
// iv,
// );
// let decrypted = await decipher.update(code, 'hex', 'utf8');
// decrypted += decipher.final('utf8');
// if (decrypted.includes('Hello')) {
// await this.repository.save({
// ...chest,
// status: ChestStatus.Openned,
// });
// await job.progress(100);
// // return {
// // decrypted,
// // };
// } else {
// }
// }
// });
// });
// });
// });
for (let i = 0; i < DIFFICULTY[chest.difficulty].maxValues[0]; i++) {
for (let j = 0; j < DIFFICULTY[chest.difficulty].maxValues[1]; j++) {
for (let k = 0; k < DIFFICULTY[chest.difficulty].maxValues[2]; k++) {
for (let l = 0; l < DIFFICULTY[chest.difficulty].maxValues[3]; l++) {
if (
i === original[0] &&
j === original[1] &&
k === original[2] &&
l === original[3]
) {
console.log(i, j, k, l, end());
const decipher = await crypto.createDecipheriv(
'aes-128-cbc',
Buffer.from([i, j, k, l, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
iv,
);
let decrypted = await decipher.update(code, 'hex', 'utf8');
decrypted += decipher.final('utf8');
if (decrypted.includes('Hello')) {
await this.repository.save({
...chest,
status: ChestStatus.Openned,
});
await job.progress(100);
// return {
// decrypted,
// };
} else {
}
}
}
}
}
}
await this.repository.save({
...chest,
status: ChestStatus.Locked,
});
await job.progress(100);
// return {
// decrypted: false,
// };
}
}
I have got map a lot of ranges to a value like 0-300 = 10 , 300-600 = 20, 600-900 = 30 ... 2500000-2700000 = 7000 .... So I could make a really large switch-statement/if-block but I wonder if there is a more elegant approach to solve this little problem.
Ok here is a small subset of the table with real data:
0-300 : 25
301-600. : 45
601-900 : 65
901-1200. : 85
1201-1500: 105
1501-2000 : 133
2001-2500 : 161
2501-3000: 189
3001-3500:217
3501-4000:245
4001-4500:273
4501-5000:301
5001-6000:338
The most common pattern for getting rid of a switch statement is to use a dictionary. In your case, since you're mapping ranges, you'll use an NSArray of range cutoffs instead. This is what it would look like if you're dealing with ints:
NSArray *rangeCutoffs = [NSArray arrayWithObjects:[NSNumber numberWithInt:300],[NSNumberWithInt:600],...,nil];
NSArray *values = [NSArray arrayWithObjects:[NSNumber numberWithInt:10], [NSNumber numberWithInt:20],...,nil];
int mappedInt;
for (int index=0; index <= [rangeCutoffs count]; index++) {
if (intToMap < [[rangeCutoffs objectAtIndex:index] intValue]) {
mappedInt = [[values objectAtIndex:index] intValue];
}
}
if (mappedInt == 0) {
mappedInt = [[values lastObject] intValue];
}
In practice you'd want to load rangeCutoffs and values from a plist instead of hardcoding them.
You could use a table. e.g.
struct Lookup
{
int min;
int max;
int value;
};
struct Lookup table[] =
{
{ 0, 300, 10 },
{ 301, 600, 20 },
{ 601, 900, 30 },
// other ranges
{ 2500000, 2700000, 7000 },
{ -1, -1, -1 } // marks the end of the table
};
And then simply iterate through it to find the right range
int result = -1;
for (int i = 0 ; table[i].min != -1 && result == -1 ; ++i)
{
if (table[i].min <= value && value <= table[i].max)
{
result = table[i].value;
}
}
If it's a really large table, you can use a binary search instead.
You could do something like this (C example):
#include <stdio.h>
#include <stdlib.h>
typedef int range_type;
typedef int value_type;
typedef struct {
range_type min;
range_type max;
value_type value;
} range_t;
const range_t *find_range(const range_t *ranges, size_t rangesSize,
value_type valueToFind)
{
for (size_t i = 0; i < rangesSize; ++i) {
if (ranges[i].min <= valueToFind && valueToFind <= ranges[i].max)
return &ranges[i];
}
return NULL;
}
int main() {
const range_t ranges[] = {
{ 0, 300, 10 },
{ 301, 600, 20 },
{ 601, 900, 30 },
{ 901, 1200, 40 }
// And so on...
};
value_type testValues[] = {
-1, // None
0, 299, 300, // [ 0, 300]
301, 599, 600, // [301, 600]
601, 899, 900, // [601, 900]
901, 1199, 1200, // [901, 1200]
// And so on...
};
for (size_t i = 0; i < sizeof(testValues) / sizeof(testValues[0]); ++i) {
const range_t *match = find_range(
ranges, sizeof(ranges) / sizeof(ranges[0]), testValues[i]);
if (match != NULL)
printf("%d found at [%d..%d]\n", testValues[i], match->min,
match->max);
else
printf("%d not found\n", testValues[i]);
}
return EXIT_SUCCESS;
}
Should output:
-1 not found
0 found at [0..300]
299 found at [0..300]
300 found at [0..300]
301 found at [301..600]
599 found at [301..600]
600 found at [301..600]
601 found at [601..900]
899 found at [601..900]
900 found at [601..900]
901 found at [901..1200]
1199 found at [901..1200]
1200 found at [901..1200]
I am trying to create an application that simulates a slot machine.
Now, I have all the images ready, with the vertical png file and the plist file. My question is, how do I simulate the spinning (when the user presses a button), and then the stopping of the slot machine (after around 1-2 seconds)?
Note that the png file has to wrap around somehow.
Everything else is all a matter of NSArrays and checking, what I want to figure out is the animation. I hope some can share some code or references to do this.
Thanks!
This is relatively straightforward: just repeat the png file as many times as you need to simulate the spinning action. So it's basically a vertical variation on parallax scrolling. If you have Steffan Itterheim's book, he talks about this type of thing in chapter 7 "Scrolling With Joy". You may also find some help here: Cocos2D vertically scrolling background
Hope this helps!
Mike
I am doing something like this:
#include <ctime>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
using namespace std;
static int last[5]={0, 0, 0, 0, 0};
static int stops[5];
static int reels[5][63] = {
{9,7,12,5,7,3,4,11,9,7,12,6,7,4,11,10,4,3,11,12,7,5,10,9,7,5,9,10,8,9,7,4,9,10,11,5,10,3,9,10,3,9,4,8,7,5,11,9,12,6,3,5,7,9,11,10,6,7,3,5,10,8,4,},
{11,5,4,7,6,8,4,9,7,8,3,11,6,5,11,7,12,5,8,6,10,9,5,6,8,7,12,11,5,6,10,3,4,5,9,12,8,9,6,5,12,8,9,12,7,8,5,10,12,7,11,3,4,8,7,4,5,9,8,6,12,4,6,},
{10,4,5,8,6,7,5,9,6,7,8,4,6,5,11,3,9,8,7,11,12,6,8,5,4,8,6,12,9,6,5,11,3,7,4,8,7,3,10,9,5,6,4,3,9,12,10,8,9,6,3,9,10,6,7,5,6,8,4,11,9,7,8,},
{9,3,6,5,3,10,6,9,5,12,4,8,11,10,7,6,5,9,7,3,8,6,12,4,5,7,3,12,10,6,9,7,8,5,6,4,9,6,11,5,8,12,6,7,3,6,10,3,7,5,10,8,9,6,12,4,7,9,5,6,8,3,10,},
{5,3,9,4,6,12,10,5,11,4,8,7,10,5,9,11,4,6,7,3,6,4,8,5,11,8,5,10,8,11,5,10,8,3,7,4,10,11,5,7,8,9,5,11,6,8,10,3,7,9,3,8,10,12,6,8,10,11,7,10,8,11,6,},
};
static SDL_Window *window = NULL;
static SDL_Surface *canvas = NULL;
static const SDL_Surface *backgroundSurface = IMG_Load("./Background.png");
static SDL_Rect backgroundCoordinates = { 0, 0, 0, 0 };
static const SDL_Surface *symbolsSurface[] = {
NULL,
NULL,
NULL,
IMG_Load("./Symbol03.png"),
IMG_Load("./Symbol04.png"),
IMG_Load("./Symbol05.png"),
IMG_Load("./Symbol06.png"),
IMG_Load("./Symbol07.png"),
IMG_Load("./Symbol08.png"),
IMG_Load("./Symbol09.png"),
IMG_Load("./Symbol10.png"),
IMG_Load("./Symbol11.png"),
IMG_Load("./Symbol12.png"),
NULL,
NULL,
NULL,
NULL,
};
static const SDL_Surface *reelsSurface[5] = {NULL, NULL, NULL, NULL, NULL};
static SDL_Rect symbolsCoordinates[5][3] = {
{ { 298, 118, 0, 0 }, { 298, 266, 0, 0 }, { 298, 414, 0, 0 } },
{ { 474, 118, 0, 0 }, { 474, 266, 0, 0 }, { 474, 414, 0, 0 } },
{ { 651, 118, 0, 0 }, { 651, 266, 0, 0 }, { 651, 414, 0, 0 } },
{ { 827, 118, 0, 0 }, { 827, 266, 0, 0 }, { 827, 414, 0, 0 } },
{ { 1003, 118, 0, 0 }, { 1003, 266, 0, 0 }, {1003, 414, 0, 0 } },
};
static unsigned long animationStart = 0;
static unsigned long animationEnd = 0;
static bool stopped[5] = {false, false, false, false, false};
void draw() {
static double y0 = 0;
static double v0[5] = {-9.5, -9.6, -9.7, -9.8, -9.9};
static long t = 0;
static double a = 0.0005;
static int y = 0;
SDL_BlitSurface((SDL_Surface*) backgroundSurface, NULL, canvas, &backgroundCoordinates);
for (int i = 0; i < 5 && animationStart!=animationEnd; i++) {
/*
* y = y0 + v0*t + 1/2*at^2
*/
y0 = last[i] * 140;
t = (1000 * clock() / CLOCKS_PER_SEC) - animationStart;
y = (int)(y0 + v0[i]*t + a*t*t/2) % (63*140);
if(y < 0) {
y += 63*140;
}
/*
* Stop near to the target position.
*/
if(i==0 && abs(y-stops[i]*140)<=140) {
last[i] = stops[i];
stopped[i] = true;
}else if(stopped[i-1] == true && stopped[i] == false && abs(y-stops[i]*140)<=140) {
last[i] = stops[i];
stopped[i] = true;
}
if(stopped[i] == true) {
SDL_SetSurfaceAlphaMod((SDL_Surface*) reelsSurface[i], 255);
y = stops[i] * 140;
} else {
SDL_SetSurfaceAlphaMod((SDL_Surface*) reelsSurface[i], 191);
}
const SDL_Rect frame = {0, y, 140, 3*140};
SDL_BlitSurface((SDL_Surface*) reelsSurface[i], &frame, canvas, &symbolsCoordinates[i][0]);
}
SDL_UpdateWindowSurface(window);
}
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
/*
* Build long strips (two more images at the end).
*/
for(int i=0, index; i<5; i++) {
reelsSurface[i] = IMG_Load("./Reel.png");
for(int j=0; j<(63+2); j++) {
index = reels[i][j%63];
SDL_Rect coordinates = {0, 140*j, 0, 0};
SDL_BlitSurface((SDL_Surface*) symbolsSurface[index], NULL, (SDL_Surface*)reelsSurface[i], &coordinates);
}
}
//window = SDL_CreateWindow("Slot Reels Animation", 0, 0, 1280, 1024, SDL_WINDOW_FULLSCREEN_DESKTOP);
window = SDL_CreateWindow("Slot Reels Animation", 0, 0, 1440, 900, 0);
canvas = SDL_GetWindowSurface(window);
SDL_Event event;
bool done = false;
while (done == false) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
done = true;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
done = true;
break;
case SDLK_RETURN:
//startAnimation();
memset(stopped, false, 5*sizeof(bool));
animationStart = 1000 * clock() / CLOCKS_PER_SEC;
for (int i = 0, r; i < 5; i++) {
stops[i] = rand() % 63;
}
break;
}
}
}
draw();
}
SDL_DestroyWindow(window);
for(int i=0; i<5; i++) {
SDL_FreeSurface((SDL_Surface*)reelsSurface[i]);
}
SDL_Quit();
return EXIT_SUCCESS;
}