extern statcontext *relational_player_stats_get(const char *player0, const char *player1) { int id0 = -1; int id1 = -1; DBProvider *pdb = NULL; char *query[2]; int i; char *buf; RowSet *rs; statcontext *psc; g_return_val_if_fail(player0, NULL); if ((pdb = ConnectToDB(dbProviderType)) == NULL) return NULL; id0 = GetPlayerId(pdb, player0); if (player1) id1 = GetPlayerId(pdb, player1); if (id0 == -1 || (player1 && id1 == -1)) return NULL; psc = g_new0(statcontext, 1); if (!player1) { query[0] = g_strdup_printf("where matchstat.player_id = %d", id0); query[1] = g_strdup_printf("NATURAL JOIN session WHERE " "(session.player_id0 = %d OR session.player_id1 = %d) " "AND matchstat.player_id != %d", id0, id0, id0); } else { query[0] = g_strdup_printf("NATURAL JOIN session WHERE " "((session.player_id0 = %d OR session.player_id1 = %d) " " AND " " (session.player_id0 = %d OR session.player_id1 = %d))" "AND matchstat.player_id = %d", id0, id0, id1, id1, id0); query[1] = g_strdup_printf("NATURAL JOIN session WHERE " "((session.player_id0 = %d OR session.player_id1 = %d) " " AND " " (session.player_id0 = %d OR session.player_id1 = %d))" "AND matchstat.player_id = %d", id0, id0, id1, id1, id1); } IniStatcontext(psc); for (i = 0; i < 2; ++i) { buf = g_strdup_printf("SUM(total_moves)," "SUM(unforced_moves)," "SUM(total_cube_decisions)," "SUM(close_cube_decisions)," "SUM(doubles)," "SUM(takes)," "SUM(passes)," "SUM(very_bad_moves)," "SUM(bad_moves)," "SUM(doubtful_moves)," "SUM(unmarked_moves)," "SUM(very_unlucky_rolls)," "SUM(unlucky_rolls)," "SUM(unmarked_rolls)," "SUM(lucky_rolls)," "SUM(very_lucky_rolls)," "SUM(missed_doubles_below_cp)," "SUM(missed_doubles_above_cp)," "SUM(wrong_doubles_below_dp)," "SUM(wrong_doubles_above_tg)," "SUM(wrong_takes)," "SUM(wrong_passes)," "SUM(chequer_error_total_normalised)," "SUM(error_missed_doubles_below_cp_normalised)," "SUM(error_missed_doubles_above_cp_normalised)," "SUM(error_wrong_doubles_below_dp_normalised)," "SUM(error_wrong_doubles_above_tg_normalised)," "SUM(error_wrong_takes_normalised)," "SUM(error_wrong_passes_normalised)," "SUM(luck_total_normalised)" "from matchstat " "%s", query[i]); rs = pdb->Select(buf); g_free(buf); if ((!rs) || !strtol(rs->data[1][0], NULL, 0)) return NULL; psc->anTotalMoves[i] = strtol(rs->data[1][0], NULL, 0); psc->anUnforcedMoves[i] = strtol(rs->data[1][1], NULL, 0); psc->anTotalCube[i] = strtol(rs->data[1][2], NULL, 0); psc->anCloseCube[i] = strtol(rs->data[1][3], NULL, 0); psc->anDouble[i] = strtol(rs->data[1][4], NULL, 0); psc->anTake[i] = strtol(rs->data[1][5], NULL, 0); psc->anPass[i] = strtol(rs->data[1][6], NULL, 0); psc->anMoves[i][SKILL_VERYBAD] = strtol(rs->data[1][7], NULL, 0); psc->anMoves[i][SKILL_BAD] = strtol(rs->data[1][8], NULL, 0); psc->anMoves[i][SKILL_DOUBTFUL] = strtol(rs->data[1][9], NULL, 0); psc->anMoves[i][SKILL_NONE] = strtol(rs->data[1][10], NULL, 0); psc->anLuck[i][LUCK_VERYBAD] = strtol(rs->data[1][11], NULL, 0); psc->anLuck[i][LUCK_BAD] = strtol(rs->data[1][12], NULL, 0); psc->anLuck[i][LUCK_NONE] = strtol(rs->data[1][13], NULL, 0); psc->anLuck[i][LUCK_GOOD] = strtol(rs->data[1][14], NULL, 0); psc->anLuck[i][LUCK_VERYGOOD] = strtol(rs->data[1][15], NULL, 0); psc->anCubeMissedDoubleDP[i] = strtol(rs->data[1][16], NULL, 0); psc->anCubeMissedDoubleTG[i] = strtol(rs->data[1][17], NULL, 0); psc->anCubeWrongDoubleDP[i] = strtol(rs->data[1][18], NULL, 0); psc->anCubeWrongDoubleTG[i] = strtol(rs->data[1][19], NULL, 0); psc->anCubeWrongTake[i] = strtol(rs->data[1][20], NULL, 0); psc->anCubeWrongPass[i] = strtol(rs->data[1][21], NULL, 0); psc->arErrorCheckerplay[i][0] = (float)g_ascii_strtod(rs->data[1][22], NULL); psc->arErrorMissedDoubleDP[i][0] = (float)g_ascii_strtod(rs->data[1][23], NULL); psc->arErrorMissedDoubleTG[i][0] = (float)g_ascii_strtod(rs->data[1][24], NULL); psc->arErrorWrongDoubleDP[i][0] = (float)g_ascii_strtod(rs->data[1][25], NULL); psc->arErrorWrongDoubleTG[i][0] = (float)g_ascii_strtod(rs->data[1][26], NULL); psc->arErrorWrongTake[i][0] = (float)g_ascii_strtod(rs->data[1][27], NULL); psc->arErrorWrongPass[i][0] = (float)g_ascii_strtod(rs->data[1][28], NULL); psc->arLuck[i][0] = (float)g_ascii_strtod(rs->data[1][29], NULL); FreeRowset(rs); } psc->fMoves = 1; psc->fCube = 1; psc->fDice = 1; return psc; }
static void ExportGameText(FILE * pf, listOLD * plGame, const int iGame, const int fLastGame) { listOLD *pl; moverecord *pmr; matchstate msExport; matchstate msOrig; int iMove = 0; statcontext *psc = NULL; static statcontext scTotal; xmovegameinfo *pmgi = NULL; GString *gsz; listOLD *pl_hint = NULL; statcontext *psc_rel; msOrig.nMatchTo = 0; if (!iGame) IniStatcontext(&scTotal); updateStatisticsGame(plGame); if (game_is_last(plGame)) pl_hint = game_add_pmr_hint(plGame); for (pl = plGame->plNext; pl != plGame; pl = pl->plNext) { pmr = pl->p; FixMatchState(&msExport, pmr); switch (pmr->mt) { case MOVE_GAMEINFO: ApplyMoveRecord(&msExport, plGame, pmr); gsz = g_string_new(NULL); TextPrologue(gsz, &msExport, iGame); fputs(gsz->str, pf); g_string_free(gsz, TRUE); if (exsExport.fIncludeMatchInfo) TextMatchInfo(pf, &mi); msOrig = msExport; pmgi = &pmr->g; psc = &pmr->g.sc; AddStatcontext(psc, &scTotal); /* FIXME: game introduction */ break; case MOVE_NORMAL: if (pmr->fPlayer != msExport.fMove) { SwapSides(msExport.anBoard); msExport.fMove = pmr->fPlayer; } msExport.fTurn = msExport.fMove = pmr->fPlayer; msExport.anDice[0] = pmr->anDice[0]; msExport.anDice[1] = pmr->anDice[1]; gsz = g_string_new(NULL); TextBoardHeader(gsz, &msExport, iGame, iMove); fputs(gsz->str, pf); g_string_free(gsz, TRUE); printTextBoard(pf, &msExport); gsz = g_string_new(NULL); TextAnalysis(gsz, &msExport, pmr); fputs(gsz->str, pf); g_string_free(gsz, TRUE); iMove++; break; case MOVE_DOUBLE: case MOVE_TAKE: case MOVE_DROP: gsz = g_string_new(NULL); TextBoardHeader(gsz, &msExport, iGame, iMove); fputs(gsz->str, pf); g_string_free(gsz, TRUE); printTextBoard(pf, &msExport); gsz = g_string_new(NULL); TextAnalysis(gsz, &msExport, pmr); fputs(gsz->str, pf); g_string_free(gsz, TRUE); iMove++; break; default: break; } if (exsExport.fIncludeAnnotation) TextPrintComment(pf, pmr); ApplyMoveRecord(&msExport, plGame, pmr); } if (pl_hint) game_remove_pmr_hint(pl_hint); if (pmgi && pmgi->fWinner != -1) { /* print game result */ fprintf(pf, ngettext("%s wins %d point", "%s wins %d points", pmgi->nPoints), ap[pmgi->fWinner].szName, pmgi->nPoints); } if (psc) { gsz = g_string_new(NULL); g_string_append_printf(gsz, _("\n\nGame statistics for game %d\n\n"), iGame + 1); TextDumpStatcontext(gsz, psc, msOrig.nMatchTo); fputs(gsz->str, pf); g_string_free(gsz, TRUE); } if (fLastGame) { gsz = g_string_new(NULL); if (msOrig.nMatchTo) g_string_append_printf(gsz, _("Match statistics\n\n")); else g_string_append_printf(gsz, _("Session statistics\n\n")); TextDumpStatcontext(gsz, &scTotal, msOrig.nMatchTo); psc_rel = relational_player_stats_get(ap[0].szName, ap[1].szName); if (psc_rel) { g_string_append_printf(gsz, _("\nStatistics from database\n\n")); TextDumpStatcontext(gsz, psc_rel, 0); g_free(psc_rel); } fputs(gsz->str, pf); g_string_free(gsz, TRUE); } TextEpilogue(pf, &msExport); }