static int AddStats(DBProvider * pdb, int gm_id, int player_id, int player, const char *table, int nMatchTo, statcontext * sc) { gchar *buf; GString *column, *value; int totalmoves, unforced; float errorcost, errorskill; float aaaar[3][2][2][2]; float r; int ret; char tmpf[G_ASCII_DTOSTR_BUF_SIZE]; int gms_id = GetNextId(pdb, table); if (gms_id == -1) return FALSE; totalmoves = sc->anTotalMoves[player]; unforced = sc->anUnforcedMoves[player]; getMWCFromError(sc, aaaar); errorskill = aaaar[CUBEDECISION][PERMOVE][player][NORMALISED]; errorcost = aaaar[CUBEDECISION][PERMOVE][player][UNNORMALISED]; column = g_string_new(NULL); value = g_string_new(NULL); if (strcmp("matchstat", table) == 0) { APPENDI("matchstat_id", gms_id); APPENDI("session_id", gm_id); } else { APPENDI("gamestat_id", gms_id); APPENDI("game_id", gm_id); } APPENDI("player_id", player_id); APPENDI("total_moves", totalmoves); APPENDI("unforced_moves", unforced); APPENDI("unmarked_moves", sc->anMoves[player][SKILL_NONE]); APPENDI("good_moves", 0); APPENDI("doubtful_moves", sc->anMoves[player][SKILL_DOUBTFUL]); APPENDI("bad_moves", sc->anMoves[player][SKILL_BAD]); APPENDI("very_bad_moves", sc->anMoves[player][SKILL_VERYBAD]); APPENDF("chequer_error_total_normalised", sc->arErrorCheckerplay[player][0]); APPENDF("chequer_error_total", sc->arErrorCheckerplay[player][1]); APPENDF("chequer_error_per_move_normalised", Ratio(sc->arErrorCheckerplay[player][0], unforced)); APPENDF("chequer_error_per_move", Ratio(sc->arErrorCheckerplay[player][1], unforced)); APPENDI("chequer_rating", GetRating(Ratio (scMatch.arErrorCheckerplay[player][0], unforced))); APPENDI("very_lucky_rolls", sc->anLuck[player][LUCK_VERYGOOD]); APPENDI("lucky_rolls", sc->anLuck[player][LUCK_GOOD]); APPENDI("unmarked_rolls", sc->anLuck[player][LUCK_NONE]); APPENDI("unlucky_rolls", sc->anLuck[player][LUCK_BAD]); APPENDI("very_unlucky_rolls", sc->anLuck[player][LUCK_VERYBAD]); APPENDF("luck_total_normalised", sc->arLuck[player][0]); APPENDF("luck_total", sc->arLuck[player][1]); APPENDF("luck_per_move_normalised", Ratio(sc->arLuck[player][0], totalmoves)); APPENDF("luck_per_move", Ratio(sc->arLuck[player][1], totalmoves)); APPENDI("luck_rating", getLuckRating(Ratio(sc->arLuck[player][0], totalmoves))); APPENDI("total_cube_decisions", sc->anTotalCube[player]); APPENDI("close_cube_decisions", sc->anCloseCube[player]); APPENDI("doubles", sc->anDouble[player]); APPENDI("takes", sc->anTake[player]); APPENDI("passes", sc->anPass[player]); APPENDI("missed_doubles_below_cp", sc->anCubeMissedDoubleDP[player]); APPENDI("missed_doubles_above_cp", sc->anCubeMissedDoubleTG[player]); APPENDI("wrong_doubles_below_dp", sc->anCubeWrongDoubleDP[player]); APPENDI("wrong_doubles_above_tg", sc->anCubeWrongDoubleTG[player]); APPENDI("wrong_takes", sc->anCubeWrongTake[player]); APPENDI("wrong_passes", sc->anCubeWrongPass[player]); APPENDF("error_missed_doubles_below_cp_normalised", sc->arErrorMissedDoubleDP[player][0]); APPENDF("error_missed_doubles_above_cp_normalised", sc->arErrorMissedDoubleTG[player][0]); APPENDF("error_wrong_doubles_below_dp_normalised", sc->arErrorWrongDoubleDP[player][0]); APPENDF("error_wrong_doubles_above_tg_normalised", sc->arErrorWrongDoubleTG[player][0]); APPENDF("error_wrong_takes_normalised", sc->arErrorWrongTake[player][0]); APPENDF("error_wrong_passes_normalised", sc->arErrorWrongPass[player][0]); APPENDF("error_missed_doubles_below_cp", sc->arErrorMissedDoubleDP[player][1]); APPENDF("error_missed_doubles_above_cp", sc->arErrorMissedDoubleTG[player][1]); APPENDF("error_wrong_doubles_below_dp", sc->arErrorWrongDoubleDP[player][1]); APPENDF("error_wrong_doubles_above_tg", sc->arErrorWrongDoubleTG[player][1]); APPENDF("error_wrong_takes", sc->arErrorWrongTake[player][1]); APPENDF("error_wrong_passes", sc->arErrorWrongPass[player][1]); APPENDF("cube_error_total_normalised", errorskill * sc->anCloseCube[player]); APPENDF("cube_error_total", errorcost * sc->anCloseCube[player]); APPENDF("cube_error_per_move_normalised", errorskill); APPENDF("cube_error_per_move", errorcost); APPENDI("cube_rating", GetRating(errorskill));; APPENDF("overall_error_total_normalised", errorskill * sc->anCloseCube[player] + sc->arErrorCheckerplay[player][0]); APPENDF("overall_error_total", errorcost * sc->anCloseCube[player] + sc->arErrorCheckerplay[player][1]); APPENDF("overall_error_per_move_normalised", Ratio(errorskill * sc->anCloseCube[player] + sc->arErrorCheckerplay[player][0], sc->anCloseCube[player] + unforced)); APPENDF("overall_error_per_move", Ratio(errorcost * sc->anCloseCube[player] + sc->arErrorCheckerplay[player][1], sc->anCloseCube[player] + unforced)); APPENDI("overall_rating", GetRating(Ratio (errorskill * sc->anCloseCube[player] + sc->arErrorCheckerplay[player][0], sc->anCloseCube[player] + unforced))); APPENDF("actual_result", sc->arActualResult[player]); APPENDF("luck_adjusted_result", sc->arLuckAdj[player]); APPENDI("snowie_moves", totalmoves + scMatch.anTotalMoves[!player]); APPENDF("snowie_error_rate_per_move", Ratio(errorskill * scMatch.anCloseCube[player] + scMatch.arErrorCheckerplay[player][0], totalmoves + scMatch.anTotalMoves[!player])); /*time */ APPENDI("time_penalties", 0); APPENDF("time_penalty_loss_normalised", 0.0); APPENDF("time_penalty_loss", 0.0); /* matches only */ r = 0.5f + scMatch.arActualResult[player] - scMatch.arLuck[player][1] + scMatch.arLuck[!player][1]; if (nMatchTo && r > 0.0f && r < 1.0f) APPENDF("luck_based_fibs_rating_diff", relativeFibsRating(r, nMatchTo)); if (nMatchTo && (scMatch.fCube || scMatch.fMoves)) { APPENDF("error_based_fibs_rating", absoluteFibsRating(aaaar[CHEQUERPLAY][PERMOVE] [player][NORMALISED], aaaar[CUBEDECISION][PERMOVE] [player][NORMALISED], nMatchTo, rRatingOffset)); if (scMatch.anUnforcedMoves[player]) APPENDF("chequer_rating_loss", absoluteFibsRatingChequer(aaaar [CHEQUERPLAY] [PERMOVE][player] [NORMALISED], nMatchTo)); if (scMatch.anCloseCube[player]) APPENDF("cube_rating_loss", absoluteFibsRatingCube(aaaar[CUBEDECISION] [PERMOVE][player] [NORMALISED], nMatchTo)); } /* for money sessions only */ if (scMatch.fDice && !nMatchTo && scMatch.nGames > 1) { APPENDF("actual_advantage", scMatch.arActualResult[player] / scMatch.nGames); APPENDF("actual_advantage_ci", 1.95996f * sqrt(scMatch.arVarianceActual[player] / scMatch.nGames)); APPENDF("luck_adjusted_advantage", scMatch.arLuckAdj[player] / scMatch.nGames); APPENDF("luck_adjusted_advantage_ci", 1.95996f * sqrt(scMatch.arVarianceLuckAdj[player] / scMatch.nGames)); } g_string_truncate(column, column->len - 2); g_string_truncate(value, value->len - 2); buf = g_strdup_printf("INSERT INTO %s (%s) VALUES(%s)", table, column->str, value->str); ret = pdb->UpdateCommand(buf); g_free(buf); g_string_free(column, TRUE); g_string_free(value, TRUE); return ret; }
extern GList * formatGS(const statcontext * psc, const int nMatchTo, const enum _formatgs fg) { GList *list = NULL; char **aasz; float aaaar[3][2][2][2]; getMWCFromError(psc, aaaar); switch (fg) { case FORMATGS_CHEQUER: { static int ai[4] = { SKILL_NONE, SKILL_DOUBTFUL, SKILL_BAD, SKILL_VERYBAD }; static const char *asz[4] = { N_("Unmarked moves"), N_("Moves marked doubtful"), N_("Moves marked bad"), N_("Moves marked very bad") }; int i; /* chequer play part */ list = g_list_append(list, numberEntry(_("Total moves"), psc->anTotalMoves[0], psc->anTotalMoves[1])); list = g_list_append(list, numberEntry(_("Unforced moves"), psc->anUnforcedMoves[0], psc->anUnforcedMoves[1])); for (i = 0; i < 4; ++i) list = g_list_append(list, numberEntry(gettext(asz[i]), psc->anMoves[0][ai[i]], psc->anMoves[1][ai[i]])); /* total error rate */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Error total %s"), total_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRate(-aaaar[CHEQUERPLAY][TOTAL][i][NORMALISED], -aaaar[CHEQUERPLAY][TOTAL][i][UNNORMALISED], nMatchTo); list = g_list_append(list, aasz); /* error rate per move */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Error rate %s"), rate_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRateMP(-aaaar[CHEQUERPLAY][PERMOVE][i][NORMALISED], -aaaar[CHEQUERPLAY][PERMOVE][i][UNNORMALISED], nMatchTo); list = g_list_append(list, aasz); /* chequer play rating */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Chequerplay rating")); for (i = 0; i < 2; ++i) if (psc->anUnforcedMoves[i]) aasz[i + 1] = g_strdup(Q_(aszRating[GetRating(aaaar[CHEQUERPLAY][PERMOVE][i][NORMALISED])])); else aasz[i + 1] = g_strdup(_("n/a")); list = g_list_append(list, aasz); } break; case FORMATGS_CUBE: { static const char *asz[] = { N_("Total cube decisions"), N_("Close or actual cube decisions"), N_("Doubles"), N_("Takes"), N_("Passes") }; static const char *asz2[] = { N_("Missed doubles below CP"), N_("Missed doubles above CP"), N_("Wrong doubles below DP"), N_("Wrong doubles above TG"), N_("Wrong takes"), N_("Wrong passes") }; int i, j; const int *ai[5], *ai2[6]; const float *af2[2][6]; ai[0] = psc->anTotalCube; ai[1] = psc->anCloseCube; ai[2] = psc->anDouble; ai[3] = psc->anTake; ai[4] = psc->anPass; ai2[0] = psc->anCubeMissedDoubleDP; ai2[1] = psc->anCubeMissedDoubleTG; ai2[2] = psc->anCubeWrongDoubleDP; ai2[3] = psc->anCubeWrongDoubleTG; ai2[4] = psc->anCubeWrongTake; ai2[5] = psc->anCubeWrongPass; af2[0][0] = psc->arErrorMissedDoubleDP[0]; af2[0][1] = psc->arErrorMissedDoubleTG[0]; af2[0][2] = psc->arErrorWrongDoubleDP[0]; af2[0][3] = psc->arErrorWrongDoubleTG[0]; af2[0][4] = psc->arErrorWrongTake[0]; af2[0][5] = psc->arErrorWrongPass[0]; af2[1][0] = psc->arErrorMissedDoubleDP[1]; af2[1][1] = psc->arErrorMissedDoubleTG[1]; af2[1][2] = psc->arErrorWrongDoubleDP[1]; af2[1][3] = psc->arErrorWrongDoubleTG[1]; af2[1][4] = psc->arErrorWrongTake[1]; af2[1][5] = psc->arErrorWrongPass[1]; for (i = 0; i < 5; ++i) list = g_list_append(list, numberEntry(gettext(asz[i]), ai[i][0], ai[i][1])); for (i = 0; i < 6; ++i) { aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf("%s (%s)", gettext(asz2[i]), total_text(nMatchTo)); for (j = 0; j < 2; ++j) aasz[j + 1] = cubeEntry(ai2[i][j], -af2[j][i][0], -af2[j][i][1], nMatchTo); list = g_list_append(list, aasz); } /* total error rate */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Error total %s"), total_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRate(-aaaar[CUBEDECISION][TOTAL][i][NORMALISED], -aaaar[CUBEDECISION][TOTAL][i][UNNORMALISED], nMatchTo); list = g_list_append(list, aasz); /* error rate per cube decision */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Error rate %s"), rate_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRateMP(-aaaar[CUBEDECISION][PERMOVE][i][NORMALISED], -aaaar[CUBEDECISION][PERMOVE][i][UNNORMALISED], nMatchTo); list = g_list_append(list, aasz); /* cube decision rating */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Cube decision rating")); for (i = 0; i < 2; ++i) if (psc->anCloseCube[i]) aasz[i + 1] = g_strdup(Q_(aszRating[GetRating(aaaar[CUBEDECISION][PERMOVE][i][NORMALISED])])); else aasz[i + 1] = g_strdup(_("n/a")); list = g_list_append(list, aasz); } break; case FORMATGS_LUCK: { static const char *asz[] = { N_("Rolls marked very lucky"), N_("Rolls marked lucky"), N_("Rolls unmarked"), N_("Rolls marked unlucky"), N_("Rolls marked very unlucky") }; int i; for (i = 0; i < 5; ++i) list = g_list_append(list, numberEntry(gettext(asz[i]), psc->anLuck[0][4 - i], psc->anLuck[1][4 - i])); /* total luck */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Luck total %s"), total_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRate(psc->arLuck[i][0], psc->arLuck[i][1], nMatchTo); list = g_list_append(list, aasz); /* luck rate per move */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Luck rate %s"), rate_text(nMatchTo)); for (i = 0; i < 2; ++i) if (psc->anTotalMoves[i]) aasz[i + 1] = errorRateMP(psc->arLuck[i][0] / psc->anTotalMoves[i], psc->arLuck[i][1] / psc->anTotalMoves[i], nMatchTo); else aasz[i + 1] = g_strdup(_("n/a")); list = g_list_append(list, aasz); /* chequer play rating */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Luck rating")); for (i = 0; i < 2; ++i) if (psc->anTotalMoves[i]) aasz[i + 1] = g_strdup(Q_(aszLuckRating[getLuckRating(psc->arLuck[i][0] / psc->anTotalMoves[i])])); else aasz[i + 1] = g_strdup(_("n/a")); list = g_list_append(list, aasz); } break; case FORMATGS_OVERALL: { int i, n; /* total error rate */ aasz = g_malloc(3 * sizeof(*aasz)); if (psc->fCube || psc->fMoves) { aasz[0] = g_strdup_printf(_("Error total %s"), total_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRate(-aaaar[COMBINED][TOTAL][i][NORMALISED], -aaaar[COMBINED][TOTAL][i][UNNORMALISED], nMatchTo); list = g_list_append(list, aasz); /* error rate per decision */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup_printf(_("Error rate %s"), rate_text(nMatchTo)); for (i = 0; i < 2; ++i) aasz[i + 1] = errorRateMP(-aaaar[COMBINED][PERMOVE][i][NORMALISED], -aaaar[COMBINED][PERMOVE][i][UNNORMALISED], nMatchTo); list = g_list_append(list, aasz); /* eq. snowie error rate */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Snowie error rate")); for (i = 0; i < 2; ++i) if ((n = psc->anTotalMoves[0] + psc->anTotalMoves[1]) > 0) aasz[i + 1] = errorRateMP(-aaaar[COMBINED][TOTAL][i][NORMALISED] / n, 0.0f, nMatchTo); else aasz[i + 1] = g_strdup(_("n/a")); list = g_list_append(list, aasz); /* rating */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Overall rating")); for (i = 0; i < 2; ++i) if (psc->anCloseCube[i] + psc->anUnforcedMoves[i]) aasz[i + 1] = g_strdup(Q_(aszRating[GetRating(aaaar[COMBINED][PERMOVE][i][NORMALISED])])); else aasz[i + 1] = g_strdup(_("n/a")); list = g_list_append(list, aasz); } if (psc->fDice) { /* luck adj. result */ if ((psc->arActualResult[0] > 0.0f || psc->arActualResult[1] > 0.0f) && psc->fDice) { list = g_list_append(list, luckAdjust(_("Actual result"), psc->arActualResult, nMatchTo)); list = g_list_append(list, luckAdjust(_("Luck adjusted result"), psc->arLuckAdj, nMatchTo)); if (nMatchTo) { /* luck based fibs rating */ float r = 0.5f + psc->arActualResult[0] - psc->arLuck[0][1] + psc->arLuck[1][1]; aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Luck based FIBS rating diff.")); aasz[2] = g_strdup(""); if (r > 0.0f && r < 1.0f) aasz[1] = g_strdup_printf("%+7.2f", relativeFibsRating(r, ms.nMatchTo)); else aasz[1] = g_strdup_printf(_("n/a")); list = g_list_append(list, aasz); } } } if (psc->fCube || psc->fMoves) { /* error based fibs rating */ if (nMatchTo) { aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Error based abs. FIBS rating")); for (i = 0; i < 2; ++i) if (psc->anCloseCube[i] + psc->anUnforcedMoves[i]) aasz[i + 1] = g_strdup_printf("%6.1f", absoluteFibsRating(aaaar[CHEQUERPLAY][PERMOVE][i][NORMALISED], aaaar[CUBEDECISION][PERMOVE][i] [NORMALISED], nMatchTo, rRatingOffset)); else aasz[i + 1] = g_strdup_printf(_("n/a")); list = g_list_append(list, aasz); /* chequer error fibs rating */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Chequerplay errors rating loss")); for (i = 0; i < 2; ++i) if (psc->anUnforcedMoves[i]) aasz[i + 1] = g_strdup_printf("%6.1f", absoluteFibsRatingChequer(aaaar[CHEQUERPLAY][PERMOVE][i] [NORMALISED], nMatchTo)); else aasz[i + 1] = g_strdup_printf(_("n/a")); list = g_list_append(list, aasz); /* cube error fibs rating */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(_("Cube errors rating loss")); for (i = 0; i < 2; ++i) if (psc->anCloseCube[i]) aasz[i + 1] = g_strdup_printf("%6.1f", absoluteFibsRatingCube(aaaar[CUBEDECISION][PERMOVE][i] [NORMALISED], nMatchTo)); else aasz[i + 1] = g_strdup_printf(_("n/a")); list = g_list_append(list, aasz); } } if (psc->fDice && !nMatchTo && psc->nGames > 1) { static const char *asz[2][2] = { {N_("Advantage (actual) in ppg"), /* xgettext: no-c-format */ N_("95% confidence interval (ppg)")}, {N_("Advantage (luck adjusted) in ppg"), /* xgettext: no-c-format */ N_("95% confidence interval (ppg)")} }; int i, j; const float *af[2][2]; af[0][0] = psc->arActualResult; af[0][1] = psc->arVarianceActual; af[1][0] = psc->arLuckAdj; af[1][1] = psc->arVarianceLuckAdj; for (i = 0; i < 2; ++i) { /* ppg */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(gettext(asz[i][0])); for (j = 0; j < 2; ++j) aasz[j + 1] = g_strdup_printf("%+*.*f", fOutputDigits + 3, fOutputDigits, af[i][0][j] / psc->nGames); list = g_list_append(list, aasz); /* std dev. */ aasz = g_malloc(3 * sizeof(*aasz)); aasz[0] = g_strdup(gettext(asz[i][1])); for (j = 0; j < 2; ++j) { float ci = 1.95996f * sqrtf(af[i][1][j] / psc->nGames); float max = af[i][0][j] + ci; float min = af[i][0][j] - ci; aasz[j + 1] = g_strdup_printf("[%*.*f,%*.*f]", fOutputDigits + 3, fOutputDigits, min, fOutputDigits + 3, fOutputDigits, max); } list = g_list_append(list, aasz); } } } break; default: g_assert_not_reached(); break; } return list; }