@@ -25,6 +25,22 @@ function ensureInt(obj: any, argName: string): number {
2525 throw new Error ( `'${ argName } ' spec key is not a safe integer.` ) ;
2626 return obj ;
2727}
28+ function ensureUniqueStrArray ( obj : any , argName : string ) : string [ ] {
29+ if ( ! Array . isArray ( obj ) ) {
30+ throw new Error ( `'${ argName } ' spec key is not an array of strings.` ) ;
31+ }
32+ const newArr : string [ ] = [ ] ;
33+ for ( const e of obj ) {
34+ if ( typeof e !== "string" ) {
35+ throw new Error ( `'${ argName } ' spec key must be an array of strings.` ) ;
36+ }
37+ newArr . push ( e ) ;
38+ }
39+ if ( ( new Set ( newArr ) ) . size !== newArr . length ) {
40+ throw new Error ( `'${ argName } ' spec key must contain unique strings.` ) ;
41+ }
42+ return newArr ;
43+ }
2844//function ensureNum(obj: any, argName: string): number {
2945// if (typeof obj === "number") return obj;
3046// throw new Error(`'${argName}' spec key is not a number.`);
@@ -60,12 +76,30 @@ function inputIntegerTransform(obj: any): InputIntegerPartialSpec {
6076 } ;
6177}
6278
63- /********************************************************************/
79+ function fieldLabelsToIndices (
80+ arr : string [ ] ,
81+ reference : string [ ] ,
82+ argName : string ,
83+ refName : string ,
84+ ) : number [ ] {
85+ const indices : number [ ] = arr . map ( x => reference . indexOf ( x ) ) ;
86+ if ( indices . some ( x => ( x < 0 ) ) ) {
87+ throw new Error ( `'${ argName } ' spec key must contain strings found in ${ refName } .` ) ;
88+ }
6489
65- interface OutputFieldSpec {
66- label : string ;
90+ // Sanity checks
91+ if ( ( new Set ( indices ) ) . size !== indices . length ) {
92+ throw new Error ( `Critical bug: arr must map to unique indices.` ) ;
93+ }
94+ if ( indices . some ( x => x >= reference . length ) ) {
95+ throw new Error ( `Critical bug: arr must map to indices within range.` ) ;
96+ }
97+
98+ return indices ;
6799}
68100
101+ /********************************************************************/
102+
69103interface InputPartialSpec {
70104 title : string ;
71105 parameters : number ;
@@ -78,11 +112,27 @@ interface InputIntegerPartialSpec {
78112 initial : number ;
79113}
80114
115+ /*** ***/
116+
117+ //type OutputFieldSortBy = "ascending" | "descending";
118+
119+ interface OutputFieldSpec {
120+ label : string ;
121+
122+ //sortBy: OutputFieldSortBy; // We are always ascending for now
123+ }
124+
81125interface OutputPartialSpec {
82126 title : string ;
83127 fields : OutputFieldSpec [ ] ;
128+
129+ // Formatting
130+ groupPriority : number [ ] ; // closer to front = higher-priority
131+ sortPriority : number [ ] ; // closer to front = higher-priority
84132}
85133
134+ /*** ***/
135+
86136export interface SpecValues {
87137 name : string ;
88138 appTitle : string ;
@@ -157,17 +207,39 @@ export function getSpecValues(specPath: string): SpecValues {
157207
158208 output : objectValueMap ( output , ( obj : any ) => {
159209 const title : string = ensureStr ( obj . title , "output[].title" ) ;
160- const fieldLabels : any = obj . fieldLabels ;
161- if ( ! Array . isArray ( fieldLabels ) ) {
162- throw new Error ( `Output ${ obj . title } must provide a fields specification array.` ) ;
163- }
210+ const fieldLabels : string [ ] = ensureUniqueStrArray (
211+ obj . fieldLabels , "output[].fieldLabels" ,
212+ ) ;
213+ const groupBy : string [ ] = ensureUniqueStrArray (
214+ obj . format ?. groupBy , "output[].format.groupBy" ,
215+ ) ;
216+ const sortBy : string [ ] = ensureUniqueStrArray (
217+ obj . format ?. sortBy , "output[].format.sortBy" ,
218+ ) ;
219+
220+ const fields : OutputFieldSpec [ ] = fieldLabels . map ( x => ( { label : x } ) ) ;
164221
165- const fields : OutputFieldSpec [ ] = fieldLabels . map (
166- x => ( { label : ensureStr ( x , `output[].fields[].label` ) } )
222+ const groupPriority : number [ ] = fieldLabelsToIndices (
223+ groupBy ,
224+ fieldLabels ,
225+ "output[].format.groupBy" ,
226+ "output[].fieldLabels" ,
167227 ) ;
228+ const sortPriority : number [ ] = fieldLabelsToIndices (
229+ sortBy ,
230+ fieldLabels ,
231+ "output[].format.sortBy" ,
232+ "output[].fieldLabels" ,
233+ ) ;
234+
235+ // We want to sort all fields, so we fill more values
236+ for ( let i = 0 ; i < fieldLabels . length ; ++ i ) {
237+ if ( ! sortPriority . includes ( i ) ) sortPriority . push ( i ) ;
238+ }
239+ console . log ( groupPriority ) ;
240+ console . log ( sortPriority ) ;
168241
169- const outputObj = { title, fields} ;
170- return outputObj ;
242+ return { title, fields, groupPriority, sortPriority} ;
171243 } ) ,
172244 } ;
173245}
0 commit comments