Skip to content

Commit

Permalink
create new achievements for first student match
Browse files Browse the repository at this point in the history
  • Loading branch information
dhenkel92 committed Sep 11, 2024
1 parent 8ad1771 commit f1252a5
Show file tree
Hide file tree
Showing 11 changed files with 517 additions and 264 deletions.
76 changes: 30 additions & 46 deletions common/achievement/derive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ const GhostAchievements: { [key: string]: achievement_template } = {
group: PupilNewMatchGroup,
groupOrder: 1,
type: AchievementType.SEQUENTIAL,
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_1.png',
image: 'gamification/achievements/release/new_match/five_pieces/empty_state.png',
tagline: 'Starte eine Lernpatenschaft',
title: 'Neue Lernunterstützung',
subtitle: null,
description:
'Es war großartig, dich am {{date}} besser kennenzulernen und freuen uns, dass du gemeinsam mit uns die Bildungschancen von Schüler:innen verbessern möchtest. Um dir eine:n passende:n Lernpartner:in zuzuweisen, bitten wir dich zunächst, eine Anfrage auf unserer Plattform zu stellen. Hier kannst du die Fächer und Jahrgangsstufe angeben, die für dich passend sind. Wir freuen uns auf den Start!',
'Damit wir dir den:die perfekte:n Lernpartner:in zuweisen können, musst du zunächst eine Anfrage auf unserer Plattform stellen. Dort kannst du ganz einfach die Fächer angeben, die für dich wichtig sind und in denen wir dir helfen können. Wir freuen uns darauf, mit dir gemeinsam durchzustarten und die Lernreise zu beginnen!',
footer: null,
actionName: 'Anfrage stellen',
actionRedirectLink: '/matching',
actionRedirectLink: '/request-match',
actionType: AchievementActionType.Action,
condition: 'false', // This will ensure that an evaluation will always fail
conditionDataAggregations: {},
Expand All @@ -50,7 +50,7 @@ const GhostAchievements: { [key: string]: achievement_template } = {
group: PupilNewMatchGroup,
groupOrder: 2,
type: AchievementType.SEQUENTIAL,
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_2.png',
image: 'gamification/achievements/release/new_match/five_pieces/step_1.png',
tagline: 'Starte eine Lernpatenschaft',
title: 'Neue Lernunterstützung',
subtitle: null,
Expand All @@ -74,15 +74,15 @@ const GhostAchievements: { [key: string]: achievement_template } = {
group: StudentNewMatchGroup,
groupOrder: 1,
type: AchievementType.SEQUENTIAL,
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_1.png',
image: 'gamification/achievements/release/new_match/five_pieces/empty_state.png',
tagline: 'Starte eine Lernpatenschaft',
title: 'Neue Lernunterstützung',
subtitle: null,
description:
'Es war großartig, dich am {{date}} besser kennenzulernen und freuen uns, dass du gemeinsam mit uns die Bildungschancen von Schüler:innen verbessern möchtest. Um dir eine:n passende:n Lernpartner:in zuzuweisen, bitten wir dich zunächst, eine Anfrage auf unserer Plattform zu stellen. Hier kannst du die Fächer und Jahrgangsstufe angeben, die für dich passend sind. Wir freuen uns auf den Start!',
footer: null,
actionName: 'Anfrage stellen',
actionRedirectLink: '/matching',
actionRedirectLink: '/request-match',
actionType: AchievementActionType.Action,
condition: 'false', // This will ensure that an evaluation will always fail
conditionDataAggregations: {},
Expand All @@ -92,30 +92,6 @@ const GhostAchievements: { [key: string]: achievement_template } = {
achievedImage: null,
sequentialStepName: 'Anfrage stellen',
},
student_new_match_2: {
id: -1,
templateFor: AchievementTemplateFor.Match,
group: StudentNewMatchGroup,
groupOrder: 2,
type: AchievementType.SEQUENTIAL,
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_2.png',
tagline: 'Starte eine Lernpatenschaft',
title: 'Neue Lernunterstützung',
subtitle: null,
description:
'Fantastisch, deine Anfrage ist eingegangen! Bevor wir dir deine:n ideale:n Lernpartner:in vermitteln können, möchten wir gerne kurz per Zoom mit dir sprechen. Unser Ziel ist es, die perfekte Person für dich zu finden und genau zu verstehen, was du dir wünschst. Buche doch gleich einen Termin für unser Gespräch – wir sind schon ganz gespannt auf dich!',
footer: null,
actionName: 'Termin buchen',
actionRedirectLink: 'https://calendly.com',
actionType: AchievementActionType.Action,
condition: 'false',
conditionDataAggregations: {},
isActive: true,
achievedDescription: null,
achievedFooter: null,
achievedImage: null,
sequentialStepName: 'Gespräch mit Lern-Fair absolvieren',
},
};

// Large parts of our user communication are event based, i.e. users get a notification for an appointment,
Expand Down Expand Up @@ -175,6 +151,8 @@ async function generatePupilMatching(
});
}

console.log('iso', hasRequest, hasSuccessfulScreening, achievement);

result.push({
id: -1,
templateId: -1,
Expand All @@ -183,7 +161,8 @@ async function generatePupilMatching(
template: GhostAchievements.pupil_new_match_1,
context: ctx,
recordValue: null,
achievedAt: hasRequest || achievement ? new Date() : null,
achievedAt: new Date(),
// achievedAt: hasRequest || achievement ? new Date() : null,
relation: achievement?.relation ?? randomRelation,
});

Expand All @@ -195,7 +174,8 @@ async function generatePupilMatching(
template: GhostAchievements.pupil_new_match_2,
context: ctx,
recordValue: null,
achievedAt: hasSuccessfulScreening || achievement ? new Date() : null,
// achievedAt: hasSuccessfulScreening || achievement ? new Date() : null,
achievedAt: new Date(),
relation: achievement?.relation ?? randomRelation,
});
return result;
Expand All @@ -211,6 +191,7 @@ async function derivePupilMatching(user: User, pupil: Pupil, result: achievement
where: { pupilId: pupil.id, status: pupil_screening_status_enum.success, invalidated: false },
orderBy: { createdAt: 'desc' },
});
const totalMatchCount = await prisma.match.count({ where: { pupilId: pupil.id } });

const newMatchAchievements = userAchievements.filter(
(row) => row.template.group === PupilNewMatchGroup && row.template.groupOrder === PupilNewMatchGroupOrder
Expand All @@ -222,12 +203,20 @@ async function derivePupilMatching(user: User, pupil: Pupil, result: achievement
if (successfulScreenings.length > 0) {
ctx.lastScreeningDate = successfulScreenings[0].updatedAt.toISOString();
}
// This case happens when the student just registered and had a successful screening
if (pupil.openMatchRequestCount === 0 && totalMatchCount === 0) {
console.log('hier');
const ghosts = await generatePupilMatching(null, user, hasRequest, successfulScreenings.length > 0, ctx);
result.push(...ghosts);
}
for (let i = 0; i < pupil.openMatchRequestCount; i++) {
console.log('hier2');
const ghosts = await generatePupilMatching(null, user, hasRequest, successfulScreenings.length > 0, ctx);
result.push(...ghosts);
}

for (const userAchievement of newMatchAchievements) {
console.log('hier3');
const ghosts = await generatePupilMatching(userAchievement, user, hasRequest, successfulScreenings.length > 0, ctx);
result.push(...ghosts);
}
Expand All @@ -243,6 +232,7 @@ async function deriveStudentMatching(user: User, student: Student, result: achie
where: { studentId: student.id, success: true },
orderBy: { createdAt: 'desc' },
});
const totalMatchCount = await prisma.match.count({ where: { studentId: student.id } });

const newMatchAchievements = userAchievements.filter(
(row) => row.template.group === StudentNewMatchGroup && row.template.groupOrder === StudentNewMatchGroupOrder
Expand All @@ -254,13 +244,19 @@ async function deriveStudentMatching(user: User, student: Student, result: achie
if (successfulScreenings.length > 0) {
ctx.lastScreeningDate = successfulScreenings[0].updatedAt.toISOString();
}
// This case happens when the student just registered and had a successful screening
if (student.openMatchRequestCount === 0 && totalMatchCount === 0) {
const ghosts = await generateStudentMatching(null, user, hasRequest, ctx);
result.push(...ghosts);
}
// This will
for (let i = 0; i < student.openMatchRequestCount; i++) {
const ghosts = await generateStudentMatching(null, user, hasRequest, successfulScreenings.length > 0, ctx);
const ghosts = await generateStudentMatching(null, user, hasRequest, ctx);
result.push(...ghosts);
}

for (const userAchievement of newMatchAchievements) {
const ghosts = await generateStudentMatching(userAchievement, user, hasRequest, successfulScreenings.length > 0, ctx);
const ghosts = await generateStudentMatching(userAchievement, user, hasRequest, ctx);
result.push(...ghosts);
}
}
Expand All @@ -269,7 +265,6 @@ async function generateStudentMatching(
achievement: achievement_with_template | null,
user: User,
hasRequest: boolean,
hasSuccessfulScreening: boolean,
ctx: StudentNewMatchGhostContext
): Promise<achievement_with_template[]> {
const result: achievement_with_template[] = [];
Expand Down Expand Up @@ -306,16 +301,5 @@ async function generateStudentMatching(
relation: achievement?.relation ?? randomRelation,
});

result.push({
id: -1,
templateId: -1,
userId: user.userID,
isSeen: true,
template: GhostAchievements.student_new_match_2,
context: ctx,
recordValue: null,
achievedAt: hasSuccessfulScreening || achievement ? new Date() : null,
relation: achievement?.relation ?? randomRelation,
});
return result;
}
15 changes: 15 additions & 0 deletions common/achievement/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const batchOfMetrics = [
createMetric('student_onboarding_screened', ['student_screening_appointment_done', 'tutor_screening_success', 'instructor_screening_success'], () => {
return 1;
}),
createMetric('student_onboarding_tutor_screened', ['tutor_screening_success'], () => {
return 1;
}),
createMetric('student_onboarding_coc_success', ['student_coc_updated'], () => {
return 1;
}),
Expand All @@ -49,6 +52,9 @@ const batchOfMetrics = [
),

/* CONDUCTED MATCH APPOINTMENT */
createMetric('student_add_match_appointment', ['student_add_appointment_match_with_pupil'], () => {
return 1;
}),
createMetric('student_conducted_match_appointment', ['student_joined_match_meeting'], () => {
return 1;
}),
Expand Down Expand Up @@ -106,9 +112,18 @@ const batchOfMetrics = [
}),

/* Matching */
createMetric('pupil_create_new_match_chat', ['pupil_create_new_match_chat'], () => {
return 1;
}),
createMetric('student_create_new_match_chat', ['student_create_new_match_chat'], () => {
return 1;
}),
createMetric('pupil_match_create', ['tutee_matching_success'], () => {
return 1;
}),
createMetric('student_match_requested', ['tutor_match_requested'], () => {
return 1;
}),
createMetric('student_match_create', ['tutor_matching_success'], () => {
return 1;
}),
Expand Down
8 changes: 8 additions & 0 deletions common/appointment/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getMatch, getPupil, getStudent } from '../../graphql/util';
import { PrerequisiteError, RedundantError } from '../../common/util/error';
import { getContextForGroupAppointmentReminder, getContextForMatchAppointmentReminder } from './util';
import { getNotificationContextForSubcourse } from '../../common/courses/notifications';
import { createRelation, EventRelationType } from '../achievement/relation';

const logger = getLogger();

Expand Down Expand Up @@ -96,6 +97,7 @@ export const createMatchAppointments = async (matchId: number, appointmentsToBeC

if (!silent) {
await Notification.actionTaken(userForPupil(pupil), 'student_add_appointment_match', {
relation: createRelation(EventRelationType.Match, matchId),
student,
matchId: matchId.toString(),
});
Expand All @@ -110,6 +112,12 @@ export const createMatchAppointments = async (matchId: number, appointmentsToBeC
...(await getContextForMatchAppointmentReminder(appointment)),
pupil,
});
await Notification.actionTaken(userForStudent(student), 'student_add_appointment_match_with_pupil', {
relation: createRelation(EventRelationType.Match, matchId),
pupil,
match: { id: matchId.toString() },
lecture: appointment,
});
}
}

Expand Down
18 changes: 18 additions & 0 deletions common/chat/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import systemMessages from './localization';
import { getLogger } from '../logger/logger';
import assert from 'assert';
import { createHmac } from 'crypto';
import { actionTaken } from '../notification';
import { createRelation, EventRelationType } from '../achievement/relation';

const logger = getLogger('Chat');
const getOrCreateOneOnOneConversation = async (
Expand Down Expand Up @@ -201,6 +203,22 @@ async function createContactChat(meUser: User, contactUser: User): Promise<strin
},
};

if (contact.match) {
if (meUser.studentId) {
await actionTaken(meUser, 'student_create_new_match_chat', {
user: meUser,
match: { id: `${contact.match.matchId}` },
relation: createRelation(EventRelationType.Match, contact.match.matchId),
});
} else {
await actionTaken(meUser, 'pupil_create_new_match_chat', {
user: meUser,
match: { id: `${contact.match.matchId}` },
relation: createRelation(EventRelationType.Match, contact.match.matchId),
});
}
}

const conversation = await getOrCreateOneOnOneConversation([meUser, contactUser], conversationInfos, ContactReason.CONTACT);
logger.info(`Contact conversation was created by ${meUser} with ${contactUser} with ID ${conversation.id} `);
return conversation.id;
Expand Down
24 changes: 23 additions & 1 deletion common/notification/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,20 @@ const _notificationActions = {
},
},
student_add_appointment_match: {
description: 'Tutee / Tutor added Match Appointment',
description: 'Tutee / Tutor added Match Appointment (Pupil event)',
sampleContext: {
student: sampleUser,
matchId: '1',
},
},
student_add_appointment_match_with_pupil: {
description: 'Tutee / Tutor added Match Appointment (Tutee / Tutor event)',
sampleContext: {
pupil: sampleUser,
match: { id: '1' },
lecture: {},
},
},
pupil_decline_appointment_group: {
description: 'Instructor / Group Appointment declined by Participant',
sampleContext: {
Expand Down Expand Up @@ -602,6 +610,20 @@ const _notificationActions = {
appointment: sampleAppointment,
},
},
pupil_create_new_match_chat: {
description: 'User has clicked on new chat with a match partner',
sampleContext: {
user: sampleUser,
match: { id: '1' },
},
},
student_create_new_match_chat: {
description: 'User has clicked on new chat with a match partner',
sampleContext: {
user: sampleUser,
match: { id: '1' },
},
},
missed_one_on_one_chat_message: {
description: 'Missed message in 1:1 chat',
sampleContext: sampleMissedOneOnOneMessage,
Expand Down
2 changes: 1 addition & 1 deletion common/student/screening.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ export async function addTutorScreening(
},
});

const asUser = userForStudent(student);
if (!batchMode) {
if (screening.success) {
const asUser = userForStudent(student);
await updateSessionRolesOfUser(asUser.userID);
await scheduleCoCReminders(student);
await Notification.actionTaken(userForStudent(student), 'tutor_screening_success', {});
Expand Down
Loading

0 comments on commit f1252a5

Please sign in to comment.