Ticket #2352: libdispatch.diff

File libdispatch.diff, 19.1 KB (added by mortennorby, 13 years ago)
  • PiecesView.h

     
    2929@interface PiecesView : NSImageView
    3030{
    3131    int8_t  * fPieces;
     32       
     33        float   * fPrevPiecesPercent;
    3234   
    3335    NSImage * fBack;
    34     NSColor * fGreenAvailabilityColor, * fBluePieceColor;
     36    NSColor * fGreenAvailabilityColor, * fBluePieceColor, * fPercentProgressColor0, * fPercentProgressColor1;
    3537   
    3638    Torrent * fTorrent;
    3739    NSInteger fNumPieces, fAcross, fWidth, fExtraBorder;
     40               
     41        BOOL prevShowAvailability;
     42       
     43        float interval;
     44        int   lastRowColCount;
     45       
     46        BOOL useGCD;
    3847}
    3948
    4049- (void) setTorrent: (Torrent *) torrent;
     
    4251- (void) clearView;
    4352- (void) updateView;
    4453
     54- (void) determineColorsForRow: (NSInteger) row
     55                                  withColCount: (NSInteger) colCount
     56                                        withPieces: (int8_t *)pieces
     57                         withPiecesPercent: (float *) piecesPercent
     58                                        imageWidth: (CGFloat) imageWidth
     59                          showAvailability: (BOOL) showAvailablity
     60                                          firstRun: (BOOL) first
     61                                  allFillRects: (NSRect   *) allFillRects
     62                                 allFillColors: (NSColor **) allFillColors
     63                                 allUsedCounts: (int      *) allUsedCounts;
     64
     65
     66
    4567@end
     68
     69// A couple of straight C functions
     70void calculatePiecesPercentInterval(int row, int rowCount, int lastRowColCount, int stride, float interval, float* unsampledPiecesPercent, float* piecesPercent);
     71void calculatePiecesInterval(int row, int rowCount, int lastRowColCount, int stride, float interval, int8_t* unsampledPieces, int8_t* pieces);
     72
  • PiecesView.m

     
    2222 * DEALINGS IN THE SOFTWARE.
    2323 *****************************************************************************/
    2424
     25#import "NSApplicationAdditions.h"
     26
    2527#import "PiecesView.h"
    2628#import "Torrent.h"
    2729#import "InfoWindowController.h"
     
    3638#define PIECE_SOME 1
    3739#define PIECE_HIGH_PEERS 2
    3840#define PIECE_FINISHED 3
    39 #define PIECE_FLASHING 4
     41#define PIECE_FLASHING_COMPLETE 4
     42#define PIECE_FLASHING_PROGRESS_0 5
     43#define PIECE_FLASHING_PROGRESS_1 6
    4044
     45#define USE_GCD
     46
     47
    4148@implementation PiecesView
    4249
    4350- (void) awakeFromNib
     
    5158    [gradient drawInRect: [self bounds] angle: 90.0f];
    5259    [gradient release];
    5360    [fBack unlockFocus];
    54    
     61       
    5562    //store box colors
    5663    fGreenAvailabilityColor = [[NSColor colorWithCalibratedRed: 0.0f green: 1.0f blue: 0.4f alpha: 1.0f] retain];
    5764    fBluePieceColor = [[NSColor colorWithCalibratedRed: 0.0f green: 0.4f blue: 0.8f alpha: 1.0f] retain];
    58            
     65               
     66    //store box colors for the yellow flash on progress
     67        fPercentProgressColor0 = [[NSColor colorWithCalibratedRed: 0.900f green: 0.900f blue: 0.165f alpha: 1.0f] retain];
     68        fPercentProgressColor1 = [[NSColor colorWithCalibratedRed: 0.925f green: 0.925f blue: 0.171f alpha: 1.0f] retain];     
     69
     70        // Use Grand Central Dispatch (libdispatch) for some loops
     71        // useGCD      = [NSApp isOnSnowLeopardOrBetter] ;   // Only use GCD on Snow Leopard
     72               
    5973    //actually draw the box
    6074    [self setTorrent: nil];
    6175}
     
    6377- (void) dealloc
    6478{
    6579    tr_free(fPieces);
    66    
     80        tr_free(fPrevPiecesPercent);
     81       
    6782    [fBack release];
    6883   
    6984    [fGreenAvailabilityColor release];
    7085    [fBluePieceColor release];
     86    [fPercentProgressColor0 release];
     87    [fPercentProgressColor1 release];
    7188   
    7289    [super dealloc];
    7390}
     
    86103        CGFloat width = [self bounds].size.width;
    87104        fWidth = (width - (fAcross + 1) * BETWEEN) / fAcross;
    88105        fExtraBorder = (width - ((fWidth + BETWEEN) * fAcross + BETWEEN)) / 2;
     106               
     107                interval = (float)[fTorrent pieceCount] / fNumPieces;
     108               
     109                // Calculate number of columns in the last row of the grid.
     110                // This should cover cases with fewer than fAcross*fAcross pieces.
     111                // In the normal case with many pieces, lastRowColCount
     112                // should be equal to fAcross.
     113                lastRowColCount = fNumPieces % fAcross > 0 ? fNumPieces % fAcross : fAcross;
    89114    }
    90115   
    91116    //reset the view to blank
     
    99124- (void) clearView
    100125{
    101126    tr_free(fPieces);
     127        tr_free(fPrevPiecesPercent);
     128       
    102129    fPieces = NULL;
     130        fPrevPiecesPercent = NULL;
    103131}
    104132
    105133- (void) updateView
    106134{
    107135    if (!fTorrent)
    108136        return;
     137                   
     138    int8_t * pieces = NULL, * unsampledPieces = NULL;
     139    float * piecesPercent = NULL, * unsampledPiecesPercent = NULL;
     140       
     141        // For parallelization of the drawing algorithm
     142        NSRect   * allFillRects = tr_malloc([fTorrent pieceCount] * sizeof(NSRect));   
     143        NSColor ** allFillColors = tr_malloc([fTorrent pieceCount] * sizeof(NSColor *));
     144        int      * allUsedCounts = tr_malloc(fAcross * sizeof(int) );
     145                   
     146    BOOL showAvailablity = [[NSUserDefaults standardUserDefaults] boolForKey: @"PiecesViewShowAvailability"];
     147               
     148        if (showAvailablity)
     149    {   
     150                unsampledPieces = (int8_t *)tr_malloc([fTorrent pieceCount] * sizeof(int8_t));
     151                pieces = (int8_t *)tr_malloc(fNumPieces * sizeof(int8_t));
     152                [fTorrent getAvailability: unsampledPieces size: [fTorrent pieceCount]];
     153
     154#ifdef USE_GCD
     155                dispatch_apply(fAcross, dispatch_get_global_queue(0, 0), ^(size_t row) {
     156#else
     157                for ( int row = 0; row < fAcross; ++row )                       
     158#endif
     159                        calculatePiecesInterval( row,  fAcross,  lastRowColCount,  fAcross,  interval, unsampledPieces, pieces);
     160#ifdef USE_GCD
     161                });
     162#endif
     163               
     164                /*
     165                if ( useGCD ) {
     166                        dispatch_apply(fAcross, dispatch_get_global_queue(0, 0), ^(size_t row) {
     167                                calculatePiecesInterval( row,  fAcross,  lastRowColCount,  fAcross,  interval, unsampledPieces, pieces);
     168                        });
     169                }
     170                else {
     171                        for ( int row = 0; row < fAcross; ++row )
     172                                calculatePiecesInterval( row,  fAcross,  lastRowColCount,  fAcross,  interval, unsampledPieces, pieces);
     173                }
     174                 */
     175    }
     176    else
     177    {   
     178                unsampledPiecesPercent = (float *)tr_malloc([fTorrent pieceCount] * sizeof(float));
     179                piecesPercent = (float *)tr_malloc(fNumPieces * sizeof(float));
     180                [fTorrent getAmountFinished: unsampledPiecesPercent size: [fTorrent pieceCount]];
     181               
     182#ifdef USE_GCD
     183                dispatch_apply(fAcross, dispatch_get_global_queue(0, 0), ^(size_t row) {
     184#else
     185                for ( int row = 0; row < fAcross; ++row )                       
     186#endif
     187                        calculatePiecesPercentInterval( row,  fAcross,  lastRowColCount,  fAcross,  interval, unsampledPiecesPercent, piecesPercent);
     188#ifdef USE_GCD
     189                });
     190#endif
     191               
     192                /*
     193                if ( useGCD ) {
     194                        dispatch_apply(fAcross, dispatch_get_global_queue(0, 0), ^(size_t row) {
     195                                calculatePiecesPercentInterval( row,  fAcross,  lastRowColCount,  fAcross,  interval, unsampledPiecesPercent, piecesPercent);
     196                        });
     197                }
     198                else {
     199                        for ( int row = 0; row < fAcross; ++row )
     200                                calculatePiecesPercentInterval( row,  fAcross,  lastRowColCount,  fAcross,  interval, unsampledPiecesPercent, piecesPercent);
     201                }
     202                 */
     203        }
    109204   
    110205    //determine if first time
    111206    const BOOL first = fPieces == NULL;
    112     if (first)
     207    if (first) {
    113208        fPieces = (int8_t *)tr_malloc(fNumPieces * sizeof(int8_t));
     209                fPrevPiecesPercent = (float *)tr_malloc(fNumPieces * sizeof(float));
     210        }
    114211
    115     int8_t * pieces = NULL;
    116     float * piecesPercent = NULL;
     212        if ( first || !showAvailablity && prevShowAvailability  ) {
     213                // First run after switching view from availability to progress
     214                // (or first run altogether) so previous pieces are set to 200%
     215                // to avoid a huge flash of yellow.
     216                for ( int i = 0; i < fNumPieces; i++ ) {
     217                        fPrevPiecesPercent[i] = 2.0f;
     218                }
     219        }
     220       
     221    NSImage * image = [self image];
     222       
     223        for (NSInteger i = 0; i < fAcross; i++)
     224                 allUsedCounts[i] = 0;
    117225   
    118     const BOOL showAvailablity = [[NSUserDefaults standardUserDefaults] boolForKey: @"PiecesViewShowAvailability"];
    119     if (showAvailablity)
    120     {   
    121         pieces = (int8_t *)tr_malloc(fNumPieces * sizeof(int8_t));
    122         [fTorrent getAvailability: pieces size: fNumPieces];
     226#ifdef USE_GCD
     227        dispatch_apply(fAcross, dispatch_get_global_queue(0, 0), ^(size_t i) {
     228#else
     229        for (NSInteger i = 0; i < fAcross; i++)
     230#endif
     231                [self determineColorsForRow: i
     232                                           withColCount: fAcross
     233                                                 withPieces: pieces
     234                                  withPiecesPercent:  piecesPercent
     235                                                 imageWidth:  [image size].width
     236                                   showAvailability:  showAvailablity
     237                                                   firstRun:  first
     238                                           allFillRects:  allFillRects
     239                                          allFillColors:  allFillColors
     240                                          allUsedCounts:  allUsedCounts
     241                 ];
     242#ifdef USE_GCD
     243        });
     244#endif
     245       
     246               
     247        /*
     248        if ( useGCD ) {
     249                dispatch_apply(fAcross, dispatch_get_global_queue(0, 0), ^(size_t i) {
     250                        [self determineColorsForRow: i
     251                                                   withColCount: fAcross
     252                                                         withPieces: pieces
     253                                          withPiecesPercent:  piecesPercent
     254                                                         imageWidth:  [image size].width
     255                                           showAvailability:  showAvailablity
     256                                                           firstRun:  first
     257                                                   allFillRects:  allFillRects
     258                                                  allFillColors:  allFillColors
     259                                                  allUsedCounts:  allUsedCounts
     260                         ];
     261                });
     262        }
     263        else {
     264                for (NSInteger i = 0; i < fAcross; i++)
     265                        [self determineColorsForRow: i
     266                                                   withColCount: fAcross
     267                                                         withPieces: pieces
     268                                          withPiecesPercent: piecesPercent
     269                                                         imageWidth: [image size].width
     270                                           showAvailability: showAvailablity
     271                                                           firstRun: first
     272                                                   allFillRects: allFillRects
     273                                                  allFillColors: allFillColors
     274                                                  allUsedCounts: allUsedCounts
     275                         ];
    123276    }
    124     else
    125     {   
    126         piecesPercent = (float *)tr_malloc(fNumPieces * sizeof(float));
    127         [fTorrent getAmountFinished: piecesPercent size: fNumPieces];
    128     }
    129    
    130     NSImage * image = [self image];
    131    
    132     NSRect fillRects[fNumPieces];
    133     NSColor * fillColors[fNumPieces];
    134    
    135     NSInteger index = -1, usedCount = 0;
    136    
     277        */
     278       
     279        BOOL changed = FALSE;
    137280    for (NSInteger i = 0; i < fAcross; i++)
    138         for (NSInteger j = 0; j < fAcross; j++)
    139         {
    140             index++;
    141             if (index >= fNumPieces)
    142             {
    143                 i = fAcross;
    144                 break;
    145             }
    146            
    147             NSColor * pieceColor = nil;
    148            
    149             if (showAvailablity ? pieces[index] == -1 : piecesPercent[index] == 1.0)
    150             {
    151                 if (first || fPieces[index] != PIECE_FINISHED)
    152                 {
    153                     if (!first && fPieces[index] != PIECE_FLASHING)
    154                     {
    155                         pieceColor = [NSColor orangeColor];
    156                         fPieces[index] = PIECE_FLASHING;
    157                     }
    158                     else
    159                     {
    160                         pieceColor = fBluePieceColor;
    161                         fPieces[index] = PIECE_FINISHED;
    162                     }
    163                 }
    164             }
    165             else if (showAvailablity ? pieces[index] == 0 : piecesPercent[index] == 0.0)
    166             {
    167                 if (first || fPieces[index] != PIECE_NONE)
    168                 {
    169                     pieceColor = [NSColor whiteColor];
    170                     fPieces[index] = PIECE_NONE;
    171                 }
    172             }
    173             else if (showAvailablity && pieces[index] >= HIGH_PEERS)
    174             {
    175                 if (first || fPieces[index] != PIECE_HIGH_PEERS)
    176                 {
    177                     pieceColor = fGreenAvailabilityColor;
    178                     fPieces[index] = PIECE_HIGH_PEERS;
    179                 }
    180             }
    181             else
    182             {
    183                 //always redraw "mixed"
    184                 CGFloat percent = showAvailablity ? (CGFloat)pieces[index]/HIGH_PEERS : piecesPercent[index];
    185                 NSColor * fullColor = showAvailablity ? fGreenAvailabilityColor : fBluePieceColor;
    186                 pieceColor = [[NSColor whiteColor] blendedColorWithFraction: percent ofColor: fullColor];
    187                 fPieces[index] = PIECE_SOME;
    188             }
    189            
    190             if (pieceColor)
    191             {
    192                 fillRects[usedCount] = NSMakeRect(j * (fWidth + BETWEEN) + BETWEEN + fExtraBorder,
    193                                                     [image size].width - (i + 1) * (fWidth + BETWEEN) - fExtraBorder,
    194                                                     fWidth, fWidth);
    195                 fillColors[usedCount] = pieceColor;
    196                
    197                 usedCount++;
    198             }
    199         }
    200    
    201     if (usedCount > 0)
    202     {
    203         [image lockFocus];
    204         NSRectFillListWithColors(fillRects, fillColors, usedCount);
    205         [image unlockFocus];
    206         [self setNeedsDisplay];
    207     }
    208    
     281                        changed |= allUsedCounts[i] > 0;
     282       
     283        if (changed) {
     284                [image lockFocus];
     285                for (NSInteger i = 0; i < fAcross; i++)
     286                {
     287                        NSRectFillListWithColors( &(allFillRects[i * fAcross]), &(allFillColors[i * fAcross]), allUsedCounts[i]);
     288                        for (int j = 0; j < allUsedCounts[i]; j++)
     289                                [allFillColors[i * fAcross + j] release];
     290                }
     291                [image unlockFocus];
     292                [self setNeedsDisplay];
     293        }
     294       
     295        if ( !showAvailablity ) {
     296                memcpy(fPrevPiecesPercent,  piecesPercent, fNumPieces * sizeof(float));
     297        }
     298
    209299    tr_free(pieces);
    210300    tr_free(piecesPercent);
     301        tr_free(unsampledPieces);
     302        tr_free(unsampledPiecesPercent);
     303       
     304        tr_free(allFillRects); 
     305        tr_free(allFillColors);
     306        tr_free(allUsedCounts);
     307       
     308        prevShowAvailability = showAvailablity;
    211309}
    212310
     311
     312- (void) determineColorsForRow: (NSInteger) row
     313                                  withColCount: (NSInteger) colCount
     314                                        withPieces: (int8_t *)pieces
     315                         withPiecesPercent: (float *) piecesPercent
     316                                        imageWidth: (CGFloat) imageWidth
     317                          showAvailability: (BOOL) showAvailablity
     318                                          firstRun: (BOOL) first
     319                                  allFillRects: (NSRect   *) allFillRects
     320                                 allFillColors: (NSColor **) allFillColors
     321                                 allUsedCounts: (int      *) allUsedCounts
     322{
     323        int usedCount = 0;
     324       
     325        for (NSInteger j = 0; j < colCount; j++)
     326        {
     327                NSInteger index = row * colCount + j;
     328                if (index >= fNumPieces)
     329                {
     330                        //i = fAcross;
     331                        break;
     332                }
     333               
     334                NSColor * pieceColor = nil;
     335               
     336                if (showAvailablity ? pieces[index] == -1 : piecesPercent[index] == 1.0)
     337                {
     338                        if (first || fPieces[index] != PIECE_FINISHED)
     339                        {
     340                                if (!first && fPieces[index] != PIECE_FLASHING_COMPLETE)
     341                                {
     342                                        pieceColor = [NSColor orangeColor];
     343                                        fPieces[index] = PIECE_FLASHING_COMPLETE;
     344                                }
     345                                else
     346                                {
     347                                        pieceColor = fBluePieceColor;
     348                                        fPieces[index] = PIECE_FINISHED;
     349                                }
     350                        }
     351                }
     352                else if (showAvailablity ? pieces[index] == 0 : piecesPercent[index] == 0.0)
     353                {
     354                        if (first || fPieces[index] != PIECE_NONE)
     355                        {
     356                                pieceColor = [NSColor whiteColor];
     357                                fPieces[index] = PIECE_NONE;
     358                        }
     359                }
     360                else if ( !showAvailablity && ( piecesPercent[index] > fPrevPiecesPercent[index] ) )
     361                {               
     362                        // There is progress compared to the previous run - show it!
     363                        if ( fPieces[index] == PIECE_FLASHING_PROGRESS_1 ) {
     364                                pieceColor = fPercentProgressColor0;
     365                                fPieces[index] = PIECE_FLASHING_PROGRESS_0;
     366                        }
     367                        else {
     368                                pieceColor = fPercentProgressColor1;
     369                                fPieces[index] = PIECE_FLASHING_PROGRESS_1;
     370                        }                               
     371                }
     372                else if (showAvailablity && pieces[index] >= HIGH_PEERS)
     373                {
     374                        if (first || fPieces[index] != PIECE_HIGH_PEERS)
     375                        {
     376                                pieceColor = fGreenAvailabilityColor;
     377                                fPieces[index] = PIECE_HIGH_PEERS;
     378                        }
     379                }
     380                else
     381                {
     382                        //always redraw "mixed"
     383                        CGFloat percent = showAvailablity ? (CGFloat)pieces[index]/HIGH_PEERS : piecesPercent[index];
     384                        NSColor * fullColor = showAvailablity ? fGreenAvailabilityColor : fBluePieceColor;
     385                        pieceColor = [[NSColor whiteColor] blendedColorWithFraction: percent ofColor: fullColor];
     386                        fPieces[index] = PIECE_SOME;
     387                }
     388               
     389               
     390                if (pieceColor)
     391                {
     392                        allFillRects[ row * colCount + usedCount] = NSMakeRect(j * (fWidth + BETWEEN) + BETWEEN + fExtraBorder,
     393                                                                                          imageWidth - (row + 1) * (fWidth + BETWEEN) - fExtraBorder,
     394                                                                                          fWidth, fWidth);
     395                        [pieceColor retain];
     396                        allFillColors[row * colCount + usedCount] = pieceColor;
     397                       
     398                        usedCount++;
     399                        allUsedCounts[row] = usedCount;                         
     400                }
     401        }
     402}
     403
     404void calculatePiecesPercentInterval(int row, int rowCount, int lastRowColCount, int stride, float interval, float* unsampledPiecesPercent, float* piecesPercent)
     405{
     406        int colCount = row == rowCount - 1 ? lastRowColCount : stride;
     407       
     408        for( int col = 0; col < colCount; ++col )
     409        {
     410                int i = row * stride + col;
     411               
     412                int first_piece = i * interval;
     413               
     414                // Last piece of last interval is also the last piece of the torrent
     415                int last_piece =  ( i + 1 ) * interval;
     416               
     417                float lower_piece_fract = 1.0f - ((float)i * interval - first_piece );
     418                float upper_piece_fract = ((float)(i + 1) * interval -  last_piece );
     419               
     420                if ( upper_piece_fract == 0.0f ) {
     421                        last_piece--;
     422                        upper_piece_fract = 1.0f;
     423                }
     424               
     425                float sum = 0.0f, avg;
     426               
     427                // The flag complete is used to keep track of the interval. If
     428                // all pieces in the interval are complete, the downsampled
     429                // value is set to exactly 1.0f to avoid rounding errors.
     430                BOOL complete = TRUE;
     431               
     432                if ( first_piece == last_piece ) {
     433                        avg =  unsampledPiecesPercent[first_piece];
     434                        complete = ( avg == 1.0f );
     435                }
     436                else {
     437                        if ( unsampledPiecesPercent[first_piece] != 1.0f ) {
     438                                sum += unsampledPiecesPercent[first_piece] * lower_piece_fract;
     439                                complete = FALSE;
     440                        }
     441                        else {
     442                                sum += lower_piece_fract;
     443                        }
     444                       
     445                        if ( unsampledPiecesPercent[last_piece] != 1.0f ) {                             
     446                                sum += unsampledPiecesPercent[last_piece] * upper_piece_fract;
     447                                complete = FALSE;
     448                        }
     449                        else {
     450                                sum += upper_piece_fract;
     451                        }
     452                       
     453                        int j;
     454                        for ( j = first_piece + 1; j < last_piece; j++ ) {
     455                                if ( unsampledPiecesPercent[j] != 1.0f ) {
     456                                        sum += unsampledPiecesPercent[j];
     457                                        complete = FALSE;
     458                                }
     459                                else {
     460                                        sum += 1.0f;
     461                                }
     462                        }
     463                       
     464                        avg = sum / interval;
     465                }
     466               
     467                piecesPercent[i] = complete ? 1.0f : avg;
     468        }
     469}
     470
     471void calculatePiecesInterval(int row, int rowCount, int lastRowColCount, int stride, float interval, int8_t* unsampledPieces, int8_t* pieces)
     472{               
     473        int colCount = row == rowCount - 1 ? lastRowColCount : stride;
     474       
     475        for( int col = 0; col < colCount; ++col )
     476        {
     477                int i = row * stride + col;
     478               
     479                int first_piece = i * interval;
     480                int last_piece =  ( i + 1 ) * interval;
     481               
     482                float lower_piece_fract = 1.0f - ((float)i * interval - first_piece );
     483                float upper_piece_fract = ((float)(i + 1) * interval -  last_piece );
     484               
     485                if ( upper_piece_fract == 0.0f ) {
     486                        last_piece--;
     487                        upper_piece_fract = 1.0f;
     488                }
     489               
     490                int   pieceCount;
     491               
     492                float sum = 0.0f, result;
     493               
     494                if ( first_piece == last_piece ) {
     495                        if ( unsampledPieces[first_piece] != -1 ) {
     496                                result = (pieceCount = unsampledPieces[first_piece]);
     497                        }
     498                        else {
     499                                result = -1;
     500                        }
     501                }
     502                else {
     503                        float incompleteCount = 0.0f;
     504                       
     505                        if ( unsampledPieces[first_piece] != -1 )
     506                        {       
     507                                sum += (pieceCount = unsampledPieces[first_piece]) * lower_piece_fract;
     508                                incompleteCount += lower_piece_fract;
     509                        }
     510                       
     511                        if ( unsampledPieces[last_piece] != -1 )
     512                        {       
     513                                sum += (pieceCount = unsampledPieces[last_piece]) * upper_piece_fract;
     514                                incompleteCount += upper_piece_fract;
     515                        }
     516                       
     517                        for ( int j = first_piece + 1; j < last_piece; j++ ) {
     518                                if ( unsampledPieces[j] != -1 )
     519                                {       
     520                                        sum += (pieceCount = unsampledPieces[j]);
     521                                        incompleteCount += 1.0f;
     522                                }
     523                        }
     524                       
     525                        if ( incompleteCount > 0 ) {
     526                                result = sum / incompleteCount;
     527                        }
     528                        else {
     529                                result = -1;
     530                        }
     531                }
     532               
     533                pieces[i] = (int)result;
     534    }
     535}
     536
     537
    213538- (BOOL) acceptsFirstMouse: (NSEvent *) event
    214539{
    215540    return YES;