inline int scoreDigraph(Keyboard *k, char digraph[], int64_t multiplier, int allLocs[]) { int loc0 = allLocs[(int) digraph[0]]; int loc1 = allLocs[(int) digraph[1]]; #ifdef USE_COST_ARRAY k->fitness += allDigraphCosts[loc0][loc1] * multiplier; return 0; #else if (loc0 >= ksize && loc1 >= ksize) { k->distance += doubleShiftCost * multiplier; } else if ((loc0 >= ksize) ^ (loc1 >= ksize)) { k->distance += shiftCost * multiplier; } loc0 %= ksize; loc1 %= ksize; /* These all require that the hand be the same. */ if (hand[loc0] == hand[loc1]) { k->sameHand += sameHand * multiplier; k->sameFinger += calcSameFinger(loc0, loc1) * multiplier; /* These factors are meaningless for the thumbs, because thumbs are * relatively separate from the rest of the fingers. */ if (finger[loc0] != THUMB && finger[loc1] != THUMB) { k->inRoll += calcInRoll (loc0, loc1) * multiplier; k->outRoll += calcOutRoll (loc0, loc1) * multiplier; k->rowChange += calcRowChange (loc0, loc1) * multiplier; k->homeJump += calcHomeJump (loc0, loc1) * multiplier; k->ringJump += calcRingJump (loc0, loc1) * multiplier; k->toCenter += calcToCenter (loc0, loc1) * multiplier; k->toOutside += calcToOutside (loc0, loc1) * multiplier; } } return 0; #endif }
inline int scoreDigraphDirect(Keyboard *k, char digraph[], int64_t multiplier) { int locs[2]; int i; for (i = 0; i < 2; ++i) locs[i] = locIgnoreShifted(k, digraph[i]); if (hand[locs[0]] == hand[locs[1]]) { if (calcInRoll (locs[0], locs[1]) != 0) k->inRoll += multiplier; if (calcOutRoll (locs[0], locs[1]) != 0) k->outRoll += multiplier; k->sameHand += multiplier; if (calcSameFinger(locs[0], locs[1]) != 0) k->sameFinger += multiplier; if (calcRowChange (locs[0], locs[1]) != 0) k->rowChange += multiplier; if (calcHomeJump (locs[0], locs[1]) != 0) k->homeJump += multiplier; if (calcRingJump (locs[0], locs[1]) != 0) k->ringJump += multiplier; if (calcToCenter (locs[0], locs[1]) != 0) k->toCenter += multiplier; if (calcToOutside (locs[0], locs[1]) != 0) k->toOutside += multiplier; } return 0; }
int preCalculateFitness() { int i, j; memset(allDigraphCosts, 0, sizeof(allDigraphCosts)); for (i = 0; i < 2 * ksize; ++i) { for (j = 0; j < 2 * ksize; ++j) { if (i >= ksize && j >= ksize) { allDigraphCosts[i][j] += doubleShiftCost; } else if ((i >= ksize) != (j >= ksize)) { allDigraphCosts[i][j] += shiftCost; } int loc0 = i % ksize; int loc1 = j % ksize; if (hand[loc0] == hand[loc1]) { allDigraphCosts[i][j] += sameHand; allDigraphCosts[i][j] += calcSameFinger(loc0, loc1); if (finger[i] != THUMB && finger[j] != THUMB) { allDigraphCosts[i][j] += calcInRoll (loc0, loc1); allDigraphCosts[i][j] += calcOutRoll (loc0, loc1); allDigraphCosts[i][j] += calcRowChange(loc0, loc1); allDigraphCosts[i][j] += calcHomeJump (loc0, loc1); allDigraphCosts[i][j] += calcRingJump (loc0, loc1); allDigraphCosts[i][j] += calcToCenter (loc0, loc1); allDigraphCosts[i][j] += calcToOutside(loc0, loc1); } } } } return 0; }
/* * Make sure that all of the fitness functions are working correctly. A bug in there * would be hard to notice without explicitly testing it. * 1: There is a bug in one of the fitness functions. */ int testFitness() { if (fullKeyboard == FK_NO) { printf("\nTesting calcInRoll():\n"); testResult(calcInRoll(0, 0), 0); testResult(calcInRoll(10, 11), inRoll); testResult(calcInRoll(14, 15), 0); testResult(calcInRoll(29, 28), inRoll); testResult(calcInRoll(3, 4), 0); testResult(calcInRoll(4, 3), 0); testResult(calcInRoll(11, 2), 0); testResult(calcInRoll(2, 11), 0); printf("\nTesting calcOutRoll():\n"); testResult(calcOutRoll(0, 0), 0); testResult(calcOutRoll(11, 10), outRoll); testResult(calcOutRoll(15, 14), 0); testResult(calcOutRoll(28, 29), outRoll); testResult(calcOutRoll(3, 4), 0); testResult(calcOutRoll(14, 13), 0); printf("\nTesting calcSameFinger():\n"); testResult(calcSameFinger(0, 0), 0); testResult(calcSameFinger(10, 0), sameFingerP); testResult(calcSameFinger(11, 21), sameFingerR); testResult(calcSameFinger(7, 27), sameFingerM); testResult(calcSameFinger(13, 4), sameFingerI); testResult(calcSameFinger(0, 4), 0); printf("\nTesting calcRowChange():\n"); testResult(calcRowChange(8, 8), 0); testResult(calcRowChange(10, 0), rowChangeUp); testResult(calcRowChange(11, 0), rowChangeUp + handWarp); testResult(calcRowChange(13, 2), rowChangeUp + handSmooth); testResult(calcRowChange(8, 16), rowChangeDown); testResult(calcRowChange(8, 26), rowChangeDown); testResult(calcRowChange(28, 9), rowChangeUp + handWarp); testResult(calcRowChange(25, 5), rowChangeUp); printf("\nTesting calcHomeJump():\n"); testResult(calcHomeJump(8, 8), 0); testResult(calcHomeJump(10, 0), 0); testResult(calcHomeJump(11, 0), 0); testResult(calcHomeJump(10, 1), 0); testResult(calcHomeJump(8, 16), 0); testResult(calcHomeJump(8, 26), homeJump + homeJumpIndex); testResult(calcHomeJump(28, 9), homeJump); testResult(calcHomeJump(25, 5), homeJump); printf("\nTesting calcToCenter():\n"); testResult(calcToCenter(0, 0), 0); testResult(calcToCenter(13, 14), toCenter); testResult(calcToCenter(17, 15), toCenter); testResult(calcToCenter(4, 1), toCenter); testResult(calcToCenter(25, 9), toCenter); testResult(calcToCenter(25, 15), 0); } else if (fullKeyboard == FK_STANDARD) { printf("\nTesting calcHomeJump():\n"); testResult(calcHomeJump(8, 8), 0); testResult(calcHomeJump(14, 0), 0); testResult(calcHomeJump(15, 0), 0); testResult(calcHomeJump(14, 1), 0); testResult(calcHomeJump(36, 9), 0); testResult(calcHomeJump(48, 9), doubleJump + homeJumpIndex); testResult(calcHomeJump(49, 23), homeJump + homeJumpIndex); testResult(calcHomeJump(44, 18), homeJump); testResult(calcHomeJump(44, 3), doubleJump); } else { printf("\nTesting calcInRoll():\n"); testResult(calcInRoll(0, 0), 0); testResult(calcInRoll(2, 3), inRoll); testResult(calcInRoll(2, 14), 0); testResult(calcInRoll(13, 3), 0); testResult(calcInRoll(29, 28), inRoll); testResult(calcInRoll(28, 27), 0); printf("\nTesting calcSameFinger():\n"); testResult(calcSameFinger(0, 0), 0); testResult(calcSameFinger(11, 0), sameFingerP); testResult(calcSameFinger(12, 23), sameFingerR); testResult(calcSameFinger(7, 29), sameFingerM); testResult(calcSameFinger(25, 15), sameFingerI); testResult(calcSameFinger(0, 4), 0); printf("\nTesting calcHomeJump():\n"); testResult(calcHomeJump(8, 8), 0); testResult(calcHomeJump(11, 0), 0); testResult(calcHomeJump(12, 0), 0); testResult(calcHomeJump(11, 1), 0); testResult(calcHomeJump(8, 17), 0); testResult(calcHomeJump(19, 39), homeJump + homeJumpIndex); testResult(calcHomeJump(41, 20), homeJump); testResult(calcHomeJump(38, 16), homeJump); } return 0; }
int worstDigraphs(Keyboard *k, int damagingp) { int i; for (i = 0; i < FINGER_COUNT; ++i) k->fingerUsage[i] = 0; char keys[diLen][2]; memcpy(keys, diKeys, sizeof(char) * diLen * 2); int64_t values[diLen]; for (i = 0; i < diLen; ++i) { k->distance = 0; k->inRoll = 0; k->outRoll = 0; k->sameHand = 0; k->sameFinger = 0; k->rowChange = 0; k->homeJump = 0; k->toCenter = 0; k->toOutside = 0; int locs[2]; locs[0] = locWithoutShifted(k, diKeys[i][0]); locs[1] = locWithoutShifted(k, diKeys[i][1]); // These all require that the hand be the same. if (hand[locs[0]] == hand[locs[1]]) { k->inRoll = calcInRoll (locs[0], locs[1]); k->outRoll = calcOutRoll (locs[0], locs[1]); k->sameHand = sameHand ; k->sameFinger = calcSameFinger(locs[0], locs[1]); k->rowChange = calcRowChange (locs[0], locs[1]); k->homeJump = calcHomeJump (locs[0], locs[1]); k->toCenter = calcToCenter (locs[0], locs[1]); k->toOutside = calcToOutside (locs[0], locs[1]); } k->distance = (distanceCosts[locs[0]] + distanceCosts[locs[1]]) * distance; /* Re-assign diValues[i] to the cost of that digraph. */ values[i] = k->distance + k->inRoll + k->outRoll + k->sameHand + k->sameFinger + k->rowChange + k->homeJump + k->toCenter + k->toOutside; /* This function will tell you... * Without this line: Which digraphs have the worst score. * With this line: Which digraphs are the most damaging, based on both score and frequency. */ if (damagingp) values[i] *= diValues[i]; } sortDigraphs(keys, values, 0, diLen - 1); for (i = 0; i < diLen; ++i) { char buf1[5]; char buf2[5]; charToPrintable(buf1, keys[i][0], FALSE); charToPrintable(buf2, keys[i][1], FALSE); printf("%s%s = %lld\n", buf1, buf2, values[i]); } return 0; }
int worstDigraphs(Keyboard *k, int damagingp) { int i; for (i = 0; i < FINGER_COUNT; ++i) k->fingerUsage[i] = 0; struct Digraph worst[diLen]; memcpy(worst, digraphs, sizeof(worst) * diLen); for (i = 0; i < diLen; ++i) { k->distance = 0; k->inRoll = 0; k->outRoll = 0; k->sameHand = 0; k->sameFinger = 0; k->rowChange = 0; k->homeJump = 0; k->toCenter = 0; k->toOutside = 0; int locs[2]; locs[0] = locIgnoreShifted(k, worst[i].key[0]); locs[1] = locIgnoreShifted(k, worst[i].key[1]); // These all require that the hand be the same. if (hand[locs[0]] == hand[locs[1]]) { k->inRoll = calcInRoll (locs[0], locs[1]); k->outRoll = calcOutRoll (locs[0], locs[1]); k->sameHand = sameHand ; k->sameFinger = calcSameFinger(locs[0], locs[1]); k->rowChange = calcRowChange (locs[0], locs[1]); k->homeJump = calcHomeJump (locs[0], locs[1]); k->toCenter = calcToCenter (locs[0], locs[1]); k->toOutside = calcToOutside (locs[0], locs[1]); } k->distance = (distanceCosts[locs[0]] + distanceCosts[locs[1]]) * distance; /* Re-assign digraphs[i].value to the cost of that digraph. */ worst[i].value = k->distance + k->inRoll + k->outRoll + k->sameHand + k->sameFinger + k->rowChange + k->homeJump + k->toCenter + k->toOutside; /* This function will tell you... * Without this line: Which digraphs have the worst score. * With this line: Which digraphs are the most damaging, based on both score and frequency. */ if (damagingp) worst[i].value *= digraphs[i].value; } qsort(worst, diLen, sizeof(struct Digraph), &cmpDigraphsByValue); for (i = 0; i < diLen; ++i) { char buf1[5]; char buf2[5]; charToPrintable(buf1, worst[i].key[0], FALSE); charToPrintable(buf2, worst[i].key[1], FALSE); printf("%s%s = %lld\n", buf1, buf2, worst[i].value); } return 0; }