IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Générer des statistiques à partir de tables MySQL


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut Générer des statistiques à partir de tables MySQL
    bonjour,
    j'ai une table mysql qui regroupe les noms du personnel avec les taches exécutées.
    j'aimerais afficher des statistiques avec graphiques qui indique pour chaqur personne le nombre de taches qu'elle a exécutée.
    y'aurait il pas un script en php qui pourrait faire ceci?
    Merci.

  2. #2
    Membre éclairé
    Inscrit en
    Juillet 2003
    Messages
    625
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 625
    Points : 673
    Points
    673

  3. #3
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut
    le code du tuto me génère une page blanche. j'ai bien entendu fait attention à ttes mes variables et à la récuoération de ma table à partir de la requete SQL

  4. #4
    Expert éminent sénior

    Avatar de FirePrawn
    Homme Profil pro
    Consultant technique
    Inscrit en
    Mars 2011
    Messages
    3 179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique

    Informations forums :
    Inscription : Mars 2011
    Messages : 3 179
    Points : 19 373
    Points
    19 373
    Par défaut
    Citation Envoyé par sirina88 Voir le message
    le code du tuto me génère une page blanche. j'ai bien entendu fait attention à ttes mes variables et à la récuoération de ma table à partir de la requete SQL
    Si tu ne montres pas ton code, on ne risque pas de t'aider...

  5. #5
    Expert confirmé
    Avatar de Thes32
    Homme Profil pro
    Développeur PHP, .Net, T-SQL
    Inscrit en
    Décembre 2006
    Messages
    2 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur PHP, .Net, T-SQL

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 379
    Points : 4 853
    Points
    4 853
    Par défaut
    Citation Envoyé par sirina88 Voir le message
    le code du tuto me génère une page blanche. j'ai bien entendu fait attention à ttes mes variables et à la récuoération de ma table à partir de la requete SQL
    Tu as bien activer le rapport d'erreurs PHP ?

  6. #6
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par Thes32 Voir le message
    Tu as bien activer le rapport d'erreurs PHP ?
    comment je l'active?

  7. #7
    Expert éminent sénior

    Avatar de FirePrawn
    Homme Profil pro
    Consultant technique
    Inscrit en
    Mars 2011
    Messages
    3 179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique

    Informations forums :
    Inscription : Mars 2011
    Messages : 3 179
    Points : 19 373
    Points
    19 373
    Par défaut
    Tu peux éditer ton message et mettre ton code dans les balises prévues à cet effet histoire que ce soit lisible ?

  8. #8
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par Thes32 Voir le message
    Tu as bien activer le rapport d'erreurs PHP ?
    Il est activé oui !

  9. #9
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par FirePrawn Voir le message
    Tu peux éditer ton message et mettre ton code dans les balises prévues à cet effet histoire que ce soit lisible ?
    ok j'ai cru les avoir utilisés!
    voila alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
     
    <?php
     
    mysql_connect('localhost','root');
    Mysql_select_db('information');
    mysql_select_db("member");
    $query="SELECT MONTH( ddemande ) AS mois, emplacement, COUNT( * ) AS nbwo
    FROM member
    WHERE type_noeud ='msc'
    GROUP BY mois, emplacement
    ORDER BY mois ASC ";
    if(!mysql_query($query))
    echo mysql_error();
     
    $i=0;
    $element=array();
    $js=array();
    while($row=mysql_fetch_object($query))
    {
    //Prendre la premiere quantite vendue comme le minimum et maximum
    //Mettre les noms de produit et les mois de ventes dans des tableaux
    if($i==0)
    {
    $min=$row->nbwo;
    $max=$row->nbwo;
    array_push($element, $row->emplacement);
    array_push($js, $row->mois);
    }
    //Inserer le nom de produit dans le tableau s'il n'est pas encore enregistrer
    if(!in_array($row->emplacement,$element))
    {
    array_push($element, $row->emplacement);
    }
    //Inserer le mois de vente dans le tableau s'il n'est pas encore enregistrer
    if(!in_array($row->mois,$js))
    {
    array_push($js, $row->mois);
    }
     
    if($row->nbwo < $min)
    {
    $min=$row->nbwo;
    }
    else
    {
    if($row->nbwo > $max)
    {$max=$row->nbwo;}
    }
    $i++;
    }
    //Mettre les mois en Francais dans un tableau
    $moisFr=array('Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Decembre');
     
    //type mime de l'image
    header('Content-type: image/png');
    //Chemin vers le police à utiliser
    $font_file = './arial.ttf';
    //Adapter la largeur de l'image par rapport au nombre de ligne et nombre de mois
    $largeur=$i*20+(count($js)*10)+100;
    $hauteur=400;
    $absis=80;
    $courbe=imagecreatetruecolor($largeur, $hauteur);
    //Générer un tableau de couleurs
    $couleur=array();
    $red=0;
    $blue=0;
    $green=0;
    for($n=0;$n<count($element);$n++)
    {
    $x = $n%3;
    switch ($x){
    case(0):
    $red+=85;
    break;
    case(1):
    $blue+=85;
    break;
    case(2):
    $green+=85;
    break;
    }
    $couleur[$n]=imagecolorallocate($courbe, $red,$green , $blue);
    }
    //Les autre couleurs utils
    $ligne=imagecolorallocate($courbe, 220, 220, 220);
    $fond=imagecolorallocate($courbe, 250, 250, 250);
    $noir=imagecolorallocate($courbe, 0, 0, 0);
    $blanc=imagecolorallocate($courbe, 255, 255, 255);
    $rouge=imagecolorallocate($courbe, 255, 0, 0);
    //Colorer le fond
    imagefilledrectangle($courbe,0 , 0, $largeur, $hauteur, $fond);
    //Tracer l'abscisse et l'ordonnée
    imageline($courbe, 50, $hauteur-$absis, $largeur-10,$hauteur-$absis, $noir);
    imageline($courbe, 50,$hauteur-$absis,50,20, $noir);
    if($min!=0)
    {
    $absis+=30;
    $a=30;
    }
    $nbOrdonne=10;
    //Calculer les échelles suivants les abscisses et ordonnées
    $echelleX=($largeur-90-((count($js)*10)))/$i;
    $echelleY=($hauteur-$absis-20)/$nbOrdonne;
    $i=$min;
    $py=($max-$min)/$nbOrdonne;
    $pasY=$absis;
    //Tracer les grides
    while($pasY<($hauteur-19))
    {
    imagestring($courbe, 2,10 , $hauteur-$pasY-6, round($i), $noir);
    imageline($courbe, 50, $hauteur-$pasY, $largeur-20,$hauteur-$pasY, $ligne);
    $pasY+=$echelleY;
    $i+=$py;
    }
    $pasX=60;
    mysql_data_seek($query, 0);
    $mois=0;
    while($row=mysql_fetch_object($query))
    {
    if($mois<($row->mois))
    {
    //Ecrire le mois en Français en abscisse
    imagestring($courbe, 2, $pasX,$hauteur-$absis+32 , $moisFr[$row->mois-1], $noir);
    //Décaller 10 px du mois précédent
    $pasX+=10;
    }
    //Calculer la hauteur de la rectangle
    $y=($hauteur) -(($row->nbwo -$min) * ($echelleY/$py))-$absis;
    //Prendre la couleur correspondante au produit
    $clr=$couleur[array_search($row->emplacement, $element)];
    //Dessiner le rectangle
    imagefilledrectangle($courbe,$pasX-10 , $hauteur-$absis+$a, $pasX+10, $y, $clr);
    //Ecrire la valeur en verticale
    imagefttext($courbe, 10, 270, $pasX-3, $y+5, $blanc, $font_file, $row->nbwo);
    //Decaller le prochain rectangle
    $pasX+=$echelleX;
    $mois=$row->mois;
    }
    //La legende
    $pasX=50;
    //Hauteur de la premiere
    $pasY=$hauteur-$absis+47;
    foreach ($element as $index=>$libelle)
    {
    if(($index % 4)==3)
    {
    $pasX+=120;
    $pasY=$hauteur-$absis+47;
    }
    //Le nom du poduit avec sa couleur
    imagestring($courbe, 2, $pasX,$pasY , $libelle, $couleur[$index]);
    //Un petit rectangle 
    imagefilledrectangle($courbe,$pasX+80 , $pasY, $pasX+100, $pasY+12, $couleur[$index]);
    $pasY+=20;
    }
    imagepng($courbe,$file_img_bar);
    return $file_img_bar;
    ?>

  10. #10
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut
    en fait j'ai essayé avec des codes que j'ai trouvé directement sur des sites et ça m'affiche tjs une page blanche ! comme celui là par exp sur le site de cours PHP

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    <?php
    // on définit un tableau contenant le nombre de page vues par mois : par exemple, on suppose que 1500 pages du site ont été vues en janvier, 2450 en février, etc... Bien sur, pour que ce script soit vraiment valides, vous n'allez pas déclarer ce tableau, car sinon, les bâtons seront toujours les mêmes :) Vous allez plutôt effectuer une requête SQL sur votre base de données permettant de récupérer le nombre de pages vues de votre site par mois. Ensuite, il suffira d'appeler le script avec ces 12 paramètres dans votre page html (en faisant par exemple : <img src="./images/stats_year.php?visite_par_mois[1]=1500.......">)
    $visite_par_mois[1]=1500;
    $visite_par_mois[2]=2450;
    $visite_par_mois[3]=800;
    $visite_par_mois[4]=1780;
    $visite_par_mois[5]=1900;
    $visite_par_mois[6]=2450;
    $visite_par_mois[7]=1684;
    $visite_par_mois[8]=1845;
    $visite_par_mois[9]=3450;
    $visite_par_mois[10]=980;
    $visite_par_mois[11]=1234;
    $visite_par_mois[12]=500;
     
    // on calcule le nombre de pages vues sur l'année
    $max_visite = max($visite_par_mois);
     
    // on spécifie le type d'image que l'on va créer, ici ce sera une image au format PNG
    header ("Content-type: image/png");
     
    // on définit la largeur et la hauteur de notre image
    $largeur = 550;
    $hauteur = 300;
     
    // on crée une ressource pour notre image qui aura comme largeur $largeur et $hauteur comme hauteur (on place également un or die si la création se passait mal afin d'avoir un petit message d'alerte)
    $im = @ImageCreate ($largeur, $hauteur) or die ("Erreur lors de la création de l'image");
     
    // on place tout d'abord la couleur blanche dans notre table des couleurs (je vous rappelle donc que le blanc sera notre couleur de fond pour cette image).
    $blanc = ImageColorAllocate ($im, 255, 255, 255);
     
    // on place aussi le noir dans notre palette, ainsi qu'un bleu foncé et un bleu clair
    $noir = ImageColorAllocate ($im, 0, 0, 0);
    $bleu_fonce = ImageColorAllocate ($im, 75, 130, 195);
    $bleu_clair = ImageColorAllocate ($im, 95, 160, 240);
     
     
    // on dessine un trait horizontal pour représenter l'axe du temps
    ImageLine ($im, 20, $hauteur-40, $largeur-15, $hauteur-40, $noir);
     
    // on affiche le numéro des 12 mois
    for ($i=1; $i<=12; $i++) {
    	if ($i==1) {
    		ImageString ($im, 2, 42, $hauteur-38, $i, $noir);
    	}
    	else {
    		ImageString ($im, 2, ($i)*42, $hauteur-38, $i, $noir);
    	}
    }
     
    // on dessine un trait vertical pour représenter le nombre de pages vues
    ImageLine ($im, 20, 30, 20, $hauteur-40, $noir);
     
    // on affiche les legendes sur les deux axes ainsi que différents textes (note : pour que le script trouve la police verdana, vous devrez placer la police verdana dans un repertoire /fonts/)
    imagettftext($im, 14, 0, $largeur-70, $hauteur-10, $noir, "./fonts/verdana.ttf", "Mois");
    imagettftext($im, 14, 0, 10, 20, $noir, "./fonts/verdana.ttf", "Nb. de pages vues");
    imagettftext($im, 14, 0, $largeur-250, 20, $noir, "./fonts/verdana.ttf", "Statistiques pour l'année 2003");
     
    // on parcourt les douze mois de l'année
    for ($mois=1; $mois <= 12; $mois++) {
    	if ($visite_par_mois[$mois]!="0") {
    		// on calcule la hauteur du baton
    		$hauteurImageRectangle = ceil(((($visite_par_mois[$mois])*($hauteur-50))/$max_visite));
    		if ($mois=="1") {
    			// si le mois est janvier, on affiche notre premier baton
    			// on affiche le premier baton noir
    			ImageFilledRectangle ($im, 42, $hauteur-$hauteurImageRectangle, 42+14, $hauteur-41, $noir);
    			// on affiche le second baton, bleu foncé, qui sera un peu plus petit que le noir afin de recouvrir une partie du noir
    			ImageFilledRectangle ($im, 44, $hauteur-$hauteurImageRectangle+2, 42+12, $hauteur-41-1, $bleu_fonce);
    			// on affiche le dernier baton, bleu clair, qui sera un peu plus petit que le bleu foncé afin de recouvrir une partie du bleu foncé (on obtiendra ainsi un effet de dégradé)
    			ImageFilledRectangle ($im, 48, $hauteur-$hauteurImageRectangle+2, 42+8, $hauteur-41-1, $bleu_clair);
    		}
    		else {
    			// si le mois est different de janvier, on affiche les autres batons
    			ImageFilledRectangle ($im, ($mois)*42, $hauteur-$hauteurImageRectangle, ($mois)*42+14, $hauteur-41, $noir);
    			ImageFilledRectangle ($im, ($mois)*42+2, $hauteur-$hauteurImageRectangle+2, ($mois)*42+12, $hauteur-41-1, $bleu_fonce);
    			ImageFilledRectangle ($im, ($mois)*42+6, $hauteur-$hauteurImageRectangle+2, ($mois)*42+8, $hauteur-41-1, $bleu_clair);
    		}
    	}
    }
     
    // on dessine le tout
    Imagepng ($im);
    ?>

  11. #11
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    connais la méthode de recherche par dichotomie ?
    La dichotomie (« couper en deux » en grec) est, en algorithmique, un processus itératif ou récursif de recherche où, à chaque étape, on coupe en deux parties (pas forcément égales) un espace de recherche qui devient restreint à l'une de ces deux parties.

    On suppose bien sûr qu'il existe un test relativement simple permettant à chaque étape de déterminer l'une des deux parties dans laquelle se trouve une solution. Pour optimiser le nombre d'itérations nécessaires, on s'arrangera pour choisir à chaque étape deux parties sensiblement de la même « taille » (pour un concept de « taille » approprié au problème), le nombre total d'itérations nécessaires à la complétion de l'algorithme étant alors logarithmique en la taille totale du problème initial. [...] (source : wikipedia)
    1/ Je l'ai appliqué à ton exemple :
    -> on enlève des bouts de code, et on teste jusqu'à voir où apparait/disparait l'erreur.
    Et j'ai rapidement ciblé le problème sur ces lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // on affiche les legendes sur les deux axes ainsi que différents textes (note : pour que le script trouve la police verdana, vous devrez placer la police verdana dans un repertoire /fonts/)
    imagettftext($im, 14, 0, $largeur-70, $hauteur-10, $noir, "./fonts/verdana.ttf", "Mois");
    imagettftext($im, 14, 0, 10, 20, $noir, "./fonts/verdana.ttf", "Nb. de pages vues");
    imagettftext($im, 14, 0, $largeur-250, 20, $noir, "./fonts/verdana.ttf", "Statistiques pour l'année 2003");
    On remarque qu'il fait appel à une police : "./fonts/verdana.ttf"
    En ajoutant le fichier "verdana.ttf" dans le dossier "fonts" : miracle, ca fonctionne !

    Ton code perso est plus abstrait, (donc moins facile à tester) mais j'ai vu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $font_file = './arial.ttf';
    Avec un peu de chance, le problème est le même ...

    2/ autre technique simple (adapté à ce problème en particulier) :
    j'ai "commenté" les lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //header ("Content-type: image/png");
     
    //Imagepng ($im);
    Du coup, les messages d'erreurs pourront s'afficher à l'écran.
    J'ai donc obtenu le message d'erreur :
    Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/ecuri2/public_html/_admin/test/test.php on line 55
    Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/ecuri2/public_html/_admin/test/test.php on line 56
    Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/ecuri2/public_html/_admin/test/test.php on line 57
    C'est une autre méthode efficace...
    Dernière modification par Invité ; 12/08/2011 à 12h03.

  12. #12
    Nouveau membre du Club
    Inscrit en
    Août 2011
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Août 2011
    Messages : 73
    Points : 37
    Points
    37
    Par défaut
    Citation Envoyé par jreaux62 Voir le message
    Bonjour,
    connais la méthode de recherche par dichotomie ?


    1/ Je l'ai appliqué à ton exemple :
    -> on enlève des bouts de code, et on teste jusqu'à voir où apparait/disparait l'erreur.
    Et j'ai rapidement ciblé le problème sur ces lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // on affiche les legendes sur les deux axes ainsi que différents textes (note : pour que le script trouve la police verdana, vous devrez placer la police verdana dans un repertoire /fonts/)
    imagettftext($im, 14, 0, $largeur-70, $hauteur-10, $noir, "./fonts/verdana.ttf", "Mois");
    imagettftext($im, 14, 0, 10, 20, $noir, "./fonts/verdana.ttf", "Nb. de pages vues");
    imagettftext($im, 14, 0, $largeur-250, 20, $noir, "./fonts/verdana.ttf", "Statistiques pour l'année 2003");
    On remarque qu'il fait appel à une police : "./fonts/verdana.ttf"
    En ajoutant le fichier "verdana.ttf" dans le dossier "fonts" : miracle, ca fonctionne !

    Ton code perso est plus abstrait, (donc moins facile à tester) mais j'ai vu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $font_file = './arial.ttf';
    Avec un peu de chance, le problème est le même ...

    2/ autre technique simple :
    j'ai "commenté" les lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //header ("Content-type: image/png");
     
    //Imagepng ($im);
    et obtenu le message d'erreur :

    C'est une autre méthode efficace...
    ça maaaaarche!! t'avais totalement raison! merci bcp

  13. #13
    Expert confirmé
    Avatar de Thes32
    Homme Profil pro
    Développeur PHP, .Net, T-SQL
    Inscrit en
    Décembre 2006
    Messages
    2 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur PHP, .Net, T-SQL

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 379
    Points : 4 853
    Points
    4 853
    Par défaut
    Citation Envoyé par jreaux62 Voir le message
    Bonjour,
    connais la méthode de recherche par dichotomie ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/12/2011, 04h53
  2. Réponses: 0
    Dernier message: 20/03/2011, 16h50
  3. Réponses: 2
    Dernier message: 22/11/2007, 09h27
  4. Réponses: 11
    Dernier message: 25/07/2006, 21h46
  5. Générer des statistiques avec graphiques, histogrammes
    Par nico33307 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 28/11/2005, 16h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo