# SNACK 3.0 CHALLENGES
In the admin panel:
Challenges (v2.0):
- SNACKUP Challenges
- Completed Challenges
- Completed Gift Challenges
- Challenges Promo Codes
New [v3.0]
```
GET ?version=1
POST { version:1 }
ex:
v2.0 GET /snack/admin/challenge/getList?pagenumber=1&pagesize=20&order=asc
v3.0 GET /snack/admin/challenge/getList?pagenumber=1&pagesize=20&order=asc&version=1
```
Challenges (v3.0):
- Challenges (v3.0) [6 challenge types]
- Groups (v3.0)
- Completed Challenges (v3.0)
- Leader Board (Dashboard)
## Type of challenges:
| Challenge Type | Value (Int) |
| -------- | -------- |
| XXX Paid Premium Amount | 0 |
| Hit XXX steps | 1 |
| X no of days lower Bio Age than the actual age | 2 |
| Spend X no of Unique partners | 3 |
| X no of refer friends | 4 |
| Group Challenges | 5 |
| X no of transactions by partner | 6 |
| X no of transactions with any partners | 7 |
| Community challenge | 8 |
**NOTE:
SIT & UAT need to confirm: Admin panel + BE + DB**
Note: only for below challenge type:
start Date & endDate, no of days max of 30 Days
Hit XXX steps
X no of days lower Bio Age than the actual age
---
challenges [current v2.0]:
```json=
{
id, // auto generated one
uid, // we are generating it our end.
brandPremiumAppId,
brandName,
description,
title,
subtitle,
icon,
imageBackground,
startDate,
endDate,
content,
terms,
status, // 0 -> inactive, 1 -> active
type, // 0 -> normal, 1 -> gift
createdAt,
updatedAt,
}
```
challenges_v3.0 [New v3.0]:
```json=
{
id, // auto generated one
uid, // we are generating it our end.
brandPremiumAppId, // optional Default -> NULL
brandName, // optional Default -> NULL
title,
subtitle,
description,
icon,
imageBackground, // optional in create challenge, If it empty from Admin -> default Image.
listingActiveIcon, // New
listingInactiveIcon, // New
startDate,
endDate,
content,
terms,
status, // 0 -> inactive, 1 -> active
type, // 0 - 5
isDashboard,
sortNum,
createdAt,
updatedAt,
completionValue, // New Type. VARCHAR(255), we cast the type based on the challenge type.,
dashboardSortNum // Default -> 0
}
```
challenge_groups
```json=
{
id, // Auto Generated one.
displayName, // ex: NUS
title, // National University of Singapore
logo, // Upload Image
createdAt,
updatedAt,
status, // 0 -> inactive, 1 -> active
}
```
group_challenges
```json=
{
id,
challengeUid,
groupId,
status, // 0 -> inactive, 1 -> active,
createdAt,
updatedAt,
}
```
### Completed Challenges
```json=
user_challenges_v3
{
id,
challengeUid,
groupdId,
channelUserId,
email,
status, // 0 -> Joined but not completed, 1 -> completed, 2 -> completed and redeemed
progressValue,
createdAt,
updatedAt,
completedAt,
redeemedAt,
rewardedAt, // isRewarded, // flag to update the procurement of the Rewards sent to user by email.
}
```
### Leader Board
1. Scheudle the job to update the completed challengs everyday at 12AM
2. Update the completed challenges based on the user action.
- An API call in the background to update the completed challenges in the DB
- Challenge List ->
- ZA -> Data required for ML;
- Query -> pass the data to ML:
- every end of the Month we can do a data patch to completed challenges:
startDate: 17:05:2022 - 00:00:00
endDate: 18:05:2022 - 23:59:59
## XXX Paid Premium Amount
Within the challenge duration, ZA paid the premium value:
user's progress (paid premium) Value: $20
Admin user configured as: $45
```
ZA: ${snackUrl}/snack/query/statisticsByUser
statisticsType: TOTAL_PAID_PREMIUM
Response:
{
...
"totalPaidPremium":"21.00",
}
```
## Hit XXX steps
Within the challenge duration, get the total number of steps:
user's progress Value: 12,000
Admin user configured as: 20000
```
ZA: ${snackUrl}/snack/query/snackFitActivity
Response:
"historyActivityList": [
{
"activityDate": "2021‐08‐24",
"height": 180,
"weight": "60",
"steps": 8100,
"kcal": 750,
"sleep": "8.5",
"rhr": "50.5",
"bioAge": "26",
"ageBalance": "1",
"calcuationTime": "2021‐08‐25 09:39:31"
},
"steps": 8100 Get the accumated value.
```
## X no of days lower Bio Age than the actual age
Within the challenge duration, get the bioAge:
user's progress Value: 6 (Get the no of days use's bio age is greater than zero)
Admin user configured as: 20
```
ZA: ${snackUrl}/snack/query/snackFitActivity
Response:
"historyActivityList": [
{
"activityDate": "2021‐08‐24",
"height": 180,
"weight": "60",
"steps": 8100,
"kcal": 750,
"sleep": "8.5",
"rhr": "50.5",
"bioAge": "26",
"ageBalance": "1",
"calcuationTime": "2021‐08‐25 09:39:31"
},
"ageBalance": "1",
23.02.2022 - 2
24.02.2022 - 0
25.02.2022 - 1
26.02.2022 - 0
...
total: 2
2 / 20 =
```
## Spend X no of Unique partners
Within the challenge duration, check how many SNACKUP partners user is spending.
user's progress Value: 2
Admin user configured as: 5
```
ZA: ${snackUrl}/snack/query/statisticsByUser
statisticsType: TOTAL_FREE_COVERAGE
{
"value": {
"totalFreeCoverage": "20000",
"partnerCount": 4,
"partnerList": [
"FOODPANDA",
"UOB",
"REVOLUT",
"KIPOS"
],
partnerCount: 4 (progress Value)
```
## X no of refer friends
Within the challenge duration, check how many referrals user has.
user's progress Value: 2
Admin user configured as: 5
GET no of referral count from user.referrals where channelUserId='' AND (uppadtedAt >= challenge.startDate && updaatedAt <= challenge.endDate)
```
ML DB
```
## Group challenge points calculation
group_user_challenge_points
```json=
{
id,
channelUserId,
challengeUid,
groupId,
referralCount,
points // 0 -> Bonus points completed referrals and No of completed challenges.
createdAt,
updatedAt
}
```
1. on the fly get the individual referral count by a channelUserId
2. on the fly get the grp referral count by a group
channelUserID: 134454
No of completed challenges: 3
challengeUid: (ABC), completionValue: 20 pts
User(134454)'s total points for the challenge ABC is 60 pts (3 * 20)
### A schedular will be run every day, time will be provided by MG.
## Leader Board (Dashboard)
@subhaish, @joy, @yahui
```json=
challenge_leaderboard
{
id,
challengeUid,
status, // 0 -> inactive, 1 -> active,
title, //
description,
imageUrl,
createdAt,
updatedAt
}
challenge_leaderboard_points
{
id,
leaderboardId,
points,
groupId, // logo and the display name or | and title from there.
createdAt,
updatedAt
}
```
challenge Use cases.
1. When the challenge is active / completed, admin can edit except [statDate, endDate, completionValue, type of the challenge, title, subtitle]
2. For future grp challenge admin user can able to remove / add a new grp, and able to edit the fields.
For the PROGRESS UPDATE API:
1. Get all the challenges that user joined.
2. Based on each challenge type update the progress Value.
**@Joy, - Feedback from client by 14 Jun 2022
For query the data to update the progress of the challenge, start date will be the joined date of the challenge by the user.**
type == 4
user.referrals & filter user.referrals.updatedAt
## Completed challenges CSV
## Challenge Query
```javascript=
List:
QUERY:
(startDate <= currentDate && currentDate <= endDate) && staus == 1
SORT:
sortNum
Dashboard QUERY:
(startDate <= currentDate && currentDate <= endDate) && staus == 1 && isDashboard == 1
SORT:
dashboardSortNum
History (User):
challenges: noOfDays(currentDate - challenge.startDate) <= 90 && staus == 1
user_challenges:
status = 0 [Joined not completed] && challenge.endDate < currentDate
status = 1 [Completed] && challenge.endDate < currentDate
status = 2 [Completed and Redeemed]
```
Update from clinet: 15 June 2022:
`These 2 parts I am wondering if it is possible. Replace the top 3 leaderboard to school leaderboard, and display the student's rank in their school`

@Joy can we check the rank for the user within a grp challenge?
Note: Query to MG
For leaderboard points: CRON JOB vs MANUAL (override the value or not)
@Karthik
As checked with MG it will be MANUAL for phase1, in phase2 we can update the logic with CRON JOB.
1. Update Progress: User request
- ZA: snackFitActivity, statisticsByUser [1:1]
CRON - Job, 15K - 15K per one challenge, 4 = 60K
Graphene 2.0
- Batch update API [100],
## Phase2: Challenges:
API specification:
ZA -> ML:
CRON - grp challenges
/status/update
ZA -> ML -> AML status [ML DB]:
## Challenge Enhancement for update progress
### Real Time
ML provide an API, ZA will call the ML API whenever the values updated.
- Request body for all challenge types:
- date - current Date
## XXX Paid Premium Amount
```json
{
"channelUserId": 33434,
"date": "27-08-2022"
"statisticsType": "TOTAL_PAID_PREMIUM"
"statisticsValue":"21.00"
}
```
## Spend X no of Unique partners
```json
{
"channelUserId": 33434,
"date": "27-08-2022"
"statisticsType": "TOTAL_FREE_COVERAGE_NO_OF_PARTNERS"
"statisticsValue": 4
}
```
## Hit XXX steps
```json
{
"channelUserId": 33434,
"date": "27-08-2022"
"statisticsType": "SNACK_FIT_TOTAL_STEPS"
"statisticsValue": 2000
}
```
## X no of days lower Bio Age than the actual age
```json
{
"channelUserId": 33434,
"date": "27-08-2022"
"statisticsType": "SNACK_FIT_AGE_BALANCE"
"statisticsValue": 0
}
```
Note: Export the data from ZA and import in ML DB before rollout this enhancement.
## upcoming challenges.
```json
{
"channelUserId": 33434,
"date": "27-08-2022"
"statisticsType": "TOTAL_FREE_COVERAGE"
"statisticsValue": "20000"
}
```
statisticsByUser
snackFitActivity
### statisticsTypes
TOTAL_PAID_PREMIUM
TOTAL_FREE_COVERAGE_NO_OF_PARTNERS
SNACK_FIT_AGE_BALANCE
SNACK_FIT_TOTAL_STEPS
CRON JOB, bulk Query:
[
".. channelUserIds",
"statisticsType": "TOTAL_FREE_COVERAGE",
]
Note: Each challenge for a user has diff startDate (joined date of the challenge), endDate will be challenge end Date.
## 14.12.2022 => Community Challenge
1. Dashboard [New Template]
Type "EXPLORE_CHALLENGE"
Title
Image
Template => TOP IMAGE
htmlDescription => html text
contentImage => NEW IMAGE INPUT [optional]
backgroundColor: {
startColor: "", [text input] [hex value]
endColor: "" [text input] [hex value]
} [optional],
Active
Order
Content


2. Community Challenge:


Challenge Type => Community challenge (8)
Challenge Title [html text]
Challenge Subtitle [html text]
Description [html text]
Scheduled on
Image Background
Icon
Listing Active Icon Url
Listing Inactive Icon Url
Content
Terms and Conditions
Completion Value
Order
Is Dashboard
Active
NEW TABLE:
`community_challenge_additional_info`
id,
title [html text],
description [html text],
image,
backgroundColor: {
startColor: "", [text input] [hex value]
endColor: "" [text input] [hex value]
} [JSON],
content: [
{
label [html text],
value [html text],
info [html text],
subInfo [html text] [optional],
}
] [JSON],
tiers: [
{
displayText (required) [html text],
displayLabel (required) [html text],
activeImage (optional),
inactiveImage (optional),
isActive (required) [bool]
}
] [JSON],
contentUpdatedAt, [datetime input] // SGT
createdAt,
updatedAt
# 7.12.2022 - X no of transactions by partner, X no of transaction by any partner
include datasouce in the Filter:

Dropdown:
```json
{
"None": "",
"Visa": "DS0005",
"Mastercard": "DS0013"
}
```