|
| 1 | +import { |
| 2 | + InvalidIndexNameError, |
| 3 | + MultipleTextIDsWithoutSpecifiedTextIDError |
| 4 | +} from '../util/errors'; |
| 5 | +import type { |
| 6 | + ImportAnnotation |
| 7 | +} from '@/types/import-annotation'; |
| 8 | + |
| 9 | +export const parseAlgorithmAnnotationsCSV = ( |
| 10 | + text: string, |
| 11 | + title: string, |
| 12 | + textId?: string, |
| 13 | + textName: string = 'text', |
| 14 | + algorithm_id: string = 'algorithm_id', |
| 15 | + fixationName: string = 'fix_uid', |
| 16 | + boxName: string = 'char_uid', |
| 17 | + dGeomName: string = 'D_geom', |
| 18 | + pShareName: string = 'P_share' |
| 19 | +): ImportAnnotation => { |
| 20 | + const lines = text.split( /\r?\n/ ).filter( l => l.trim() !== '' ); |
| 21 | + const header = lines.shift()!.split( ',' ) |
| 22 | + .map( h => h.trim() ); |
| 23 | + const algorithmName = header.indexOf( algorithm_id ); |
| 24 | + const textIndex = header.indexOf( textName ); |
| 25 | + const fixIndex = header.indexOf( fixationName ); |
| 26 | + const boxIndex = header.indexOf( boxName ); |
| 27 | + const dGeomIndex = header.indexOf( dGeomName ); |
| 28 | + const pShareIndex = header.indexOf( pShareName ); |
| 29 | + |
| 30 | + if ( fixIndex < 0 ) |
| 31 | + throw new InvalidIndexNameError( 'X coordinate' ); |
| 32 | + else if ( boxIndex < 0 ) |
| 33 | + throw new InvalidIndexNameError( 'Y coordinate' ); |
| 34 | + else if ( algorithmName < 0 ) |
| 35 | + throw new InvalidIndexNameError( 'algorithm ID' ); |
| 36 | + else if ( textIndex < 0 ) |
| 37 | + throw new InvalidIndexNameError( 'text ID' ); |
| 38 | + |
| 39 | + const firstCols = lines[0]!.split( ',' ); |
| 40 | + const firstEncounteredTextID = firstCols[ textIndex ]; |
| 41 | + // First index is text, second id is reader |
| 42 | + const annotations: ImportAnnotation = {}; |
| 43 | + |
| 44 | + for ( let i = 0; i < lines.length; i++ ) { |
| 45 | + const cols = lines[i]!.split( ',' ); |
| 46 | + |
| 47 | + if ( firstEncounteredTextID !== cols[ textIndex ] && !textId ) { |
| 48 | + throw new MultipleTextIDsWithoutSpecifiedTextIDError(); |
| 49 | + } |
| 50 | + |
| 51 | + if ( textId === undefined ) { |
| 52 | + const algorithm = cols[ algorithmName ]!; |
| 53 | + |
| 54 | + if ( !annotations[ algorithm ] ) { |
| 55 | + annotations[ algorithm ] = { |
| 56 | + 'title': title, |
| 57 | + 'annotations': [] |
| 58 | + }; |
| 59 | + } |
| 60 | + |
| 61 | + const preAnnotation = { |
| 62 | + 'foreignFixationId': parseInt( cols[ fixIndex ]! ), |
| 63 | + 'foreignCharacterBoxId': parseInt( cols[ boxIndex ]! ), |
| 64 | + ...(dGeomIndex >= 0 && cols[ dGeomIndex ] && { 'dGeom': parseFloat( cols[ dGeomIndex ] ) }), |
| 65 | + ...(pShareIndex >= 0 && cols[ pShareIndex ] && { 'pShare': parseFloat( cols[ pShareIndex ] ) }) |
| 66 | + }; |
| 67 | + (annotations[ algorithm ]!.annotations as any).push( preAnnotation ); |
| 68 | + } else if ( cols[ textIndex ] === textId ) { |
| 69 | + const algorithm = cols[ algorithmName ]!; |
| 70 | + |
| 71 | + if ( !annotations[ algorithm ] ) { |
| 72 | + annotations[ algorithm ] = { |
| 73 | + 'title': title, |
| 74 | + 'annotations': [] |
| 75 | + }; |
| 76 | + } |
| 77 | + |
| 78 | + const preAnnotation = { |
| 79 | + 'foreignFixationId': parseInt( cols[ fixIndex ]! ), |
| 80 | + 'foreignCharacterBoxId': parseInt( cols[ boxIndex ]! ), |
| 81 | + ...(dGeomIndex >= 0 && cols[ dGeomIndex ] && { 'dGeom': parseFloat( cols[ dGeomIndex ] ) }), |
| 82 | + ...(pShareIndex >= 0 && cols[ pShareIndex ] && { 'pShare': parseFloat( cols[ pShareIndex ] ) }) |
| 83 | + }; |
| 84 | + (annotations[ algorithm ]!.annotations as any).push( preAnnotation ); |
| 85 | + } |
| 86 | + } |
| 87 | + |
| 88 | + return annotations; |
| 89 | +}; |
0 commit comments