Skip to content

Instantly share code, notes, and snippets.

@alexsad
Last active February 11, 2025 17:57
Show Gist options
  • Save alexsad/39db45e2d2deccb247f649baad569103 to your computer and use it in GitHub Desktop.
Save alexsad/39db45e2d2deccb247f649baad569103 to your computer and use it in GitHub Desktop.
andar-aleatorio-com-rxjs
import { interval, merge } from 'rxjs';
import { map, takeWhile } from 'rxjs/operators';
//visual renders
const drawCell = (text: string) => {
const finalText = text || ''
const padText = ' '
return `${padText.substring(0, padText.length - finalText.length)}${finalText}`
}
function drawVector(matriz: string[][]) {
matriz.forEach(linha => {
console.log(linha.map(item => `[${(drawCell((item || ' ').substring(1)))}]`.padStart(3, '')).join(''));
});
}
//prob calculate
function binomial(n: number, k: number): number {
if (k < 0 || k > n) return 0;
if (k === 0 || k === n) return 1;
let result = 1;
for (let i = 1; i <= k; i++) {
result = (result * (n - i + 1)) / i;
}
return result;
}
function calculateFinalProbabilities(
matrixWidth: number,
matrixHeight: number,
startX: number
): number[] {
const probabilities: number[] = new Array(matrixWidth).fill(0);
const n: number = matrixHeight;
for (let x = 0; x < matrixWidth; x++) {
const diff: number = n + x - startX;
if (diff % 2 === 0) {
const k: number = diff / 2;
if (k >= 0 && k <= n) {
probabilities[x] = binomial(n, k) * Math.pow(0.5, n);
}
}
}
return probabilities;
}
//util funcs
function createMatrix<T>(rows: number, cols: number, initialValue: T): T[][] {
return Array.from({ length: rows }, () => Array.from({ length: cols }, () => initialValue));
}
//rxjs
const getRandowStep = (trackId: string, steps: number) => {
return interval(1000)
.pipe(
takeWhile(val => val < steps),
map(val => ({
y: val-1,
x: Math.random() < .5 ? -1 : 1,
trackId,
})),
)
}
//request-api
export type IStepResponse = {
stepsLeft: number,
x: number,
y: number,
trackId: string,
}
function getRandowStepFromAPI(trackId: string, steps: number) {
return new Observable<MessageEvent<string>>(observer => {
const eventSource = new EventSource(`/stream-api/drunk/walk?steps=${steps}`);
eventSource.onmessage = (event) => observer.next(event);
eventSource.onerror = (error) => {
console.log('error:', error)
observer.error(error);
eventSource.close();
};
return () => eventSource.close();
}).pipe(
map(({ data }) => JSON.parse((data || '{}')) as IStepResponse),
map(item => ({
...item,
trackId,
})),
)
}
//request-sml
const steps = 40
const drunkData = createMatrix(steps, steps, '')
calculateFinalProbabilities(steps, steps, Math.floor(steps / 2)).map(prob => drawCell(`${prob}`)).forEach((value, xIndex) => {
drunkData[steps - 1][xIndex] = value.substring(0, 5)
})
//consumer
merge(
getRandowStep('X', steps),
getRandowStep('P', steps),
getRandowStep('G', steps),
getRandowStep('R', steps),
getRandowStep('M', steps),
getRandowStep('T', steps),
).subscribe(val => {
const zIndex = Math.max(val.y, 0)
const drunkData = this.data
if (zIndex < (drunkData.length)) {
const rowSize = drunkData[0].length
const previousY = Math.max(zIndex - 1, 0)
let lastX = drunkData[previousY].findIndex(item => item.includes(val.trackId))
let nextX = Math.floor(rowSize / 2)
if (lastX > -1) {
nextX = Math.min(Math.max(0, lastX + val.x), rowSize - 1)
}
const oldContent = drunkData[zIndex][nextX].split(',')
drunkData[zIndex][nextX] = oldContent.concat(val.trackId).join(',')
}
this.data = cloneObject(drunkData)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment