pokie
Version:
A server-side video slot game logic framework for JavaScript and TypeScript.
116 lines (101 loc) • 4.67 kB
text/typescript
import {LinesDefinitionsDescribing, SymbolsSequenceDescribing} from "pokie";
export class SymbolsCombinationsAnalyzer {
public static getSymbolsForDefinition(symbols: string[][], definition: number[]): string[] {
return definition.map((col, index) => symbols[index][col]);
}
public static getSymbolsMatchingPattern(symbols: string[], pattern: number[]): string[] {
return symbols.filter((_, i: number) => pattern[i] === 1);
}
public static isMatchPattern(symbols: string[], pattern: number[], wildSymbols?: string[]): boolean {
const symbolsByPattern: string[] = SymbolsCombinationsAnalyzer.getSymbolsMatchingPattern(symbols, pattern);
const unique = Array.from(new Set(symbolsByPattern));
const uniqueNotWilds = unique.filter((symbol) => !wildSymbols?.some((wildSymbol) => wildSymbol === symbol));
return uniqueNotWilds.length === 1;
}
public static getWinningSymbolId(symbols: string[], pattern: number[], wildSymbols?: string[]): string | null {
const symbolsByPattern: string[] = SymbolsCombinationsAnalyzer.getSymbolsMatchingPattern(symbols, pattern);
const unique: Set<string> = new Set(symbolsByPattern);
let prev: string | null = null;
unique.forEach((cur) => {
if (!wildSymbols?.some((wild) => wild === cur)) {
prev = cur;
}
});
return prev;
}
public static getMatchingPattern(symbols: string[], patterns: number[][], wildSymbols?: string[]): number[] | null {
for (const pattern of patterns) {
if (SymbolsCombinationsAnalyzer.isMatchPattern(symbols, pattern, wildSymbols)) {
return pattern;
}
}
return null;
}
public static getWildSymbolsPositions(symbols: string[], pattern: number[], wildSymbols: string[]): number[] {
return symbols
.map((symbol: string, i: number) =>
wildSymbols.some((wildSymbolId) => symbol === wildSymbolId) && pattern[i] === 1 ? i : -1,
)
.filter((index: number) => index !== -1);
}
public static getScatterSymbolsPositions(symbols: string[][], scatterSymbolId: string): number[][] {
const r: number[][] = [];
for (let i = 0; i < symbols.length; i++) {
for (let j = 0; j < symbols[i].length; j++) {
if (symbols[i][j] === scatterSymbolId) {
r.push([i, j]);
}
}
}
return r;
}
public static getWinningLinesIds(
symbols: string[][],
linesDefinitions: LinesDefinitionsDescribing,
patterns: number[][],
wildSymbols?: string[],
): string[] {
const lines: string[] = linesDefinitions.getLinesIds();
const ids: string[] = lines.filter((lineId: string) => {
const symbolsLine: string[] = SymbolsCombinationsAnalyzer.getSymbolsForDefinition(
symbols,
linesDefinitions.getLineDefinition(lineId),
);
return SymbolsCombinationsAnalyzer.getMatchingPattern(symbolsLine, patterns, wildSymbols) !== null;
});
ids.sort();
return ids;
}
public static getAllPossibleSymbolsCombinations(
sequences: SymbolsSequenceDescribing[],
symbolsNumber: number,
): string[][][] {
function generateCombinations(arr) {
const result: number[][] = [];
function generateRecursively(currCombination: number[], index: number) {
if (index === arr.length) {
result.push(currCombination.slice());
return;
}
for (let i = 0; i <= arr[index]; i++) {
currCombination[index] = i;
generateRecursively(currCombination, index + 1);
}
}
generateRecursively(new Array(arr.length).fill(0), 0);
return result;
}
const sequencesSizes: number[] = [];
sequences.forEach((seq) => sequencesSizes.push(seq.getSize() - 1));
const combinations = generateCombinations(sequencesSizes);
const allPossibleSymbolsCombinations: string[][][] = [];
combinations.forEach((values) => {
const curCombination: string[][] = new Array(sequences.length);
values.forEach((value, i) => {
curCombination[i] = sequences[i].getSymbols(value, symbolsNumber);
});
allPossibleSymbolsCombinations.push(curCombination);
});
return allPossibleSymbolsCombinations;
}
}