Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ type RenderFunction = (resolution: number, indexX: number, indexY: number) => st
* Returns a randomly generated string representation code of an avatar for a given `complexity`
* @param {number} [complexity] - A positive integer that represents the number of rows and columns to be drawn
* @param {string} [avatarDataSeparator] - A character to be used as data separator
* @param {any} [seed] - A value to be used as the seed for generating the avatar data; accepts any value that the `String` constructor would accept
* @return {string} Output example: 0-6-6te25-9d9p0-xd5g
*/
export function generateRandomAvatarData(complexity?: number, avatarDataSeparator?: string): string;
export function generateRandomAvatarData(complexity?: number, avatarDataSeparator?: string, seed?: any): string;

/**
* Returns a string with a valid SVG markup for a given `avatarData`
Expand Down
48 changes: 44 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,56 @@ function parseAvatarData(data, separator) {
return ret;
}

export function generateRandomAvatarData(complexity = 16, avatarDataSeparator = '-') {
const xAxis = Math.floor(Math.random() * Math.pow(2, complexity - 1));
const yAxis = Math.floor(Math.random() * (Math.pow(2, complexity) - 1)) + 1;
// https://stackoverflow.com/a/47593316/1714997
function cyrb128(str) {
let h1 = 1779033703, h2 = 3144134277,
h3 = 1013904242, h4 = 2773480762;
for (let i = 0, k; i < str.length; i++) {
k = str.charCodeAt(i);
h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
}
h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
h1 ^= (h2 ^ h3 ^ h4), h2 ^= h1, h3 ^= h1, h4 ^= h1;
return [h1>>>0, h2>>>0, h3>>>0, h4>>>0];
}

// https://stackoverflow.com/a/47593316/1714997
function sfc32(a, b, c, d) {
return function() {
a |= 0; b |= 0; c |= 0; d |= 0;
let t = (a + b | 0) + d | 0;
d = d + 1 | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
c = c + t | 0;
return (t >>> 0) / 4294967296;
}
}

function getRandomNumberGenerator(seed) {
const seedString = String(seed); // Making sure that the seed is a string.
const seedHashed = cyrb128(seedString);
return sfc32(seedHashed[0], seedHashed[1], seedHashed[2], seedHashed[3]);
}

export function generateRandomAvatarData(complexity = 16, avatarDataSeparator = '-', seed = Math.random()) {
const getRandomNumber = getRandomNumberGenerator(seed);
const xAxis = Math.floor(getRandomNumber() * Math.pow(2, complexity - 1));
const yAxis = Math.floor(getRandomNumber() * (Math.pow(2, complexity) - 1)) + 1;

const rows = getBinaryList(yAxis, complexity);
let ret = `${xAxis.toString(36)}${avatarDataSeparator}${yAxis.toString(36)}`;
let color;

rows.forEach(() => {
color = Math.floor(Math.random() * 16777215);
color = Math.floor(getRandomNumber() * 16777215);
ret += `${avatarDataSeparator}${color.toString(36)}`;
});

Expand Down
25 changes: 23 additions & 2 deletions src/index.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getRandomAvatar, getAvatarFromData, generateRandomAvatarData } from './index.js';

describe('Generate random avatar Ddta', () => {
describe('Generate random avatar Data', () => {
it('should return a random code from default values', () => {
const avatarCode = generateRandomAvatarData();
expect(avatarCode.split('-').length).toEqual(18);
Expand All @@ -11,6 +11,27 @@ describe('Generate random avatar Ddta', () => {
});
});

describe('Generate random avatar data with seed', () => {
it('should return the same code for the same seed', () => {
const seed = "apples";
const avatarCode1 = generateRandomAvatarData(16, '-', seed);
const avatarCode2 = generateRandomAvatarData(16, '-', seed);
expect(avatarCode1).toEqual(avatarCode2);
});
it('should return different codes for different seeds', () => {
const seed1 = "apples";
const seed2 = "oranges";
const avatarCode1 = generateRandomAvatarData(16, '-', seed1);
const avatarCode2 = generateRandomAvatarData(16, '-', seed2);
expect(avatarCode1).not.toEqual(avatarCode2);
});
it('should return different codes when no seed is provided', () => {
const avatarCode1 = generateRandomAvatarData();
const avatarCode2 = generateRandomAvatarData();
expect(avatarCode1).not.toEqual(avatarCode2);
});
});

describe('Get svg from avatar data', () => {
it('should fail if wrong avatar code is submited', () => {
expect(() => getAvatarFromData('')).toThrow('Incorrect avatar data');
Expand Down Expand Up @@ -41,4 +62,4 @@ describe('Get a random svg avatar', () => {
expect(getRandomAvatar(2, 'circle')).toMatch(/<svg xmlns="http:\/\/www.w3.org\/2000\/svg" width="100%" height="100%" viewBox="0 0 256 256">.+<\/svg>/);
expect(getRandomAvatar(2, 'circle', 16)).toMatch(/<svg xmlns="http:\/\/www.w3.org\/2000\/svg" width="100%" height="100%" viewBox="0 0 16 16">.+<\/svg>/);
});
});
});