@huz-com/game-developer-sdk

1.0.29 • Public • Published

Huz.Com > SDK > Game Developer

  • Stores game x profile data, statistics, leaderboards etc
  • Serves stored data
  • Provide to filter/criteria in stored data for game
  • Provide to learn player status for game

For SDK Developers

Standards

  • Language: TS
  • Eslint: Yes
  • Static Code Analysis: Yes IntelliJ Code Inspections
  • DDD - Document Driven: Yes
  • EDD - Exception Driven: Yes
  • TDD - Test Driven: Yes go to test folder
  • NoSQL, Dynamic Entity: Yes
  • Standards Complied: Huz Standards

Commands

  • npm run clear // clears "dist" folder
  • npm run lint // runs eslint for static code analysis
  • npm run test // runs test files in "test" folder
  • npm run build // builds JS files at "dist" folder
  • npm publish or npm run publix // publishes "dist" folder to npm

For Game Developers

Install

npm i @huz-com/game-developer-sdk

Usage

Importing

Export Instances: connector

Export Builder Classes: AnalyzeBuilder, FilterBuilder, SetBuilder, IncrementBuilder

Export Enum Classes: PrimitiveTypeEnum, EqualityEnum, AggregationEnum

const {connector} = require('@huz-com/game-developer-sdk');

Initialization

// initializes api connection options
connector.init({
    apiUrl: 'given-api-url',
    project: 'given-project-id',
    secret: 'given-game-secret',
    silent: false // if false, prints console.log messages
});

Basic Operations

Get, Set, Delete

// get all data
connector.getAsync(
).then((content) => {}).catch((err) => {});

// get partial data
connector.partialAsync(
    // returns only given fields
    'field1', 'field2', 'field3'
).then((content) => {}).catch((err) => {});

// set multiple data
connector.setAsync({
    // set point value, if existing them overwrite else create field    
    point: 101,
    // set level value, if existing them overwrite else create field
    level: 2,
    // set is favorited value, if existing them overwrite else create field
    isFavorited: false,
    // set level-1 date value, if existing them overwrite else create field, ISO Datetime format
    level1Date: '2020-01-03T13:35:00.000Z'
}).then((content) => {}).catch((err) => {});

// set one data
connector.setAsync({
    // set point value, if existing them overwrite else create field    
    point: 104,
}).then((content) => {}).catch((err) => {});

// set array data
connector.setAsync({
    // sets favorite colors as array, ie: you can use $intersects in where    
    favoriteColors: ['red', 'blue', 'black'],
}).then((content) => {}).catch((err) => {});

// increment multiple data
connector.incrementAsync({
    // increments level 2 point value if exists, else it evaluates old value is zero and increments again    
    level2Point: 10,
    // increments gold count value if exists, else it evaluates old value is zero and increments again    
    goldCount: 2,
}).then((content) => {}).catch((err) => {});

// increment one data
connector.incrementAsync({
    // increments level 2 point value if exists, else it evaluates old value is zero and increments again    
    level2Point: 10,
}).then((content) => {}).catch((err) => {});

// decrement one data
connector.incrementAsync({
    // decrements (because negative) gold value if exists, else it evaluates old value is zero and decrements again    
    gold: -1
}).then((content) => {}).catch((err) => {});

// decrement multiple data
connector.incrementAsync({
    // decrements (because negative) gold value if exists, else it evaluates old value is zero and decrements again    
    gold: -1,
    // decrements (because negative) point value if exists, else it evaluates old value is zero and decrements again    
    point: -10,
}).then((content) => {}).catch((err) => {});

// delete partial data
connector.deleteAsync(
    // deletes field1, field2 and field3 if any of them is existing
    'field1', 'field2', 'field3'
).then((content) => {}).catch((err) => {});

Filter Operations (Native)

Top-n Lists, ScoreBoard, LeaderBoard etc

// list top-20 players by track 1 point if player is;
// - "at level 3"
connector.filterAsync({
    select: [
        // get track 1 point and type is integer
        {field: 'track1Point', type: 'integer'},
    ],
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
    ],
    orderBy: [
        // sort players by track 1 point desc (9 > 0)
        {field: 'track1Point', type: 'integer', desc: true},
    ],
    // top 20 players
    limit: 20,
}).then((content) => {}).catch((err) => {});

// list top-20 players by track 1 point if player is;
// - "at level 3" and "male"
connector.filterAsync({
    select: [
        // get track 1 point and type is integer
        {field: 'track1Point', type: 'integer'},
    ],
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
        // Players are male or boy
        {field: 'gender', values: ['male'], type: 'string', equation: '$eq'},
    ],
    orderBy: [
        // sort players by track 1 point desc (9 > 0)
        {field: 'track1Point', type: 'integer', desc: true},
    ],
    // top 20 players
    limit: 20,
}).then((content) => {}).catch((err) => {});

// list top-20 players by track 1 point if player is;
// - "at level 3" and "male" and "clicked before 2020-09-01"
connector.filterAsync({
    select: [
        // get track 1 point and type is integer
        {field: 'track1Point', type: 'integer'},
    ],
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
        // Players are male or boy
        {field: 'gender', values: ['male'], type: 'string', equation: '$eq'},
        // Players are clicked before 2020-09-01
        {field: 'firstClickDate', values: ['2020-09-01'], type: 'date', equation: '$lt'},
    ],
    orderBy: [
        // sort players by track 1 point desc (9 > 0)
        {field: 'track1Point', type: 'integer', desc: true},
    ],
    // top 20 players
    limit: 20,
}).then((content) => {}).catch((err) => {});

// list top-20 players by track 1 point if player is;
// - "at level 3" and "male" and "clicked before 2020-09-01" and "favorite color is red"
connector.filterAsync({
    select: [
        // get track 1 point and type is integer
        {field: 'track1Point', type: 'integer'},
    ],
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
        // Players are male or boy
        {field: 'gender', values: ['male'], type: 'string', equation: '$eq'},
        // Players are clicked before 2020-09-01
        {field: 'firstClickDate', values: ['2020-09-01'], type: 'date', equation: '$lt'},
        // Players who has favorite color is red, favoriteColors is array, so we used intersects
        {field: 'favoriteColors', values: ['red'], type: 'string', equation: '$intersects'},
    ],
    orderBy: [
        // sort players by track 1 point desc (9 > 0)
        {field: 'track1Point', type: 'integer', desc: true},
    ],
    // top 20 players
    limit: 20,
}).then((content) => {}).catch((err) => {});

Analyze Operations (Native)

Comparison current player to all players

// analyze current player by track 1 point with players who are;
// - "at level 3"
connector.analyzeAsync({
    // analyze by track 1 point and value is integer
    field: 'track1Point',
    type: 'integer',
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
    ],
}).then((content) => {}).catch((err) => {});

// analyze current player by track 1 point with players who are;
// - "at level 3" and "male"
connector.analyzeAsync({
    // analyze by track 1 point and value is integer
    field: 'track1Point',
    type: 'integer',
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
        // Players are male or boy
        {field: 'gender', values: ['male'], type: 'string', equation: '$eq'},
    ],
}).then((content) => {}).catch((err) => {});

// analyze current player by track 1 point with players who are;
// - "at level 3" and "male" and "clicked before 2020-09-01"
connector.analyzeAsync({
    // analyze by track 1 point and value is integer
    field: 'track1Point',
    type: 'integer',
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
        // Players are male or boy
        {field: 'gender', values: ['male'], type: 'string', equation: '$eq'},
        // Players are clicked before 2020-09-01
        {field: 'firstClickDate', values: ['2020-09-01'], type: 'date', equation: '$lt'},
    ],
}).then((content) => {}).catch((err) => {});

// analyze current player by track 1 point with players who are;
// - "at level 3" and "male" and "clicked before 2020-09-01" and "favorite color is red"
connector.analyzeAsync({
    // analyze by track 1 point and value is integer
    field: 'track1Point',
    type: 'integer',
    where: [
        // Players are at level 3
        {field: 'level', values: [3], type: 'integer', equation: '$eq'},
        // Players are male or boy
        {field: 'gender', values: ['male'], type: 'string', equation: '$eq'},
        // Players are clicked before 2020-09-01
        {field: 'firstClickDate', values: ['2020-09-01'], type: 'date', equation: '$lt'},
        // Players who has favorite color is red, favoriteColors is array, so we used intersects
        {field: 'favoriteColors', values: ['red'], type: 'string', equation: '$intersects'},
    ],
}).then((content) => {}).catch((err) => {});

Basic Operations (Builder)

Set Builder is same with "connector.setAsync" method

Increment Builder is same with "connector.incrementAsync" method

Implemented to provide clean-code and easy-usage

// sets level and point values, if they are not existing create them
new SetBuilder()
    // set level as 6
    .field('level', 6)
    // set point as 3
    .field('point', 3)
    // trigger setAsync
    .runAsync()
    .then((content) => {}).catch((err) => {});

// increments level and point values if exist, else it evaluates old values are zero and increments again
new IncrementBuilder()
    // increment level with 6
    .field('level', 6)
    // increment point with 3
    .field('point', 3)
    // trigger incrementAsync
    .runAsync()
    .then((content) => {}).catch((err) => {});

Filter Operations (Builder)

Filter Builder is same with "connector.filterAsync" method

Implemented to provide clean-code and easy-usage

// list top-20 players by track 1 point if player is;
// - "at level 3"
new FilterBuilder()
    // get track 1 point and type is integer
    .select('track1Point', PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // sort players by track 1 point desc (9 > 0)
    .orderBy('track1Point', true, PrimitiveTypeEnum.INTEGER)
    // top 20 players
    .limit(20)
    // trigger filterAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

// list top-20 players by track 1 point if player is;
// - "at level 3" and "male"
new FilterBuilder()
    // get track 1 point and type is integer
    .select('track1Point', PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // Players are male or boy
    .where('gender', ['male'], EqualityEnum.EQUALS, PrimitiveTypeEnum.STRING)
    // sort players by track 1 point desc (9 > 0)
    .orderBy('track1Point', true, PrimitiveTypeEnum.INTEGER)
    // top 20 players
    .limit(20)
    // trigger filterAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

// list top-20 players by track 1 point if player is;
// - "at level 3" and "male" and "clicked before 2020-09-01"
new FilterBuilder()
    // get track 1 point and type is integer
    .select('track1Point', PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // Players are male or boy
    .where('gender', ['male'], EqualityEnum.EQUALS, PrimitiveTypeEnum.STRING)
    // Players are clicked before 2020-09-01
    .where('firstClickDate', ['2020-09-01'], EqualityEnum.LESS_THAN, PrimitiveTypeEnum.DATE)
    // sort players by track 1 point desc (9 > 0)
    .orderBy('track1Point', true, PrimitiveTypeEnum.INTEGER)
    // top 20 players
    .limit(20)
    // trigger filterAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

// list top-20 players by track 1 point if player is;
// - "at level 3" and "male" and "clicked before 2020-09-01" and "favorite color is red"
new FilterBuilder()
    // get track 1 point and type is integer
    .select('track1Point', PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // Players are male or boy
    .where('gender', ['male'], EqualityEnum.EQUALS, PrimitiveTypeEnum.STRING)
    // Players are clicked before 2020-09-01
    .where('firstClickDate', ['2020-09-01'], EqualityEnum.LESS_THAN, PrimitiveTypeEnum.DATE)
    // Players who has favorite color is red, favoriteColors is array, so we used intersects
    .where('favoriteColors', ['red'], EqualityEnum.INTERSECTS, PrimitiveTypeEnum.STRING)
    // sort players by track 1 point desc (9 > 0)
    .orderBy('track1Point', true, PrimitiveTypeEnum.INTEGER)
    // top 20 players
    .limit(20)
    // trigger filterAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

Analyze Operations (Builder)

Analyze Builder is same with "connector.analyzeAsync" method

Implemented to provide clean-code and easy-usage

// analyze current player by track 1 point with players who are;
// - "at level 3"
new AnalyzeBuilder()
    // analyze by track 1 point and value is integer
    .field('track1Point').type(PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // trigger analyzeAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

// analyze current player by track 1 point with players who are;
// - "at level 3" and "male"
new AnalyzeBuilder()
    // analyze by track 1 point and value is integer
    .field('track1Point').type(PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // Players are male or boy
    .where('gender', ['male'], EqualityEnum.EQUALS, PrimitiveTypeEnum.STRING)
    // trigger analyzeAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

// analyze current player by track 1 point with players who are;
// - "at level 3" and "male" and "clicked before 2020-09-01"
new AnalyzeBuilder()
    // analyze by track 1 point and value is integer
    .field('track1Point').type(PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // Players are male or boy
    .where('gender', ['male'], EqualityEnum.EQUALS, PrimitiveTypeEnum.STRING)
    // Players are clicked before 2020-09-01
    .where('firstClickDate', ['2020-09-01'], EqualityEnum.LESS_THAN, PrimitiveTypeEnum.DATE)
    // trigger analyzeAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

// analyze current player by track 1 point with players who are;
// - "at level 3" and "male" and "clicked before 2020-09-01" and "favorite color is red"
new AnalyzeBuilder()
    // analyze by track 1 point and value is integer
    .field('track1Point').type(PrimitiveTypeEnum.INTEGER)
    // Players are at level 3
    .where('level', [3], EqualityEnum.EQUALS, PrimitiveTypeEnum.INTEGER)
    // Players are male or boy
    .where('gender', ['male'], EqualityEnum.EQUALS, PrimitiveTypeEnum.STRING)
    // Players are clicked before 2020-09-01
    .where('firstClickDate', ['2020-09-01'], EqualityEnum.LESS_THAN, PrimitiveTypeEnum.DATE)
    // Players who has favorite color is red, favoriteColors is array, so we used intersects
    .where('favoriteColors', ['red'], EqualityEnum.INTERSECTS, PrimitiveTypeEnum.STRING)
    // trigger analyzeAsync with collected payload above
    .runAsync()
    .then((content) => {}).catch((err) => {});

Current Player

Fetch current player info

connector.meAsync({
}).then((content) => {}).catch((err) => {});

Types

Interfaces / Models

// setAsync, incrementAsync, deleteAsync response
interface UpdateResponse {
    changed: number; // changed value
    ignored: number; // ignored value for some reasons (not changed, readonly, invalid etc)
}
// getAsync response
interface GetResponse extends Record<string, unknown> {
    createdAt?: string; // default system field, it holds first activity time
    updatedAt?: string; // default system field, it holds latest updating activity time
    // record means, more keys can be responded, ie: dynamic entity
}
// analyzeAsync request
interface AnalyzeRequest {
    field: string; // which field will be analyzed
    type?: string | PrimitiveTypeEnum; // data type of field, default: string
    where?: Array<QueryWhereItem>; // criteria
}
// analyzeAsync response
interface AnalyzeResponse {
    aboveCount: number; // # of players who's value is greater then current player (by response.field)
    belowCount: number; // # of players who's value is less then current player (by response.field)
    sameCount: number; // # of players who's value is equal to current player (by response.field)
    noneCount: number; // # of players who have not any value (by response.field)
    selfValue: unknown; // current player's value (by response.field)
    minValue: unknown; // min value in all players (by response.field)
    maxValue: unknown; // max value in all players (by response.field)
}
// filterAsync request
interface FilterRequest {
    select: Array<QuerySelectItem>; // selected fields, at least one
    where?: Array<QueryWhereItem>; // where criteria
    groupBy?: Array<QueryGroupByItem>; // group by criteria, not implemented, reserved for future
    orderBy?: Array<QueryOrderByItem>; // order statements
    limit?: number; // limit, top-n value, default: 20
    offset?: number; // for pagination, offset value, default: 0
}
interface FilterResponse extends Record<string, unknown> {
    profile: ProfilePair; // profile info
    // record means, more keys can be responded, by response.select fields
}
// each select item in filterAsync
interface QuerySelectItem {
    field: string; // selected field
    type?: PrimitiveTypeEnum; // field type, default: string
    aggregate?: AggregationEnum; // reserved for future and group by
}
// each where item in filterAsync and analyzeAsync
interface QueryWhereItem {
    field: string; // criteria or filtered field
    values?: Array<unknown>; //value or values of criteria
    type?: PrimitiveTypeEnum; // field type, default: string
    equation?: EqualityEnum; // equation of criteria
}
// each group by item in filterAsync
interface QueryGroupByItem {
    field: string; // grouped field
    type?: PrimitiveTypeEnum; // field type, default: string
}
// each order by item in filterAsync
interface QueryOrderByItem {
    field: string; // ordered field
    type?: PrimitiveTypeEnum; // field type, default: string
    desc?: boolean; // is desc or asc, default: false ASC: A->Z, 0->0, DESC: Z-A, 9->0
}

Profile Models

interface ProfileEntity extends Record<string, unknown> {
    id: string;
    name: string; // nickname of player
    role: BasePair; // $.id can be [owner, kid, adult]
    kind: BasePair; // $.id can be [demo, anonymous, regular, subscribed]
    effectiveKind: BasePair; // $.id can be [demo, anonymous, regular, subscribed]
    avatar: BasePair; // $.id is global media in huz
    theme: string; // ui theme name
    pegi?: BasePair; // age group
    language: BasePair; // $.id is 2-letter language code, ie: en, nl, de, it
    country: BasePair; // $.id is 2-letter country code, ie: NL, DE, UK, US, TR
    timezone: string; // standart timezone text, ie: Europe/Amsterdam
    isKid: boolean; // shortcut for role==kid
    anonymous: boolean; // shortcut for kind==anonymous
}
// it is used filter.response[].profile
interface ProfilePair {
    id: string;
    name: string;
    avatar: AvatarPair;
}
interface BasePair {
    id: string;
    name: string;
}
interface AvatarPair {
    id: string;
}

Enumerations / Static Items

// primitive data type for db value casting
enum PrimitiveTypeEnum {
    STRING = 'string', // plain text
    INTEGER = 'integer', // D
    FLOAT = 'float', // D.D
    BOOLEAN = 'boolean', // true, false
    DATETIME = 'datetime', // yyyy-mm-ddThh::ii:ss.eeeZ
    DATE = 'date', // yyyy-mm-dd
}
// it is used in filter.where[].equation and analyze.where[].equation
enum EqualityEnum {
    EQUALS = '$eq', // a == b, if "a" is not array
    NOT_EQUALS = '$eq_not', // a != b, if "a" is not array
    TRUE = '$true', // a == true, if type is boolean
    FALSE = '$false', // a == false, if type is boolean
    NULL = '$null', // a == null, if "a" is not array
    NOT_NULL = '$null_not', // a != null, if "a" is not array
    GREATER_THAN = '$gt', // a > b, if "a" is not array
    NOT_GREATER_THAN = '$gt_not', // !(a > b), if "a" is not array
    GREATER_OR_EQUAL_THAN = '$gte', // a >= b, if "a" is not array
    NOT_GREATER_OR_EQUAL_THAN = '$gte_not', // !(a >= b), if "a" is not array
    LESS_THAN = '$lt', // a < b, if "a" is not array
    NOT_LESS_THAN = '$lt_not', // !(a < b), if "a" is not array
    LESS_OR_EQUAL_THAN = '$lte', // a <= b, if "a" is not array
    NOT_LESS_OR_EQUAL_THAN = '$lte_not', // !(a <= b), if "a" is not array
    BETWEEN = '$between', // (a >= b) && (a <= c), if "a" is not array
    NOT_BETWEEN = '$between_not', // !((a >= b) && (a <= c)), if "a" is not array
    IN = '$in', // a in [b,c,d,..], if "a" is not array
    NOT_IN = '$in_not', // !(a in [b,c,d,..]), if "a" is not array
    INTERSECTS = '$intersects', // (a intersects [b,c,d,...]), if "a" is array
    NOT_INTERSECTS = '$intersects_not', // !(a intersects [b,c,d,...]), if "a" is array
    STARTS_WITH = '$starts_with', // a.startsWith(b), if type is string
    NOT_STARTS_WITH = '$starts_with_not', // !a.startsWith(b), if type is string
    ENDS_WITH = '$ends_with', // a.endsWith(b), if type is string
    NOT_ENDS_WITH = '$ends_with_not', // !a.endsWith(b), if type is string
    CONTAINS = '$contains', // a.contains(b), if type is string
    NOT_CONTAINS = '$contains_not', // !a.contains(b), if type is string
}
// reserved for future
enum AggregationEnum {
    COUNT = 'count', // count of players, ie: # of players
    AVG = 'avg', // average of player' values, ie: average point
    SUM = 'sum', // sum of player' values, ie: total gold won
    MIN = 'min', // min value of player' values, ie: min point
    MAX = 'max', // max value of player' values, ie: max point
}

Prepared By

Mustafa Yelmer, 2021-02-06, v03

Package Sidebar

Install

npm i @huz-com/game-developer-sdk

Weekly Downloads

0

Version

1.0.29

License

ISC

Unpacked Size

311 kB

Total Files

33

Last publish

Collaborators

  • demiremrece