-
Estrazione statistiche
Chiedo scusa per il titolo ma no trovo un modo semplice per sintetizzare la richiesta.
La situazione è questa.
Una competizione suddivisa in manche. Ogni manche composta da diverse prove.
Ogni prova, se superata, assegna un numero di punti.
Tutti questi dati sono registrati in una tabella in cui ogni rigo contiene il gareggiante, il numero della manche, la prova e i punti.
Ora il problema non è la classifica ma un dato statistico.
Mi occorre poter recuperare, per ognuno, la striscia positiva (quante manche consecutive vinte) tenendo presente che ci possono essere e ci sono casi di ex equo, e, se possibile anche la striscia massima (numero massimo di manche consecutive vinte).
Idee? Suggerimenti?
-
Cosa si intende per manche consecutive vinte? Allora ogni manche è suddivisa da x prove con y punteggi, ma se io perdo tutte le prove della prima manche avanzo ugualmente alla seconda manche?
-
Si. Si partecipa comunque.
Piuttosti che manche immagina delle vere e proprie partite indipendenti.
-
La domanda è tipo: dato un torneo di calcio, quante vittorie di seguito ha fatto ogni squadra e quale è il numero massimo di vittorie di fila?
-
Ancora non è chiaro.. Puoi fonire un esempio dei dati originali specificando se i punti sono totali (se passi la prova i punti vengono sommati)? Anche la tua domanda è confusa.. Se tu vuoi sapere quante manche consecutive sono state vinte ... Equivale a dire che si devono vincere tutte le prove per più di una manche... Discorso diverso se vuoi sapere chi è il primo di quella manche e della manche successiva (dato basato sui i punti totali di ogni manche e non per forza deve superare tutte le prove)
-
A scanso di equivoci: recuperare i dati dalla base di dati ed elaborarli con PHP è un'opzione, o è necessario che tutto avvenga tramite SQL?
-
Dunque, cerco di spiegare meglio la dinamica
Una competizione suddivisa in Manche (gare, tutte indipendenti, per cui tutti possono partecipare ad ogni manche).
Ogni manche prevede un certo numero di giochi (uno al giorno), sempre uguale, e per ogni gioco sono previsti dei punti (diversi da gioco a gioco).
Per cui per ogni manche si crea una classifica in base ai punti ottenuti (da 0 per gioco non valido al max previsto) e naturalmente ci possono essere più utenti "vincitori".
Ora se io vinco la manche 1, 2, 3 e poi la 5 e la 6 ma nella 4 sarò più indietro in classifica, io avrò, all'inizio della manche 7, come striscia attuale 2(*) (5 e 6) e come striscia max 3(**) (1, 2 e 3).
Ed è questi 2(*) e 3(**) che mi interessa trovare.
La tabella è strutturata così (dati di esempio)
Codice:
+-----------+--------+-------+-------+
| Giogatore | Manche | Giogo | Punti |
+-----------+--------+-------+-------+
| Utente 1 | 1 | A | 50 |
| Utente 2 | 1 | A | 40 |
| Utente 3 | 1 | A | 30 |
| Utente 1 | 1 | B | 40 |
| Utente 2 | 1 | B | 50 |
| Utente 3 | 1 | B | 30 |
| Utente 1 | 1 | C | 40 |
| Utente 2 | 1 | C | 40 |
| Utente 3 | 1 | C | 40 |
| Utente 1 | 2 | D | 50 |
| Utente 2 | 2 | D | 30 |
| Utente 3 | 2 | D | 40 |
| Utente 1 | 2 | E | 40 |
| Utente 2 | 2 | E | 30 |
| Utente 3 | 2 | E | 50 |
+-----------+--------+-------+-------+
non è strettamente necessario risolvere la cosa in SQL (anche se a me farebbe molto comodo).
Potrei cmq trattare i dati anche con PHP.
Non so se adesso la cosa è più chiara.
-
Mh, un'implementazione in PHP mi viene abbastanza naturale (sia n il numero di giocatrori, m il numero di manche disputate):
- costruisco la matrice M n x m tale che M[i ][j] = punteggio del giocatore i nella manche j (facile da ottenere con una singola query SQL, usando opportunamente SUM)
- trasformo M in una matrice booleana M' (sempre n x m) tale che M'[ i][j] = true sse il giocatore i ha vinto la manche j o, in termini più precisi: M'[ i][j] = \/0 <= k < n . M[ i][j] >= M[k][j], da notare che in questo modo vincitori a parimerito hanno tutti valore true
- trasformo M' in M'' (sempre n x m) tale che M''[ i][j] = serie di vittore consecutive del giocatore i alla fine della manche j; concretamente la relazione è data da (\/0 <= i < n):
- M''[ i][0] = M'[ i][0] ? 1 : 0
- M''[ i][j + 1] = M'[ i][j + 1] ? M''[ i][j] + 1 : 0
ogni riga può essere processata indipendentemente, per cui suggerirei l'uso di funzioni come array_map - alla fine, dato un giocatore i, la serie di vittorie consecutive per quel giocatore è data M''[ i][m-1], mentre la sua serie più lunga è data da max(M''[ i])
Volendo i passi 2 e 3 si possono unire in uno solo.
In SQL non mi è chiaro come ottenere lo stesso risultato...senza incasinare troppo l'interrogazione...
-
Proverò.
Non mi è chiaro però il punto 3.
Come fai a passare da M' a M''?
-
Vediamo... le righe possono essere processate indipendentemente, quindi prendiamo una riga di M', che riporta true o false se il giocatore ha vinto/perso ciascuna manche:
Codice PHP:
$row = [true, true, true, false, true, true, false];
questo vettore va trasformato in uno che riporti la serie di vittore consecutive al termine di ogni manche, quindi il risultato desiderato è:
Codice PHP:
$series = [1, 2, 3, 0, 1, 2, 0];
L'idea è di scorrere il vettore, incrementando di uno ogni volta che si incontra una vittoria, ed azzerando quando si incontra una sconfitta:
Codice PHP:
function compute_series(array $row) {
$series = array();
$series[0] = $row[0] ? 1 : 0;
for ($i = 1; $i < count($row); ++$i) {
if ($row[$i]) {
$series[$i] = $series[$i - 1] + 1;
} else {
$series[$i] = 0;
}
// For one-liners: $series[$i] = $row[$i] ? ($series[$i - 1] + 1) : 0;
}
return $series;
}
Se M' è rappresentata per righe, ad esempio:
Codice PHP:
$M_prime = [
'player1' => [true, true, false, ..., false],
'player2' => [false, false,true, ..., true],
...
'playerN' => [false, true, false, ..., false]
]
si può sfruttare l'indipendenza tra le righe ed usare array_map:
Codice PHP:
$M_second = array_map('compute_series', $M_prime);
Se l'occupazione in memoria è un problema (O(n * m)) sono quasi sicuro si possa trasformare in una versione con programmazione dinamica (O(n)).
-
Grazie.
Vedo cosa riesco a fare.
-
Se si possiede privilegi nel server MySQL è la stringa di tutti i Punti (non supera tot lunghezza) si poteva pensare a GROUP_CONCAT.. Cmq. Vogliamo ottere le manche consecutive, quindi dal momento che le Manche non sono uguali per tutti i giocatori e che la somma dei punti a zero non è di certo una vittoria.. La SQL è questa
Codice PHP:
SELECT Manche, SUM(Punti) tot, Giocatore FROM table GROUP BY Manche,Giocatore HAVING SUM(Manche) > 1 AND tot > 0;
Recupero solo chi a giocato più di una Manche e che abbia un punteggio maggiore a zero.. Ps. Per una statistica generale (grafico) occorre x Manche iniziale e y Manche finale mobili... Perché in alcuni casi potremmo avere dei vincitori di singole manche ma non di Manche consecutive.