@huz-com/game-developer-sdk
v1.0.29
Published
Score-board, data-bucket for game developers in Huz platform
Downloads
4
Readme
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" foldernpm run lint
// runs eslint for static code analysisnpm run test
// runs test files in "test" foldernpm run build
// builds JS files at "dist" foldernpm publish
ornpm 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
- To view models Profile Models
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