Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/development' into task/bt-674-pr…
Browse files Browse the repository at this point in the history
…eview-project-to-real-data
  • Loading branch information
Monyster committed Sep 30, 2023
2 parents 94412db + 064ad5d commit b643694
Show file tree
Hide file tree
Showing 158 changed files with 2,051 additions and 842 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ rules:
ignoreTypeIndexes: true
ignore:
- 0
- 1
'@typescript-eslint/no-unsafe-member-access':
- 'off'
'@typescript-eslint/no-unsafe-assignment':
Expand All @@ -133,6 +134,8 @@ rules:
- 'off'
'@typescript-eslint/no-redundant-type-constituents':
- 'off'
'@typescript-eslint/prefer-nullish-coalescing':
- 'off'
overrides:
- files:
- commitlint.config.ts
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ jobs:
env:
ENVIRONMENT: ${{ secrets.MOBILE_ENVIRONMENT }}
API_URL: ${{ secrets.MOBILE_API_URL }}
run: 'echo -e "ENVIRONMENT=$ENVIRONMENT\nAPI_URL=$API_URL\n" > ./mobile/.env'
BASE_URL: ${{ secrets.MOBILE_BASE_URL }}
run: 'echo -e "ENVIRONMENT=$ENVIRONMENT\nAPI_URL=$API_URL\nBASE_URL=$BASE_URL\n" > ./mobile/.env'

- name: Build
run: cd ./mobile && cd ./android && ./gradlew clean assembleRelease
Expand Down
6 changes: 4 additions & 2 deletions backend/src/bundles/bsa-badges/bsa-badges.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import { type BSABadgesRepository } from '~/bundles/bsa-badges/bsa-badges.reposi
import { ErrorMessage } from '~/common/enums/enums.js';
import { type Service } from '~/common/types/types.js';

import { type BadgesResponseDto } from './types/types.js';

class BSABadgesService implements Service {
private bsaBadgesRepository: BSABadgesRepository;

public constructor(bsaBadgesRepository: BSABadgesRepository) {
this.bsaBadgesRepository = bsaBadgesRepository;
}

public async findAll(): Promise<{ items: BSABadgeEntity[] }> {
public async findAll(): Promise<BadgesResponseDto> {
const badges = await this.bsaBadgesRepository.findAll();
return { items: badges };
return { items: badges.map((badge) => badge.toObject()) };
}

public find(): Promise<BSABadgeEntity> {
Expand Down
1 change: 1 addition & 0 deletions backend/src/bundles/bsa-badges/types/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { type BadgesResponseDto } from 'shared/build/index.js';
1 change: 1 addition & 0 deletions backend/src/bundles/lms-data/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { defaultShownBadges } from './default-shown-badges.js';
12 changes: 12 additions & 0 deletions backend/src/bundles/lms-data/constants/default-shown-badges.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { BsaBadgesTypeEnum } from '../enums/enums.js';

const defaultShownBadges = {
[BsaBadgesTypeEnum.ENGLISH_LEVEL]: true,
[BsaBadgesTypeEnum.LECTURE_SCORE]: true,
[BsaBadgesTypeEnum.BEST_LECTURE_SCORE]: false,
[BsaBadgesTypeEnum.PROJECT_SCORE]: true,
[BsaBadgesTypeEnum.COMMUNICATION_SCORE]: false,
[BsaBadgesTypeEnum.TEAM_SCORE]: false,
} as const;

export { defaultShownBadges };
1 change: 1 addition & 0 deletions backend/src/bundles/lms-data/enums/enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { BsaBadgesTypeEnum } from 'shared/build/index.js';
10 changes: 10 additions & 0 deletions backend/src/bundles/lms-data/helpers/get-random-score.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const MOCK_SCORE = 3;
const MAX_SCORE = 5;
const DECIMAL_PLACES = 2;

const getRandomScore = (): number => {
const randomValue = MOCK_SCORE + Math.random() * (MAX_SCORE - MOCK_SCORE);
return Number(randomValue.toFixed(DECIMAL_PLACES));
};

export { getRandomScore };
2 changes: 2 additions & 0 deletions backend/src/bundles/lms-data/helpers/helpers.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { getRandomScore } from './get-random-score.js';
export { isNumber } from './is-number.js';
export { makeLMSDataResponse, parseLMSServerData } from 'shared/build/index.js';
5 changes: 5 additions & 0 deletions backend/src/bundles/lms-data/helpers/is-number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const isNumber = (value: unknown): value is number => {
return typeof value === 'number' && !Number.isNaN(value);
};

export { isNumber };
122 changes: 122 additions & 0 deletions backend/src/bundles/lms-data/helpers/map-talent-badges.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { BsaBadgesTypeEnum } from 'shared/build/index.js';

import { type ValueOf } from '~/common/types/types.js';

import { defaultShownBadges } from '../constants/constants.js';
import { badgeTypeToLMSProperty } from '../mappers/mappers.js';
import {
type BadgesItem,
type BadgesResponseDto,
type LectureDetail,
type LMSDataResponseDto,
type Marks,
type ProjectCoachesFeedback,
type TalentBadgeCreateDto,
} from '../types/types.js';
import { getRandomScore, isNumber } from './helpers.js';

const findScoreForCommunicationAndTeam = (
projectCoachesFeedback: ProjectCoachesFeedback[],
property: keyof Marks,
): number => {
let totalScore = 0;
let totalLenght = 0;

for (const week of projectCoachesFeedback) {
if (typeof week.marks[property] === 'number') {
totalScore += week.marks[property];
totalLenght++;
}
}

const averageScore = totalScore / totalLenght;

return isNumber(averageScore) ? averageScore : getRandomScore();
};

const findBestLectureScore = (
lectureDetails: LectureDetail[],
): number | null => {
if (lectureDetails.length === 0) {
return null;
}

let bestLecture = lectureDetails[0];

for (const lecture of lectureDetails) {
if (Number(lecture.grade) > Number(bestLecture.grade)) {
bestLecture = lecture;
}
}

return bestLecture.grade;
};

const isShown = (type: ValueOf<typeof BsaBadgesTypeEnum>): boolean => {
return defaultShownBadges[type];
};

const getBadgeId = (
bsaBadges: BadgesItem[],
badgeType: ValueOf<typeof BsaBadgesTypeEnum>,
): string => {
const badge = bsaBadges.find((badge) => badge.type === badgeType);
return badge?.id ?? '';
};

type TalentBadgeCreateBody = Omit<TalentBadgeCreateDto, 'id'>;

const mapTalentBadges = (
userDetailsId: string,
lmsData: LMSDataResponseDto,
bsaBadges: BadgesResponseDto,
): TalentBadgeCreateBody[] => {
return Object.keys(badgeTypeToLMSProperty).map((badgeType) => {
const property =
badgeTypeToLMSProperty[
badgeType as unknown as keyof typeof badgeTypeToLMSProperty
];
let score = null;
let level = null;

switch (badgeType) {
case BsaBadgesTypeEnum.COMMUNICATION_SCORE:
case BsaBadgesTypeEnum.TEAM_SCORE: {
score = findScoreForCommunicationAndTeam(
lmsData.projectCoachesFeedback,
property as keyof Marks,
);
break;
}
case BsaBadgesTypeEnum.BEST_LECTURE_SCORE: {
score = findBestLectureScore(lmsData.lectureDetails);
break;
}
case BsaBadgesTypeEnum.ENGLISH_LEVEL: {
score = null;
level = lmsData.talent.english;
break;
}
case BsaBadgesTypeEnum.LECTURE_SCORE:
case BsaBadgesTypeEnum.PROJECT_SCORE: {
score = lmsData[property as keyof LMSDataResponseDto] as number;
isNumber(score) || (score = getRandomScore());
break;
}
}

return {
userId: lmsData.talent.id,
badgeId: getBadgeId(
bsaBadges.items,
badgeType as ValueOf<typeof BsaBadgesTypeEnum>,
),
score,
level,
isShown: isShown(badgeType as ValueOf<typeof BsaBadgesTypeEnum>),
userDetailsId,
};
});
};

export { mapTalentBadges };
44 changes: 42 additions & 2 deletions backend/src/bundles/lms-data/lms-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { config } from '~/common/packages/config/config.js';
import { http } from '~/common/packages/http/http.js';
import { type Service } from '~/common/types/types.js';

import { type BSABadgesService } from '../bsa-badges/bsa-badges.service.js';
import { type TalentBadgeService } from '../talent-badges/talent-badge.service.js';
import { type UserDetailsService } from '../user-details/user-details.service.js';
import { makeLMSDataResponse, parseLMSServerData } from './helpers/helpers.js';
import { mapTalentBadges } from './helpers/map-talent-badges.js';
import { LMSDataEntity } from './lms-data.entity.js';
import { type LMSDataRepository } from './lms-data.repository.js';
import {
Expand All @@ -19,9 +23,25 @@ import {
class LMSDataService implements Service {
private lmsDataRepository: LMSDataRepository;
private requestsToLMSHeaders: { 'X-Token': string };

public constructor(lmsDataRepository: LMSDataRepository) {
private bsaBadgesService: BSABadgesService;
private talentBadgeService: TalentBadgeService;
private userDetailsService: UserDetailsService;

public constructor({
lmsDataRepository,
bsaBadgesService,
talentBadgeService,
userDetailsService,
}: {
lmsDataRepository: LMSDataRepository;
bsaBadgesService: BSABadgesService;
talentBadgeService: TalentBadgeService;
userDetailsService: UserDetailsService;
}) {
this.lmsDataRepository = lmsDataRepository;
this.bsaBadgesService = bsaBadgesService;
this.talentBadgeService = talentBadgeService;
this.userDetailsService = userDetailsService;
this.requestsToLMSHeaders = {
'X-Token': config.ENV.LMS_DATA_SERVER.LMS_X_TOKEN,
};
Expand Down Expand Up @@ -70,6 +90,26 @@ class LMSDataService implements Service {

const parsedLMSData = parseLMSServerData(userId, dataFromLMS);

const userDetails = await this.userDetailsService.create({
userId,
});

const userDetailsId = userDetails.id;

const bsaBadges = await this.bsaBadgesService.findAll();

const talentBadges = mapTalentBadges(
userDetailsId as string,
parsedLMSData,
bsaBadges,
);

await Promise.all(
talentBadges.map((talentBadge) =>
this.talentBadgeService.create(talentBadge),
),
);

const newDBRecord = await this.lmsDataRepository.create(
LMSDataEntity.initialize({
...parsedLMSData,
Expand Down
11 changes: 10 additions & 1 deletion backend/src/bundles/lms-data/lms-data.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { bsaBadgesService } from '../bsa-badges/bsa-badges.js';
import { talentBadgeService } from '../talent-badges/talent-badges.js';
import { userDetailsService } from '../user-details/user-details.js';
import { LMSDataModel } from './lms-data.model.js';
import { LMSDataRepository } from './lms-data.repository.js';
import { LMSDataService } from './lms-data.service.js';

const lmsDataRepository = new LMSDataRepository(LMSDataModel);
const lmsDataService = new LMSDataService(lmsDataRepository);

const lmsDataService = new LMSDataService({
lmsDataRepository,
bsaBadgesService: bsaBadgesService,
talentBadgeService: talentBadgeService,
userDetailsService: userDetailsService,
});

export { lmsDataService };
12 changes: 12 additions & 0 deletions backend/src/bundles/lms-data/mappers/badge-type-to-lms-property.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { BsaBadgesTypeEnum } from '../enums/enums.js';

const badgeTypeToLMSProperty = {
[BsaBadgesTypeEnum.ENGLISH_LEVEL]: 'english',
[BsaBadgesTypeEnum.LECTURE_SCORE]: 'averageLectureScore',
[BsaBadgesTypeEnum.BEST_LECTURE_SCORE]: 'grade',
[BsaBadgesTypeEnum.PROJECT_SCORE]: 'averageProjectScore',
[BsaBadgesTypeEnum.COMMUNICATION_SCORE]: 'communication_result',
[BsaBadgesTypeEnum.TEAM_SCORE]: 'team_interaction',
};

export { badgeTypeToLMSProperty };
1 change: 1 addition & 0 deletions backend/src/bundles/lms-data/mappers/mappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { badgeTypeToLMSProperty } from './badge-type-to-lms-property.js';
3 changes: 3 additions & 0 deletions backend/src/bundles/lms-data/types/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export {
type BadgesItem,
type BadgesResponseDto,
type Details,
type HrFeedback,
type LectureDetail,
Expand All @@ -9,6 +11,7 @@ export {
type ProjectCoachesFeedback,
type Result,
type Talent,
type TalentBadgeCreateDto,
type UserGetLMSDataById,
type UserLMSDataDto,
} from 'shared/build/index.js';
Loading

0 comments on commit b643694

Please sign in to comment.