Place dans un classement et rang parmi des enregistrements MySQL
Si vous voulez réaliser un Top 1000 pour votre jeu en ligne ou plus généralement connaitre quelle est la place d’un de vos tuple dans un ensemble trié d’enregistrements, voici une petite astuce qui vous permettra d’obtenir le résultat avec un moyen 100 % SQL ( pas besoin de variable compteur coté serveur).
Imaginez une table players contenant les colonnes “pseudo, score et time_played”. Notre objectif est de connaitre la position d’un joueur dans le classement total connaissant le champ “pseudo”. L’obtention de son rang va se faire en 3 temps :
1. On va commencer par initialiser une variable MySQL avec la commande SET:
SET @counter = 0;
2. L’étape suivante consiste à effectuer une première requête qui va compter et créer une colonne indiquant le rang de chacun des enregistrements au sein de la table.
SELECT pseudo,score,time_played,@counter:=@counter+1 AS rang FROM players ORDER BY score ASC;
3. Enfin, nous allons isoler l’enregistrement qui nous intéresse, à savoir, celui dont la valeur pseudo est celle que nous cherchons.
Il s’agit d’une simple requête du type
SELECT place,pseudo FROM (*****) AS subrequest WHERE pseudo = ‘John Doe’;
Si vous avez suivi, vous aurez d’ores et déja compris qu’il va falloir remplacer les ***** par notre requête construite à l’étape 2 (il s’agit de ce qu’on appelle une sous- requete). Le résultat obtenu devrait être une table contenant le rang et le pseudonyme de notre joueur ‘John Doe’.
N’hésitez pas à envoyer un commentaire si vous avez besoin d’aide !
Références :
Documentation MySQL
Add comment juin 4, 2009
Iphone simulator’s mess : get your AVFoundation audio and video working !
I got yesterday an error when playing a wav or mp sound within the Iphone simulator. My code and everything was right, but the console displayed an error about a quicktime library.
Error loading /Library/QuickTime/DivX Decoder.component/Contents/MacOS/DivX Decoder: dlopen(/Library/QuickTime/DivX Decoder.component/Contents/MacOS/DivX Decoder, 262): Symbol not found: _SCDynamicStoreCopyConsoleUser
Referenced from: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.1.sdk/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
My configuration is Macbook under Mac OS 10.5 + iphone SDK 2.2.1.
How to solve this issue ?
If you have the same kind of message, it means (as far as i understand) your iphone simulator is looking for a codec on your shared library, and found one suiting for the playing of your file, but which is not linked to your simulator.
The best way i found was to uninsall with the “DivX uninstaller” program.
If you don’t have any “DivX uninstaller”, you can either:
1. Reinstall divx codecs from quicktime thirdparty code download center, and then uninstall the library using this program
or
2. Become root and type some rm -rf on the directory of the evil codec (something like /Library/QuickTime/DivX)
I’m now able to play wav files without any problem.Mp3 and m4v should be OK too.
Add comment avril 7, 2009
Animated transition between tabbar’s view on Iphone
Since last week, I’ve been attending a fantastic training course for Iphone developpement delivered by Geppy Parziale from Invasive Code.
I meet great people there, but training is now finished, and I’m on my own to develop some fresh apps!
I’ve been playing around with the Iphone SDK for the last few days. If you like “transitions” perhaps you tried to add an animation to the tab bar view. Nice transitions provide the tabbar’s item a fluent navigation. WARNING : Although i found nothing explicitely dismissing tabbar animation, it seems Apple discouraged programmers to animate tabbars view switching. Please leave a comment if you found information from Apple on this subject!
Anyway, it’s a good exercise to implement view transition to a TabBar controller. This article requires you to know how to implement the ViewController paradigm. I will not cover basic subjects like creating project, interface building, or any other ViewController related questions. If you don’t know about this, I would suggest you to attend to training courses or read some Cocoa Touch tutorials, books, and materials to be familiar with project designing.
I. Prepare your view and controller
If you are familiar with Iphone and Cocoa developpement, you probably noticed how Apple is using the delegation pattern. The project we are going to build here will follow this delegation chain:
Main application –> TabBarAppDelegate –> ViewSwitcher TabbarDelegate
To implement that, the TabBarDelegate is using the UIApplicationDelegate. The ViewSwitcherTabbarDelegate use the UITabBarController Delegate.
Create 2 or 3 viewController class, design their interface, and link them to the UITabbar’s items. Declare your UITabBarController and name it tabBarController in your application delegate .h file. When ready, just open the implementation of your TabBarAppDelegate and modify the applicationDidFinishLaunching: method as this:
-(void)applicationDidFinishLaunching:(UIApplication *)app {
tabBarController.delegate = [[ViewSwitcherTabbarDelegate alloc]init];
[window addSubview:[tabBarController view]]:
[window makeKeyAndVisible]:
}
Don’t forget to release the ViewSwitcherTabbarDelegate and the tabBarController in your dealloc method of the application Delegate.
Let’s talk about what we have done:
The first line of code declares we are using another class to enhance our tabBarController behaviour.
The second line is defining the first view which is appearing when bringing our tabBarController to the screen.
The third line make our window active on the screen.
II. create your animation
Jump to the ViewSwitcherTabbarDelegate implementation file. You need to implements 2 methods to get your delegate working:
These function are
- tabBarController:didEndCustomizingViewControllers:changed:
- tabBarController:didSelectViewController:
The method we are looking for is tabBarController:didSelectViewController:, because this method will be fired when the tabBarController is switching between his views.
Here is an example of the implementation of this method to animate the transition :
-(void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController)viewController{
// prepare your transition
CATransition *transition;
transition = [CATransition animation];
transition.type = yourtypeoftransition
transition.duration = yourduration …
// prepare your view switching
[[[ViewController view]layer]addAnimation:transition forKey:nil];
}
When building and runnig, you should now see the transition between the view, using your animation parameters. Enjoy !
6 comments avril 6, 2009
Validation xhtml strict : textes rayés et _target…
Strike !
J’avais l’habitude d’utiliser les balises <strike> et </strike> pour rayer une ligne de texte en HTML, . Seulement ces balises sont dépréciées et feront sauter votre validation xhtml strict!
La solution que je préconise pour barrer du texte en HTML est d’utiliser l’équivalent CSS.
Il suffit par exemple de créer une classe “strike”, et de créer un span portant cet attribut de classe pour rayer un texte.
Exemple :
En CSS :
.strike {
text-decoration: line-through;
}
En xHTML :
<p>Ceci est un mot <span class=’strike’>rayé </span></p>
Target !
Autre écueil du passage au xhtml strict: l’utilisation de l’attribut “target=_blank” pour ouvrir un lien dans un nouvel onglet ou une nouvelle fenetre.
L’attribut n’est plus valide xhtml strict, il faut aors utiliser javascript et remplacer l’attribut par :
onclick=“window.open(this.href); return false;”
Add comment mars 24, 2009
Playing with the shell history on Unix-ish systems
When using the shell on a server, you could type command revealing secrets on your root password or on your server organisation. For instance: just imagine your return keypress has not been working while becoming root, and your “su” password would be written without security asterisk and save in the history…)…
Moreover, it’s sometimes useful to scan your entire history when playing around with your shell.
So you juste have to learn the some shell history tricks command.
How to list the entire shell history ?
Just type “history “
How to clear the shell history ?
Just type “history -c“
How to avoid having twice the same command in the shell history ?
Just insert this in” ~/.bash_profile:”
export HISTCONTROL=ignoredups
Hope these few tricks could have been useful for you !
Add comment février 27, 2009
Sécuriser MySQL : création d’un utilisateur dédié à une base de donnée
Dans l’ensemble de cet article on supposera l’utilisateur MySQL root existant avec le mot de passe: rootPass
Etape 1 : Créer l’utilisateur
Connectez vous en root sur la table appelée “mysql”, et tapez la commandes suivantes.
INSERT INTO user(host,user,password) VALUES (’localhost’,'nom_user’,PASSWORD(’pass_user’));
Etape 2 : Créer la base de donnée
En root, il suffit d’entrer les commandes CREATE DATABASE nom_database;.
Pour générer les tables, que vous avez déjà probablement crée lors de la phase de développement, je vous conseille d’exporter la structure depuis le SGBD de dev, puis de l’insérer dans le SGBD de production en utilisant:
mysql -u root -prootPass nom_database <votrefichier.sql
Etape 3 : Attribuer les droits : insertion, suppression, et lecture sur l’ensemble de la base
L’attribution des droits s’effectue avec l’usage de la commane GRANT, comme suit:
GRANT SELECT, INSERT, UPDATE ON nom_database.* TO nom_user@’localhost’ ;
Validez l’attribution de ces droits par:
flush privileges;
Références
Add comment février 23, 2009
Vérifier la validité d’un email avec Java
Un jour ou l’autre, à travailler dans le WEB, opn finit par devoir vérifier la validité d’un email. Comme on ne peut pas faire confiance à Javascript ou Flash pour vérifier les données envoyées par le client, il faut impérativement vérifier la validité des adresse mail coté serveur (au pire, vous risquez l’injection SQL). Voivi quelques pistes pour vérifier ces emails sur un serveur J2EE, ou sur n’importe quel conteneur de servlet (Tomcat,Jetty, Glassfish).
La solution de facilité
Voici un moyen simple rapide et à priori efficace d’effectuer cette vérification, à l’aide de la libraire apache “commons-validator”:
public static boolean validateEmailAddress(String votreEmail){
EmailValidator emailValidator = EmailValidator.getInstance();
return emailValidator.isValid(votreEmail);
}
Le fichier jar est disponible à cet endroit: http://commons.apache.org/validator/. A noter que ls utilitaires de validation Apache permettent de valider également les dates, ou encore les numéros de carte bleue, que ce soit en java, ou en javascript!
Prendre le taureau par les cornes, et chercher a implémenter la RFC 2822
C’est une usine à gaz, mais ca a été fait, en listant l’ensemble des tld(top level domains: .com, .net .org, etc) existants. C’est ce qui est réalisé ici:
http://www.velocityreviews.com/forums/t125158-java-email-validator.html
Implémenter sa propre regex simplifiée
On peut également essayer de construire soi-même sa fonction, en écrivant sa regex et en comparant la chaine de caractère à cette expression régulière. Suivre strictement les recommandations de la RFC 2822 est un vrai casse-tête (comme on a pu le voir un peu plus haut), et n’est pas forcément utile car l’email bien que valide n’est peut être pas réellement attribué a une personne !
Je vous conseille donc d’utiliser une regex simple, éprouvée, et testée:
^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$
source: http://www.regular-expressions.info/email.html
Et voici l’implémentation correspondante:
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Console console = System.console();
if (console == null) {
System.err.println(”Probleme pour récupérer la console.”);
System.exit(1);
}
while (true) {
String a_tester = console.readLine(”Saisissez une adresse email à tester : “);
if(isEmailAdress(a_tester)) {
console.format(”OUI”);
}else{
console.format(”NON”);
}
}
}
public static boolean isEmailAdress(String email){
Pattern p = Pattern.compile(”^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$”);
Matcher m = p.matcher(email.toUpperCase());
return m.matches();
}
}
Attention au caractère d’échappement (doublé dans la syntaxe Java) pour la déclaration du “.” dans la seconde partie de l’email!
Add comment février 18, 2009
Récupérer l’id (autoincrement) après un insert
Fiche recette du 12 février 2009:
Comment récupérér la valeur d’un champ déclaré “auto_increment” lors d’un INSERT INTO exécuté depuis Java ?
L’API JDBC fournit une méthode extrèmement pratique appelée getGeneratedKeys():
PreparedStatement stat = connectionSql.prepareStatement("INSERT INTO maTable SET " +
"login = ?," +
"email = ?");
int i=1;
stat.setString(i++, leLogin);
stat.setString(i++, leMail);
int nb_lignes = stat.executeUpdate();
ResultSet rs = stat.getGeneratedKeys();
int idAuto_increment = 0;
if( rs.next() ) {
idAuto_increment = rs.getInt(1);
}
Un enchainement de méthodes très certainement utile à connaitre… et que je recherche à chaque fois que je travaille avec MySql et son connecteur Java…
Add comment février 12, 2009
Correspondance entre types primitifs JAVA et types MySQL
Un post pour sythétiser les possibilité de stockages d’un objet java sous forme “éclatée” dans une base de donnée MySQL:
| Type Java | Type MySQL | Valeur Max |
|---|---|---|
boolean |
tinyINT (1) |
De -128 à 127, ou 0 à 255 (unsigned) |
int |
SMALLINT |
-32768 à 32767, ou 0 à 65535 |
int |
MEDIUMINT |
-8 388 608 à 8 388 607, ou 0 à 16 777 215 |
int |
INT |
-2 147 483 648 à 2 147 483 647, ou 4 294 967 295 |
long |
BIGINT |
-9223372036854775808 à -9223372036854775807, ou 256 ^ 8 |
String |
CHAR(N) |
N caractères maximum |
String |
VARCHAR(N) |
255 caractères maximum |
* pour les chaines de caractères le programmeur doit choisir entre optimiser l’espace disque (varchar) ou optiomiser la vitesse d’éxécution, en choississant un type CHAR dont la taille est prédéterminée et remplie par des espaces.
Quelques commentaires
Que se passe-t-il en cas de dépassement ?
Un warning sera levé par mysql, et le nombre sera tronqué à sa valeur max.
Les dépassements de capacité entraînant des troncatures sont affichés comme des alertes (“warnings”) lors de l’utilisation des commandes ALTER TABLE, LOAD DATA INFILE, UPDATE, et les insertions INSERT multiples.
Comment calculer la valeur max en fonction du nombre d’octet alloués au stockage ?
La valeur max stockée dans un octet est 256 (soit 2^8).
4 octets donnent donc 256 ^ 4 possibilités, soit 4 294 967 296 (taille du INT), en entier non signé -cela signifie pas de nombre négatifs .
Références:
Add comment février 10, 2009
Protéger l’accès à une servlet (ou une page sans PHP) pour utiliser Rentabiliweb
Rentabiliweb est un service de moétisation des pages web.
Dans le cadre de la réalisation d’un serveur de mini-jeux payant écrit en Java, j’ai décidé d’utiliser le service rentabiliweb.
1. Le fonctionnement des opérateurs de micropaiement
Le principe technique est simple: l’url désirée doit être inconnue du public, mais connue de rentabiliweb. Lors de la tentative de paiement de l’utilisateur sur le serveur rentabiliweb, le service effectue une redirection vers la page protégée.
Mais que se passe-t-il si l’URL de la page secrète venait à être connue de tous ?
Il est donc nécessaire protéger la page, en utilisant les données secrètes envoyées par Rentabiliweb.
2. Les paramètres a utiliser pour protéger la page :
La page protégée doit récupérer une validation émanant de Rentabiliweb. Il faut effectuer une requête sur le serveur http://secure.rentabiliweb.com/Micropaiement.php qui nous renverra TRUE, ou FALSE selon la validité du code de paiement entré par l’utilisateur.
Le reste des infos de la query string (paramètres HTTP) est ici:
id=XXXXX (correspond à l’identifiant de votre page protégée)
&code=test (correspond au code qui a été saisi par l’utilisateur)
&submit.x=3(correspond aux coordonnées lors du clic sur l’image du formulaire)
&submit.y=5(correspond aux coordonnées lors du clic sur l’image du formulaire)
&submit=ok
La page protégée doit ensuite à son tour émettre une requete get vers un serveur de rentabiliweb, qui va répondre par “oui” ou “non”. A vous ensuite d’analyser ce résultat…Divers moyens existent. Pour ma part, j’ai choisi d’utiliser l’API java et le package java.net pour emettre une requête GET sur leur serveur. Il serait aussi possible d’utiliser conjointement PHP pour modifier la base de donnée, ou encore un script shell lancé par le runtime du conteneur de servlet…
Il est a noter que leur serveur supporte les cookies (pratique si vous avez un identifiant de session) et tranfère les paramètres HTTP de la queryString que vous lui donnerez. Apparement rentabiliweb effectue une simple redirection HTTP standard vers la page déclaré par l’administrateur.
Add comment février 4, 2009