From 0fe924dcde0eb3cb75a801eacf9952763b039784 Mon Sep 17 00:00:00 2001 From: isuru89 Date: Tue, 9 Mar 2021 15:58:56 +0530 Subject: [PATCH] improve documentation #74 --- README.md | 16 ++--- docs/specs/badges.md | 119 +++++++++++++++++++++++++++++++++++++- docs/specs/leaderboard.md | 53 ++--------------- docs/specs/milestones.md | 80 +++++++++++++++++++++---- docs/specs/points.md | 100 +++++++++++++++++++++++++++----- docs/specs/ratings.md | 28 ++++++--- 6 files changed, 303 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 6d916c45..828a64d4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Open-source Gamification framework based on Redis. Oasis, is an event-driven gamification framework having ability to define the game rules for events coming from your applications. This is inspired from Stackoverflow badge system, and extended into -supporting many game elements, such as, points, badges, leaderboards, +supporting many other game elements, such as, points, badges, leaderboards, milestones, challenges, and ratings. ## Features: @@ -57,14 +57,14 @@ As of initial version, Redis will act as the database for engine operations cons This is a full deployment with all the components as shown in [Architecture](#architecture-of-oasis). This provides out-of-the-box components which can be used by your applications. -For testing purpose, a docker compose has been provided to up and running locally. +For testing purpose, a docker compose setup has been provided to up and running locally. Kubernetes and AWS solution are still pending. ### Embedding Engine One of the important thing about Oasis is that you can embed the game engine -inside your application. In this way, you have to pumping all your events and getting +inside your application. In this way, you have to pump all your events and getting data/statistics out of Redis. Its very simple. @@ -118,7 +118,7 @@ There are four major participants in the system. A game is a boundary of all game elements. Manipulation of games can only be done by an admin thorugh Stats API. -####Player: +#### Player: A player is an entity who associate with events and get rewarded from elements. Players can register to the system only by Admins and they will be uniquely identified by email address. Also Players needs to associate with a game through a team. That means every player must be a member of team. @@ -243,14 +243,13 @@ be ratings can fluctuate to any direction, while milestones can only grow. ### Leaderboards -Oasis provides leaderboards based on points scored by users. There are several leaderboards -supported by a game. Such as, -1. Game Leaderboard -2. Team Leaderboard +Oasis provides leaderboards based on points scored by users. +Leaderboards are scoped to game and team levels. Each leaderboard can be viewed scoped on the time slots. Supported time slots are; daily, weekly, monthly, quarterly and annually. +**_Note_**: Oasis will not support global leaderboards where players can be compared across games. ## Why Oasis? @@ -273,6 +272,7 @@ Following gamifiable environments have been identified. * Cloud friendly ## Contributing +TBW ## Kudos! diff --git a/docs/specs/badges.md b/docs/specs/badges.md index 893a35c6..df0f3dd0 100644 --- a/docs/specs/badges.md +++ b/docs/specs/badges.md @@ -1,5 +1,8 @@ # Badges +After points, badges are the most important element. And Oasis has a rich support +for awarding badges for different rules. + * Badges must be pre-defined before the gameplay. * Some badges may be defined only to award manually. * Only by Admin or Curator. @@ -15,8 +18,8 @@ A badge can be awarded using below ways. * An event is occurred for the first time. * e.g. First time login. -* Based on a simple condition satisfying in a event. - * Based on multiple conditions having different thresholds, sub-badges may award +* Based on a simple condition satisfying within an event. + * Based on multiple conditions with different thresholds, sub-badges can be awarded * Streaks: Continuously satisfy a condition * Can be combined with time constraints. e.g. should have the streak within last N days/hours. * When some condition is satisfied N times within a time constraint. @@ -30,6 +33,9 @@ A badge can be awarded using below ways. * Completing a milestone level. * Manually. +## Specification +TBW + ## Time Constraints * Time will consider always only to the past. @@ -38,4 +44,111 @@ A badge can be awarded using below ways. * Badges can consider fixed time periods. * within monthly (from 1st day of the month to the last day of month) * within weekly (from Monday to Sunday) - * within daily (from morning to midnight) \ No newline at end of file + * within daily (from morning to midnight) + +## Examples + +A comprehensive set of examples for badges can be viewed from [this directory](elements/badges/src/test/resources). + +* First event badge +```yaml + - id: BDG00001 + name: Initial-Registration + description: Awards a badge when a user first registered within the application. + event: app.user.registered + kind: firstEvent +``` + +* Sub badges based on conditions +```yaml + - id: BDG-C0001 + name: Question-Quality + description: Awards badges based on how many scores got for the question + event: question.scored + kind: conditional + conditions: + - priority: 1 + attribute: 30 + condition: "e.score >= 100" + - priority: 2 + attribute: 20 + condition: "e.score >= 25" + - priority: 3 + attribute: 10 + condition: "e.score >= 10" +``` + +* Badges based on continuous streaks +```yaml + - id: BDG-S0001 + name: Question-Score-Streak + description: Awards badges when a question is up voted consecutively + event: question.voted + kind: streak + condition: "e.upvote == true" # if condition become falsy, then streak will break. + streaks: + - streak: 10 + attribute: 10 + - streak: 50 + attribute: 20 + - streak: 100 + attribute: 30 +``` + +* Badges based on periodic aggregations +```yaml + - id: BDG-P0001 + name: Daily-Reputations + description: Accumulates user reputation daily and awards badges if user scores 50+ reputations on a day + kind: periodicAccumulation + event: reputation.changed + timeUnit: daily + aggregatorExtractor: e.reputations + thresholds: + - value: 50 # 50 reputations + attribute: 10 + - value: 100 # 100 reputations + attribute: 20 + - value: 200 # 200 reputations + attribute: 30 +``` + +* Badges based on periodic streaks +```yaml + - id: BDG-PS0001 + name: Daily-Reputations + description: Accumulates user reputation and awards badges if user scores 200+ reputation for minimum 5 consecutive days. + kind: periodicAccumulationStreak + event: reputation.changed + threshold: 200 + timeUnit: daily + consecutive: true + aggregatorExtractor: e.reputations + streaks: + - streak: 5 # 5 consecutive days + attribute: 10 + - streak: 7 # 7 consecutive days + attribute: 20 + - streak: 10 # 10 consecutive days + attribute: 30 +``` + +* Badges which awards points +```yaml + - id: BDG00002 + name: test.badge.points.rule + description: Awards badge and points if value is >= 50 for streaks + plugin: core:badge + kind: streak + event: event.a + eventFilter: e.value >= 50 + timeUnit: 10 + pointId: star.points + streaks: + - streak: 3 + attribute: 10 + pointAwards: 50 + - streak: 5 + attribute: 20 + pointAwards: 100 +``` \ No newline at end of file diff --git a/docs/specs/leaderboard.md b/docs/specs/leaderboard.md index 6ff7278f..142d7b2b 100644 --- a/docs/specs/leaderboard.md +++ b/docs/specs/leaderboard.md @@ -1,54 +1,11 @@ # Leaderboards -* Leaderboards are only defined from points. -* Leaderboard definitions can be created by Curators and Admin only. - * Curators' leaderboards are defined only to their team-scope. - * Admin's leaderboards are global and visible to all. -* Leaderboards can be defined while the game is playing. -* Leaderboards are calculated on-the-fly, will not be cached. (?) -* Leaderboards are defined within three dimensions. +* Leaderboards are **_only_** defined from points. +* Leaderboards are defined against two dimensions. * Time range = daily / weekly / monthly / all time / custom ranges - * Point Rules = set of point rule(s) to get sum of points - * Scope = team-wise, team-scope-wise, global + * Scope = team-wise, game-wise -## Leaderboard Definition +## Tie-breakers -* Can include a set of point rule ids to calculate sum for. -* Can include a set of point rule ids to exclude from sum calculation. - * Once exclude set has been defined, any rules other than specified will be taken into sum. -* **Cannot** define include set and exclude set in a single leaderboard definition. -* Order can be defined. - * Either it must be ascending (asc) or descending (desc). - * Default is _descending_. - -## Tie Breakers +* When two users have same number of points, there is no guarantee that which player will come first. -* When two users have same number of points, we will be using total event count contributed - to the total points as tie breaker. -* The lower the count, will be the higher in rank. -* If it is to have same event count, then they will have the **same rank**. - * For eg: Adam and Lily will get two ranks because their count is different although they have exactly same total points. - -| User | Points | #Events | Rank | -|--- |--- |--- | --- | -| Jon | 7739 | 121 | 1 | -| **Adam** | 3864 | 78 | **2** | -| **Lily** | 3864 | 91 | **3** | -| Shanon | 2705 | 74 | 4 | -| Gabriel | 921 | 32 | 5 | - -* In case, assume that Adam and Lily has the same count, then both of their ranks will be same. - * Here Lily and Adam both will be ranked #2. - * And Shanon will still be 4th, not 3rd. - -| User | Points | #Events | Rank | -|--- |--- |--- | --- | -| Jon | 7739 | 121 | 1 | -| **Adam** | 3864 | 78 | **2** | -| **Lily** | 3864 | 78 | **2** | -| Shanon | 2705 | 74 | 4 | -| Gabriel | 921 | 32 | 5 | - -* When you want to get top 3 from above leaderboard, it will return only based on rank. - * Therefore, only Jon, Adam and Lily will be returned. - * Shanon will be ignored as her rank is 4th. \ No newline at end of file diff --git a/docs/specs/milestones.md b/docs/specs/milestones.md index 68d4c3f9..dfd171bc 100644 --- a/docs/specs/milestones.md +++ b/docs/specs/milestones.md @@ -1,21 +1,81 @@ # Milestones * All milestones are pre-defined before gameplay. -* Can be defined only by admin. +* Can be defined only by Admin. * Milestones never ends. They are played by players forever. * Milestone should be defined in a way which can play forever. * At least two levels must be there for a milestone. -* A milestone can have only **finite** amount of levels. -* When a user has reached maximum level of a milestone, Oasis consider he/she has completed the milestone. -* Milestone aggregating values must be monotonically increasing. - * Penalty values (negative values) will be accumulated separately along with positive values. -* Once user achieved a level, it cannot be undone. - * Due to the penalty values, it might go below the current level. But it does not +* A milestone can have only **finite** number of levels. +* When a player has reached maximum level of a milestone, Oasis considers that player has completed the milestone. +* ~~Milestone aggregating values must be monotonically increasing.~~ + * ~~Penalty values (negative values) will be accumulated separately along with positive values.~~ +* Once a player achieved/surpassed a level, it cannot be undone. + * Due to the penalty values, it might go below the current level. But, it does not affect to the player's achieved level. ## Milestone Creation * Milestones should be defined only using aggregation functions - * Sum of points - * Sum of KPIs - * Count of events \ No newline at end of file + * Sum of point ids + * Sum of events + * Count of events + +## Specification +TBW + +## Examples + +More comprehensive set of examples can be found in this [file](elements/milestones/src/test/resources/milestones.yml) + +* Accumulate a single point id +```yaml + - id: MILE-0001 + name: Total-Reputations + description: Provides ranking through accumulated reputations + pointIds: + - stackoverflow.reputation + levels: + - level: 1 + milestone: 1000 + - level: 2 + milestone: 5000 + - level: 3 + milestone: 10000 + - level: 4 + milestone: 50000 + - level: 5 + milestone: 100000 +``` + +* Accumulates based on multiple point ids +```yaml + - name: Star-Points + description: Allow tiers for customers based on star points accumulated + pointIds: + - star.points + - coupan.points + levels: + - level: 1 + milestone: 100 + - level: 2 + milestone: 1000 + - level: 3 + milestone: 10000 +``` + +* Accumulate directly from events based on a condition +```yaml + - name: Milestone-with-Event-Count + description: This is a milestone counting events based on a criteria. + event: stackoverflow.question.answered + eventFilter: | + return e.answeredAt - e.askedAt <= 60 * 60 * 5 + valueExtractor: 1 + levels: + - level: 1 + milestone: 5 + - level: 2 + milestone: 10 + - level: 3 + milestone: 15 +``` \ No newline at end of file diff --git a/docs/specs/points.md b/docs/specs/points.md index 494bb8d4..3e58f76d 100644 --- a/docs/specs/points.md +++ b/docs/specs/points.md @@ -1,26 +1,96 @@ -# Points Scoring +# Points - * Points are always accurate no more than upto 2 decimal points - * Only users can score points - * A team is a user too. - * A team-scope is a user too. +Points is the only core game element shipped with while all other elements has to add explicitly. + + * Points are always accurate no more than up to 2 decimal points + * Only players can score points * Each point is associated with a type - * The timestamp, team and source will be recorded against each point. + * The timestamp, team and event source id will be recorded against each point event scored. * Once scored, points cannot be deleted or modified - * To delete, same amount of penalty points needs to be added against same user - * Not all points are considered as currency. - * But by default, all point rules considered as currency. - - + * To simulate a delete, same amount of penalty points needs to be added against same player manually. + ## Scoring Methods: * By raw events - * Based on some condition (KPI) - * By total points scored per event - * Several type of points can be generated per event. + * Based on some condition + * ~~By total points scored per event~~ + * ~~Several types of points can be generated per event.~~ * When earned a badge * When milestone level reached * Becoming a winner of a challenge - * Manually award by curator or admin + * Manually can be awarded by a Curator or Admin + +## Tips +* You can combine multiple rules to emit same point type by having same id for `pointId` field. + This is useful to combine awards based on multiple time ranges. + +## Specification +TBW + +## Examples + +More up to date but different examples can be viewed from this [file](elements/points/src/test/resources/points.yml) + +* Award a constant amount of points upon a particular event received (no condition) +```yaml +version: 1 + +points: + - name: Answer-Accepted + description: Awards 15 reputations when an answer has been accepted + event: stackoverflow.answer.accepted + pointId: stackoverflow.reputation + award: 15 +``` + +* Award amount of points based on the field in the event (no condition) +```yaml +- name: General-Spending-Rule + description: Customer could receive points for order value + event: order.accepted + pointId: star.points + award: "e.total" +``` +* Based on a event with a condition +```yaml + - name: Big-Purchase-Bonus + description: Customer receives bonus points for passing purchase limit + event: order.accepted + pointId: star.points + award: | + if (e.total >= 500) { + return (e.total - 500) * 10; + } else if (e.total >= 100) { + return (e.total - 100) * 3; + } else if (e.total >= 50) { + return (e.total - 50) * 2; + } + return 0; +``` +* Based on any type of events with a filter +```yaml + - id: PNT00001 + name: Bonus-Half-Century + description: Awards points for each additional value when total is greater than 50 + plugin: core:point + events: + - event.a + - event.c + eventFilter: e.value >= 50 + award: e.value - 50 + pointId: bonus.points +``` +* Seasonal points. This rule will double the awarded points only in the month of December. +```yaml + - name: Special-Seasonal-Award + description: Awards double bonus points for every purchase done on december + event: order.accepted + pointId: star.points + timeRanges: + - type: seasonal + from: "12-01" + to: "12-31" + award: "e.total * 2" +``` \ No newline at end of file diff --git a/docs/specs/ratings.md b/docs/specs/ratings.md index 87298c5a..cd102d1c 100644 --- a/docs/specs/ratings.md +++ b/docs/specs/ratings.md @@ -1,14 +1,24 @@ # Ratings -* A rating is a status which a user can be in at any given time. +A rating indicates a state of a player. + +* A rating is a status which a player can be in at any given time. * For e.g: Question to answer ratio, Violation density -* A user can have one-and-only rating at a given time. -* Every rating is being set according to the satisfying condition. +* A player can belong to one-and-only rating at a given time. +* A rating will be set according to the first satisfying condition of the rule. + * The ordering of conditions can be controlled through priority field * If no condition is satisfied, then default rating will be awarded. -* NOTE: It is advice to specify conditions to satisfy at least one. + + **NOTE**: It is advice to specify conditions to satisfy at least one. -* Very similar to milestones but does not accumulate through history. -* External applications must send events notifying the current state. - * Based on state, user will be awarded points. -* The points awarded from state won't be part of Milestones or any other game elements. - * State points are just a net points you awarded for being in that state. +* ~~External applications must send events notifying the current state.~~ + * ~~Based on state, user will be awarded points.~~ +* ~~The points awarded from state won't be part of Milestones or any other game elements.~~ + * ~~State points are just a net points you awarded for being in that state.~~ + + +## Specification +TBW + +## Examples +TBW \ No newline at end of file