2626 <template #prepend >
2727 <q-icon name =" data_object" />
2828 </template >
29+ <template #option =" scope " >
30+ <q-item v-bind =" scope.itemProps" >
31+ <q-item-section >
32+ <q-item-label class =" flex" >
33+ {{ scope.opt.label }}
34+ <q-space />
35+ {{
36+ scope.opt.amount > 0 ? `(${scope.opt.amount})` : '(0)'
37+ }}
38+ </q-item-label >
39+ </q-item-section >
40+ </q-item >
41+ </template >
42+ <template #selected-item =" scope " >
43+ <q-item-section >
44+ <q-item-label >
45+ {{ scope.opt.label }}
46+ {{
47+ scope.opt.amount > 0 ? `(${scope.opt.amount})` : '(0)'
48+ }}
49+ </q-item-label >
50+ </q-item-section >
51+ </template >
2952 </q-select >
3053
3154 <q-input
4164 'font-family': 'monospace',
4265 }"
4366 :hint =" currentParser.value.hint"
44- @paste =" onPaste"
67+ @paste =" detectParser"
68+ @blur =" detectParser"
69+ @focus =" detectParser"
70+ @update:model-value =" detectParser"
4571 />
4672 </div >
4773 </q-tab-panel >
@@ -95,6 +121,7 @@ import { Ctf, makeId } from 'src/ctfnote/models';
95121import parsers , { ParsedTask } from ' src/ctfnote/parsers' ;
96122import { defineComponent , ref } from ' vue' ;
97123import TaskTagsList from ' src/components/Task/TaskTagsList.vue' ;
124+ import RawParser from ' src/ctfnote/parsers/raw' ;
98125
99126export default defineComponent ({
100127 components: {
@@ -107,7 +134,11 @@ export default defineComponent({
107134 setup() {
108135 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
109136 useDialogPluginComponent ();
110- const parserOptions = parsers .map ((p ) => ({ label: p .name , value: p }));
137+ const parserOptions = parsers .map ((p ) => ({
138+ label: p .name ,
139+ value: p ,
140+ amount: 0 ,
141+ }));
111142
112143 const columns = [
113144 { name: ' keep' , label: ' ' , field: ' keep' },
@@ -165,14 +196,53 @@ export default defineComponent({
165196 }
166197 },
167198 autoDetectParser() {
168- for (const parser of parsers ) {
169- if (parser .isValid (this .model )) {
170- const p = this .parserOptions .find ((opt ) => opt .value == parser );
171- if (p ) this .currentParser = p ;
199+ const outputOfParser = parsers .map ((p ) => {
200+ let challenges: ParsedTask [] = [];
201+ try {
202+ challenges = p .parse (this .model );
203+ } catch (e ) {}
204+
205+ return {
206+ parser: p ,
207+ challenges: challenges ,
208+ };
209+ });
210+
211+ // assign the amount of challenges to the parser options
212+ this .parserOptions .forEach ((opt ) => {
213+ const parser = outputOfParser .find (
214+ (p ) => p .parser .name === opt .value .name
215+ );
216+ if (parser ) {
217+ opt .amount = parser .challenges .length ;
172218 }
219+ });
220+
221+ // find the parser with the most tasks, but exclude the raw parser
222+ // since it will count the amount of newlines which does not always make sense
223+ const max = outputOfParser
224+ .filter ((p ) => p .parser .name !== RawParser .name )
225+ .reduce (
226+ (acc , cur ) =>
227+ cur .challenges .length > acc ? cur .challenges .length : acc ,
228+ 0
229+ );
230+ const bestParser = outputOfParser .find ((p ) => p .challenges .length == max );
231+ if (
232+ bestParser &&
233+ bestParser .challenges .length > 0 &&
234+ (bestParser .challenges .length > this .currentParser .amount ||
235+ this .currentParser .label == RawParser .name ) // it must be an improvement, except overriding the raw parser is allowed
236+ ) {
237+ const p = this .parserOptions .find (
238+ (opt ) => opt .value == bestParser .parser
239+ );
240+ if (p ) this .currentParser = p ;
241+ } else if (this .currentParser .amount == 0 ) {
242+ this .currentParser = this .parserOptions [0 ];
173243 }
174244 },
175- onPaste () {
245+ detectParser () {
176246 void this .$nextTick (() => this .autoDetectParser ());
177247 },
178248 normalizeTags(tags : string []): string [] {
0 commit comments