11import * as O from 'fp-ts/Option' ;
22import * as TE from 'fp-ts/TaskEither' ;
33import * as RA from 'fp-ts/ReadonlyArray' ;
4+ import * as RR from 'fp-ts/ReadonlyRecord' ;
45
56import { Dependencies } from '../../dependencies' ;
67import { SheetDataTable } from '../../sync-worker/google/sheet-data-table' ;
78import { pipe } from 'fp-ts/lib/function' ;
89import { Equipment , MemberCoreInfo } from '../shared-state/return-types' ;
910import { DateTime , Duration } from 'luxon' ;
11+ import { ReadonlyRecord } from 'fp-ts/lib/ReadonlyRecord' ;
12+ import { EquipmentId } from '../../types/equipment-id' ;
1013
1114export type EquipmentQuizResults = {
1215 passedQuizes : SheetDataTable [ 'rows' ] ;
@@ -27,20 +30,23 @@ export type MemberAwaitingTraining = Pick<
2730 waitingSince : Date ;
2831} ;
2932
33+ const isPassed = ( row : SheetDataTable [ 'rows' ] [ 0 ] ) => row . percentage >= 100 ;
34+ const isFailed = ( row : SheetDataTable [ 'rows' ] [ 0 ] ) => ! isPassed ( row ) ;
35+
3036const extractPassedQuizes = (
3137 sheetData : SheetDataTable [ 'rows' ]
3238) : SheetDataTable [ 'rows' ] =>
3339 pipe (
3440 sheetData ,
35- RA . filter ( row => row . percentage === 100 )
41+ RA . filter ( isPassed )
3642 ) ;
3743
3844const extractFailedQuizes = (
3945 sheetData : SheetDataTable [ 'rows' ]
4046) : SheetDataTable [ 'rows' ] =>
4147 pipe (
4248 sheetData ,
43- RA . filter ( row => row . percentage < 100 )
49+ RA . filter ( isFailed )
4450 ) ;
4551
4652const getQuizResults = (
@@ -70,18 +76,18 @@ const getQuizResults = (
7076 ) ;
7177} ;
7278
73- export type FullQuizResults = {
79+ export type FullQuizResultsForEquipment = {
7480 lastQuizSync : O . Option < Date > ;
7581 membersAwaitingTraining : ReadonlyArray < MemberAwaitingTraining > ;
7682 unknownMembersAwaitingTraining : ReadonlyArray < OrphanedPassedQuiz > ;
7783 failedQuizes : SheetDataTable [ 'rows' ] ;
7884} ;
7985
80- export const getFullQuizResults = (
86+ export const getFullQuizResultsForEquipment = (
8187 deps : Pick < Dependencies , 'sharedReadModel' | 'lastQuizSync' | 'getSheetData' > ,
8288 sheetId : string ,
8389 equipment : Equipment
84- ) : TE . TaskEither < string , FullQuizResults > =>
90+ ) : TE . TaskEither < string , FullQuizResultsForEquipment > =>
8591 pipe (
8692 getQuizResults ( deps , sheetId , equipment . trainedMembers ) ,
8793 TE . map ( qr => {
@@ -124,3 +130,71 @@ export const getFullQuizResults = (
124130 } ;
125131 } )
126132 ) ;
133+
134+ export type FullQuizResultsForMember = {
135+ equipmentQuizPassedAt : ReadonlyRecord < EquipmentId , ReadonlyArray < Date > > ,
136+ equipmentQuizAttempted : ReadonlyRecord < EquipmentId , ReadonlyArray < {
137+ response_submitted : Date ,
138+ sheet_id : string ;
139+ score : number ;
140+ max_score : number ;
141+ percentage : number ;
142+ } > > ,
143+ orphanedQuizAttempts : ReadonlyArray < {
144+ response_submitted : Date ,
145+ sheet_id : string ;
146+ score : number ;
147+ max_score : number ;
148+ percentage : number ;
149+ } > ,
150+ } ;
151+
152+ export const getFullQuizResultsForMember = (
153+ deps : Pick < Dependencies , 'sharedReadModel' | 'getSheetDataByMemberNumber' > ,
154+ memberNumber : number
155+ ) : TE . TaskEither < string , FullQuizResultsForMember > => pipe (
156+ deps . getSheetDataByMemberNumber ( memberNumber ) ,
157+ TE . map (
158+ qr => {
159+ const equipmentQuizPassedAt : Record < EquipmentId , Date [ ] > = { } ;
160+ const equipmentQuizAttempted : Record < EquipmentId , {
161+ response_submitted : Date ,
162+ sheet_id : string ;
163+ score : number ;
164+ max_score : number ;
165+ percentage : number ;
166+ } [ ] > = { } ;
167+ const orphanedQuizAttempts : {
168+ response_submitted : Date ,
169+ sheet_id : string ;
170+ score : number ;
171+ max_score : number ;
172+ percentage : number ;
173+ } [ ] = [ ] ;
174+ const trainingSheetMapping = deps . sharedReadModel . equipment . getTrainingSheetIdMapping ( ) ;
175+ for ( const row of qr ) {
176+ const equipmentId = RR . lookup ( row . sheet_id ) ( trainingSheetMapping ) ;
177+ if ( O . isNone ( equipmentId ) ) {
178+ orphanedQuizAttempts . push ( row ) ;
179+ } else {
180+ if ( isPassed ( row ) ) {
181+ if ( ! equipmentQuizPassedAt [ equipmentId . value ] ) {
182+ equipmentQuizPassedAt [ equipmentId . value ] = [ ] ;
183+ }
184+ equipmentQuizPassedAt [ equipmentId . value ] . push ( row . response_submitted ) ;
185+ } else {
186+ if ( ! equipmentQuizAttempted [ equipmentId . value ] ) {
187+ equipmentQuizAttempted [ equipmentId . value ] = [ ] ;
188+ }
189+ equipmentQuizAttempted [ equipmentId . value ] . push ( row ) ;
190+ }
191+ }
192+ }
193+ return {
194+ equipmentQuizPassedAt,
195+ equipmentQuizAttempted,
196+ orphanedQuizAttempts,
197+ }
198+ }
199+ )
200+ ) ;
0 commit comments