Subversion Repositories svn1

Rev

Rev 133 | Rev 195 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
91 - 1
/*************************************************************************
2
*           Copyright (C) 1995 Embedded Solutions
3
*                       All rights reserved
4
*
5
* file:     src\legtime.c
6
*
7
* purpose:  Leg time calculations
8
*
9
* functions
10
*   set_legs                    - Menu: Setup leg times
11
*   tm_lgs                      - Set up the leg start times for leg
12
*   leg_start                   - Set up the leg start times
13
*   tm_fixedstart               - Set the start time for a specific leg
14
*   tm_staggered                - Set a staggered start time for a specific leg
15
*   tm_clearleg                 - Clear start times on a specific leg
16
*   leg_ini                     - Initialize all stored times
17
*   tm_init                     - Initialize all team data
18
*   tm_gen                      - Generate dummy team names
19
*   legs_start_report           - Generate starters report
20
*   ls_timer                    - print the current leg entry
21
*   ls_team                     - print next ( numeric ) leg entry
22
*   sort_legs                   - Qsort callback function
23
*
24
* programmer: David Purdie
25
*
26
* revision  date        by      reason
27
*           11-Oct-89   DDP     leg-3 starttime. Now has an option to generate
28
*                               a printed report of teams and times
29
*
30
*           21-May-90   MV      now able to set start time and generate
31
*                               a printed report for any leg
32
*   00.0    27/01/95    DDP     Tidies up the program and formatted the file
33
*
34
**************************************************************************/
133 david 35
#include    "QDebug"
91 - 36
#include    "consts.h"
37
#include    "structs.h"
38
#include    "proto.h"
39
 
40
/*========================================================================
41
 *
42
 *  Set up the leg start times for leg
43
 *
44
 *  Purpose:
45
 *      This function is called to Set up the leg start times for leg
46
 *      The start time is based on category information
47
 *
48
 *  Parameters:
49
 *      None
50
 *
51
 *  Returns:
52
 *      Nothing
53
 *
54
 *========================================================================*/
55
 
131 david 56
void tm_lgs1(int leg, time_t starttime, time_t delta, bool report_it, bool clear_it)
91 - 57
{
58
    t_legs     *data;                            /* Address of table */
59
    t_legs     *dptr;                            /* Moving pointer */
60
    int         num_records;                     /* Number of records in array */
61
    int         i;
170 - 62
    team_type   team_buf;
91 - 63
 
64
 
65
    /*
66
    **  Read existing data into memory
67
    */
68
    data = ( t_legs * ) calloc( ( unsigned ) ( config.max_team - config.min_team + 2 ), sizeof( t_legs ) ); /* Fetch memory */
69
    if( !data )
70
    {
133 david 71
        qDebug( "No memory for report" );
91 - 72
        return;
73
    }
74
 
75
    /*
76
     * Extract the required data from the data base
77
     * Only save that information required for the operation
78
     *      - The end time of the previous leg
79
     */
80
    dptr = data;
81
    num_records = 0;
82
    for( i = config.min_team; i <= config.max_team; i++ )
83
    {
84
        if( valid_field( i ) && g_record( i, &team_buf ) )
85
        {
86
            dptr->numb = team_buf.numb;
87
            dptr->start = team_buf.leg[leg-1].end;
88
            dptr->flags = team_buf.flags;
89
            dptr++;
90
            num_records++;
91
        }
92
    }
93
 
94
    /*
95
     * Sort the data into some logical order 
96
     */
97
    qsort( ( char * ) data, num_records, sizeof( t_legs ), sort_legs );
98
 
99
    /*
100
    **  Update the team information based on the start order
101
    **  Ignore validity flags as the data will have been sorted with
102
    **  these in mind.
103
    */
104
    for( dptr = data, i = 0; i < num_records; i++, dptr++ )
105
    {
106
        if( valid_field( dptr->numb ) )
107
        {
108
            g_record( dptr->numb, &team_buf );
109
            team_buf.leg[leg].start = starttime;
110
            starttime += delta;
111
            team_buf.leg[leg].manual = TRUE;
112
 
113
            set_times( &team_buf );
114
            test_times( &team_buf, 0 );
115
            put_team_record( dptr->numb, &team_buf );
116
        }
117
    }
118
 
119
    /*
120
    **  Release the data
121
    */
122
    free( data );
123
 
124
    if( report_it )
133 david 125
        legs_start_report(leg);
91 - 126
 
127
    if ( clear_it )
133 david 128
        tm_clearleg_specified( leg, TRUE);
91 - 129
}
130
 
131
/*========================================================================
132
 *
133
 *  Set up the leg start times for leg
134
 *
135
 *  Purpose:
136
 *      This function is called to Set up the leg start times for leg
137
 *      The start time is based on current placing with:
138
 *          A constant offset added ( ie: lunch)
139
 *          A fixed increment
140
 *
141
 *  Parameters:
142
 *      None
143
 *
144
 *  Returns:
145
 *      Nothing
146
 *
147
 *========================================================================*/
148
 
130 - 149
void tm_lgs(int leg, time_t delta, bool report_it, bool clear_it)
91 - 150
{
170 - 151
    team_type   team_buf;
152
    int team = config.min_team;                      /* Team we are working with */
91 - 153
    while( team <= config.max_team )
154
    {
155
        if( valid_field( team ) )
156
        {
157
            g_record( team, &team_buf );
158
            if( team_buf.flags.valid && team_buf.leg[leg - 1].end > 0 )
159
            {
160
                team_buf.leg[leg].start = team_buf.leg[leg - 1].end + delta;
161
                team_buf.leg[leg].manual = TRUE;
162
            }
163
            else
164
                team_buf.leg[leg].start = ( time_t ) - 1;
165
 
166
            set_times( &team_buf );
167
            test_times( &team_buf, 0 );
168
            put_team_record( team, &team_buf );
169
        }
170
        team++;
171
    }
172
 
173
    if( report_it )
133 david 174
        legs_start_report(leg);
91 - 175
 
176
    if ( clear_it )
133 david 177
        tm_clearleg_specified( leg, TRUE);
91 - 178
}
179
 
180
/*========================================================================
181
 *
182
 *  Set up the leg start times
183
 *
184
 *  Purpose:
185
 *      This function is called to Set up the leg start times
186
 *
187
 *  Parameters:
188
 *      None
189
 *
190
 *  Returns:
191
 *      Nothing
192
 *
193
 *========================================================================*/
194
 
195
void leg_start(void)
196
{
170 - 197
    team_type   team_buf;
198
    int team = config.min_team;                      /* Team we are working with */
91 - 199
    while( team <= config.max_team )
200
    {
201
        if( valid_field( team ) )
202
        {
203
            ( void ) g_record( team, &team_buf );
204
            if( team_buf.teamclass > 0 && team_buf.teamclass <= config.num_class )
205
                team_buf.leg[0].start =
206
                    config.team_class[team_buf.teamclass - 1].start;
207
            else
208
                team_buf.leg[0].start = ( time_t ) - 1;
209
            team_buf.leg[1].manual = 0;
210
            team_buf.leg[1].start = team_buf.leg[0].start;
211
            team_buf.leg[0].l_place = 0;
212
            team_buf.leg[0].le_place = 0;
213
            team_buf.leg[0].lec_place = 0;
214
            team_buf.leg[0].lc_place = 0;
215
            team_buf.leg[0].manual = FALSE;
216
            set_times( &team_buf );
217
            test_times( &team_buf, 0 );
218
            put_team_record( team, &team_buf );
219
        }
220
        team++;
221
    }
222
}
223
 
224
/*========================================================================
225
 *
226
 *  Set the start time for a specific leg
227
 *
228
 *  Purpose:
229
 *      This function is called to set the start time for a specific
230
 *      leg to a specified and fixed time
231
 *
232
 *  Parameters:
233
 *      None
234
 *
235
 *  Returns:
236
 *      Nothing
237
 *
238
 *========================================================================*/
239
 
131 david 240
void tm_fixedstart(int leg, time_t starttime, bool report_it, bool clear_it)
91 - 241
{
170 - 242
    team_type   team_buf;
243
    int team = config.min_team;                      /* Team we are working with */
91 - 244
    while( team <= config.max_team )
245
    {
246
        if( valid_field( team ) )
247
        {
248
            g_record( team, &team_buf );
249
            if( team_buf.flags.valid )
250
            {
251
                team_buf.leg[leg].start = starttime;
252
                team_buf.leg[leg].manual = TRUE;
253
            }
254
            else
255
                team_buf.leg[leg].start = ( time_t ) - 1;
256
 
257
            set_times( &team_buf );
258
            test_times( &team_buf, 0 );
259
            put_team_record( team, &team_buf );
260
        }
261
        team++;
262
    }
263
 
264
    if( report_it )
133 david 265
        legs_start_report(leg);
91 - 266
 
267
    if ( clear_it )
133 david 268
        tm_clearleg_specified( leg, TRUE );
91 - 269
}
270
 
271
/*========================================================================
272
 *
273
 *  Set a staggered start time for a specific leg
274
 *
275
 *  Purpose:
276
 *      This function is called to set the start time for a specific
277
 *      leg to a specified and a staggered time
278
 *
279
 *  Parameters:
280
 *      None
281
 *
282
 *  Returns:
283
 *      Nothing
284
 *
285
 *========================================================================*/
286
 
131 david 287
void tm_staggered(int leg, time_t starttime, time_t delta, bool report_it, bool clear_it )
91 - 288
{
170 - 289
    team_type   team_buf;
290
    int team = config.min_team;                      /* Team we are working with */
91 - 291
    while( team <= config.max_team )
292
    {
293
        if( valid_field( team ) )
294
        {
295
            g_record( team, &team_buf );
296
            if( team_buf.flags.valid )
297
            {
298
                team_buf.leg[leg].start = starttime;
299
                starttime += delta;
300
                team_buf.leg[leg].manual = TRUE;
301
            }
302
            else
303
                team_buf.leg[leg].start = ( time_t ) - 1;
304
 
305
            set_times( &team_buf );
306
            test_times( &team_buf, 0 );
307
            put_team_record( team, &team_buf );
308
        }
309
        team++;
310
    }
311
 
312
    if( report_it )
133 david 313
        legs_start_report(leg);
91 - 314
 
315
    if ( clear_it )
133 david 316
        tm_clearleg_specified( leg, TRUE );
91 - 317
}
318
 
319
/*========================================================================
320
 *
321
 *  Clear start times on a specific leg
322
 *
323
 *  Purpose:
324
 *      This function is called to clear start times on a specifc leg
325
 *
326
 *  Parameters:
327
 *      cleg                - Leg to clear
328
 *      manual              - Force manual, else leave alone
329
 *
330
 *  Returns:
331
 *      Nothing
332
 *
333
 *========================================================================*/
334
 
170 - 335
void tm_clearleg_specified(int leg, bool manual)
91 - 336
{
170 - 337
    team_type   team_buf;
91 - 338
 
339
    /*
340
    **  Validate the users argument
341
    */
170 - 342
    if( leg == 0 )
91 - 343
        return;                              /* Null leg - just exit */
170 - 344
    if( leg > config.num_legs )             /* Valid leg number - Exit loop */
91 - 345
        return;
346
 
170 - 347
    int team = config.min_team;                 /* Team we are working with */
91 - 348
    while( team <= config.max_team )
349
    {
350
        if( valid_field( team ) )
351
        {
352
            g_record( team, &team_buf );
353
            team_buf.leg[leg].manual = manual;
354
            team_buf.leg[leg].start = ( time_t ) -1;
355
 
356
            set_times( &team_buf );
357
            test_times( &team_buf, 0 );
358
            put_team_record( team, &team_buf );
359
        }
360
        team++;
361
    }
362
}
363
 
364
 
365
/*========================================================================
366
 *
367
 *  Initialize all stored times
368
 *
369
 *  Purpose:
370
 *      This function is called to Initialize all stored times
371
 *
372
 *  Parameters:
373
 *      None
374
 *
375
 *  Returns:
376
 *      Nothing
377
 *
378
 *========================================================================*/
379
 
380
void leg_ini(void)
381
{
382
    int         i;
170 - 383
    team_type   team_buf;
91 - 384
 
385
 
170 - 386
    int team = config.min_team;                      /* Team we are working with */
91 - 387
    while( team <= config.max_team )
388
    {
389
        if( valid_field( team ) )
390
        {
391
            ( void ) g_record( team, &team_buf );
392
            for( i = 0; i <= MAX_LEGS; i++ )
393
            {
394
                team_buf.leg[i].start = team_buf.leg[i].end =
395
                    team_buf.leg[i].elapsed = ( time_t ) - 1;
396
                team_buf.leg[i].l_place = 0;
397
                team_buf.leg[i].le_place = 0;
398
                team_buf.leg[i].lec_place = 0;
399
                team_buf.leg[i].lc_place = 0;
400
                team_buf.leg[i].manual = FALSE;
401
            }
402
            if( team_buf.teamclass > 0 && team_buf.teamclass <= config.num_class )
403
                team_buf.leg[0].start =
404
                    config.team_class[team_buf.teamclass - 1].start;
405
            else
406
                team_buf.leg[0].start = ( time_t ) - 1;
407
 
408
            team_buf.leg[1].start = team_buf.leg[0].start;
409
            team_buf.flags.disqualified = FALSE;
410
            team_buf.flags.non_equestrian = FALSE;
411
            put_team_record( team, &team_buf );
412
        }
413
        team++;
414
    }
415
}
416
 
417
/*========================================================================
418
 *
419
 *  Initialize all team data
420
 *
421
 *  Purpose:
422
 *      This function is called to Initialize all team data
423
 *
424
 *  Parameters:
425
 *      None
426
 *
427
 *  Returns:
428
 *      Nothing
429
 *
430
 *========================================================================*/
431
void tm_init(void)
432
{
170 - 433
    team_type   team_buf;
434
    int team = config.min_team;                      /* Team we are working with */
91 - 435
    while( team <= config.max_team )
436
    {
437
        if( valid_field( team ) )
438
        {
439
            clr_team( team, &team_buf );
440
            put_team_record( team, &team_buf );
441
        }
442
        team++;
443
    }
444
}
445
 
446
/*========================================================================
447
 *
448
 *  Generate dummy team names
449
 *
450
 *  Purpose:
451
 *      This function is called to Generate dummy team names
452
 *
453
 *  Parameters:
454
 *      None
455
 *
456
 *  Returns:
457
 *      Nothing
458
 *
459
 *========================================================================*/
460
 
461
void tm_gen(void)
462
{
170 - 463
    team_type   team_buf;
464
    int team = config.min_team;                      /* Team we are working with */
91 - 465
    while( team <= config.max_team )
466
    {
467
        if( valid_field( team ) )
468
        {
469
            ( void ) g_record( team, &team_buf );
470
            team_buf.flags.valid = TRUE;
471
            sprintf( team_buf.name, "Team - %4.4d", team );
472
            team_buf.teamclass = 1;                  /* Set default class */
473
            put_team_record( team, &team_buf );
474
        }
475
        team++;
476
    }
477
}
478
 
479
 
480
/*========================================================================
481
 *
482
 *  Generate starters report
483
 *
484
 *  Purpose:
485
 *      This routine is used to generate a list of leg start times
486
 *      This system can cope with a break at the start of leg
487
 *
488
 *  Parameters:
489
 *      None
490
 *
491
 *  Returns:
492
 *      Nothing
493
 *
494
 *========================================================================*/
495
 
133 david 496
void legs_start_report(int leg)
91 - 497
{
498
    int         i;
499
    t_legs     *data;                            /* Address of table */
500
    t_legs     *dptr;                            /* Moving pointer */
501
    int         last_team;
502
    int         num_records = 0;                 /* Number of records in array */
503
    char        l_s[40];                         /* Name of start time file */
170 - 504
    team_type   team_buf;
91 - 505
 
506
    printf( "Generating Starters report for Leg-%d", leg );
507
 
508
    data = ( t_legs * ) calloc( ( unsigned ) ( config.max_team - config.min_team + 2 ), sizeof( t_legs ) ); /* Fetch memory */
509
 
510
    if( !data )
511
    {
133 david 512
        qDebug( "No memory for report" );
91 - 513
        return;
514
    }
515
 
516
    /*
517
     * Extract the required data from the data base
518
     * Only save that information required for the operation
519
     */
520
 
521
    dptr = data;
522
    for( i = config.min_team; i <= config.max_team; i++ )   /* Print team order data */
523
    {
524
        if( valid_field( i ) && g_record( i, &team_buf ) )
525
        {
526
            dptr->numb = team_buf.numb;
527
            dptr->start = team_buf.leg[leg].start;
528
            dptr->flags = team_buf.flags;
529
            dptr++;
530
            num_records++;
531
        }
532
    }
533
 
534
 
535
    /*
536
     * Sort the data into some logical order 
537
     */
538
    qsort( ( char * ) data, num_records, sizeof( t_legs ), sort_legs );
539
 
540
    /*
541
    **  Now print the data on the printer
542
    **      - Generte the name of the printer file
543
    **      - Open the printer
544
    */
545
 
546
    sprintf( l_s, "l_%d", leg );
547
    if( !open_printer( "", l_s, 80, text, "Starters Report" ) )
548
        return;
549
 
550
    /*
551
     * Print out the header for the file 
552
     */
553
    print( "\nStarters report for leg:%d %-*s\n", leg, 18, config.leg_name[leg - 1] );
554
    print( "Team order listing\n\n" );
555
 
556
    print_underline (TRUE);
557
    print( "%-8s   %-5s   %-8s   |   %-5s   %-8s", "Time", "Team", "DeltaT", "Team", "Time" );
558
    print_underline (FALSE);
559
    print( "\n" );
560
 
561
    last_team = 0;
562
    for( dptr = data, i = 0; i < num_records; i++ )
563
    {
564
        ls_timer( dptr++, i );
565
        print( "   |   " );
566
        ls_team( &last_team, data );
567
        print( "\n" );
568
    }
569
 
570
    print( "\nTeams without marked times will be started when ALL marked teams\n" );
571
    print( "have been started.\n" );
572
 
573
    /*
574
    **  Release the resources
575
    **      - Printer
576
    **      - Memory
577
    */
578
    close_printer();
579
    free( data );
580
}
581
 
582
/*========================================================================
583
 *
584
 *  print the current leg entry
585
 *
586
 *  Purpose:
587
 *      This function is a helper routine to print the current leg entry
588
 *      in time : Team number order
589
 *
590
 *  Parameters:
591
 *      ptr     Pointer to entry
592
 *      num     Entry index
593
 *
594
 *  Returns:
595
 *      Nothing
596
 *
597
 *========================================================================*/
598
 
599
void ls_timer( t_legs * ptr, int num )
600
{
601
    time_t      time;
602
    time_t      delta;
603
 
604
    if( num == 0 )
605
        delta = ( time_t ) - 1;
606
    else
607
        delta = ptr[0].start - ptr[-1].start;
608
 
609
    time = ptr->start;
610
    if( ptr->flags.disqualified )
611
        time = ( time_t ) - 1;
612
 
613
    print( "%-8s   %-5d", time_fa( time, ptr->flags.disqualified ),
614
           ptr->numb );
615
    print( "   %-8s", time_fa( delta, TRUE ) );
616
}
617
 
618
 
619
/*========================================================================
620
 *
621
 *  print next ( numeric ) leg entry
622
 *
623
 *  Purpose:
624
 *      This helper function is called to print next ( numeric ) leg entry
625
 *      in Team # time order
626
 *
627
 *  Parameters:
628
 *      last        Last one found
629
 *                  Used to relocate my self
630
 *      data        Start of data
631
 *
632
 *  Returns:
633
 *      Nothing
634
 *
635
 *========================================================================*/
636
 
637
void ls_team( int *last, t_legs * data )
638
{
639
    t_legs     *min;
640
    time_t      time;
641
 
642
    for( min = 0; data->numb; data++ )
643
    {
644
        if( data->numb > *last && ( min == 0 || data->numb < min->numb ) )
645
            min = data;
646
    }
647
    *last = min->numb;                           /* Save current team as done */
648
 
649
    time = min->start;
650
    if( min->flags.disqualified )
651
        time = ( time_t ) - 1;
652
    print( "%-5d   %-8s", min->numb,
653
           time_fa( time, min->flags.disqualified ) );
654
}
655
 
656
/*========================================================================
657
 *
658
 *  Qsort callback function
659
 *
660
 *  Purpose:
661
 *      This function is provided to Qsort() to sort the teams
662
 *
663
 *  Parameters:
664
 *      a           - Leg entry to compare
665
 *      b           - Leg entry to compare
666
 *
667
 *
668
 *  Returns:
669
 *      -1      a < b
670
 *       0      a = b
671
 *       1      a > b
672
 *
673
 *========================================================================*/
674
 
675
int sort_legs( const void * aa, const void * bb )
676
{
677
 
678
    const t_legs * a = (const t_legs *)aa;
679
    const t_legs * b = (const t_legs *)bb;
680
 
681
    int         a_bad;
682
    int         b_bad;
683
 
684
    a_bad = a->flags.disqualified || a->start <= 0;
685
    b_bad = b->flags.disqualified || b->start <= 0;
686
 
687
    if( a_bad || b_bad )                         /* Valid data has precedence */
688
    {
689
        if( a_bad && b_bad )
690
            return ( a->numb - b->numb );
691
        else
692
            return ( a_bad ? 1 : -1 );
693
    }
694
 
695
    if( a->start == b->start )
696
        return ( a->numb - b->numb );
697
    else
698
    {
699
        if( ( a->start > 0 ) && ( b->start > 0 ) )
700
            return ( ( int ) ( a->start - b->start ) );
701
        else
702
            return ( ( a->start > 0 ) ? -1 : 1 );
703
    }
704
}
705
 
706
/********************************* EOF ***********************************/