Tablas de records on-line

Temas relacionados con la programación y la actualización audiovisual
User avatar
traperic
Usuario avanzado
Posts: 75
Joined: Sun Apr 10, 2005 3:06 pm
Contact:

Tablas de records on-line

Postby traperic » Sat Dec 24, 2005 12:41 pm

Hola, estoy intentando hacer la tabla de records on-line para Phantomas, y francamente, es un tema que nunca he tocado y no tengo ni idea de cómo hacerlo.

He hecho los cgis que deben controlar ingresar un record, mostrarlo y eso y funcionan bien, lo que ocurre es que no tengo ni idea de cómo mandar/recibir los datos entre el programa y el servidor.

Me he bajado el código fuente del F1 Spirit y he investigado un poco, he pasado a C la clase F1Shttp (un poco por encima para hacer pruebas) pero no sé ni cómo usarlo bien.

Popolon, si lees esto y me puedes echar una mano te lo agradecería, y si ya es un mini ejemplo, mucho más si cabe ;-).

Este es el código del programa que se encarga de ingresar un record, básicamente coge una cadena con el nombre, el lugar y los puntos en la forma http://xxx.yyy.zzz/este_cgi/name=tu_nom ... puntuacion y lo mete en el lugar correspondiente en la tabla de records.

Code: Select all

#include <stdio.h> #include <string.h> #include <malloc.h> #include <stdlib.h> #define MAXRECORDS 10 #define NAMESIZE 50 #define PLACESIZE 50 typedef struct SIMPLEREG { char *name; char *place; int points; } SIMPLEREG; typedef struct RECORDS { char *name[MAXRECORDS]; int points[MAXRECORDS]; char *place[MAXRECORDS]; long time[MAXRECORDS]; } RECORDS; RECORDS * init_records(void); SIMPLEREG * init_simplereg(void); void destroy_records(RECORDS *r); void destroy_simplereg(SIMPLEREG *s); void view_records(RECORDS *r); int save_records(RECORDS *r); RECORDS * load_records(char *filename, RECORDS *r); int compare_ints(const void *a, const void *b); RECORDS * input_new_record(RECORDS *r, char *name, char *place, int points); RECORDS * move_record_table(RECORDS *r, int position); RECORDS * copy_table(RECORDS *r); void export_html(RECORDS *r, SIMPLEREG *s); void parse_commandline(int argc, char **argv, RECORDS *blank); void view_env(RECORDS *r); SIMPLEREG * parse_pathinfo(char * pathinfo, SIMPLEREG *aux); int main(void) { RECORDS *r, *blank; SIMPLEREG *aux; r=init_records(); aux=init_simplereg(); blank=copy_table(r); r=load_records("normal.rec",r); aux=parse_pathinfo(getenv("PATH_INFO"),aux); if (aux==NULL) { export_html(r,aux); destroy_records(blank); destroy_records(r); return 0; } else { input_new_record(r,aux->name,aux->place,aux->points); save_records(r); } export_html(r,aux); destroy_simplereg(aux); destroy_records(blank); destroy_records(r); return 0; } RECORDS * init_records(void) { RECORDS *aux; int i; aux=(struct RECORDS *)malloc(sizeof(struct RECORDS)); if (aux==NULL) return NULL; memset(aux,0,sizeof(struct RECORDS)); for (i=0;i<MAXRECORDS;i++) { aux->name[i]=(char *)malloc(sizeof(char)*NAMESIZE); if (aux->name[i]==NULL) return NULL; memset(aux->name[i],0,sizeof(char)*NAMESIZE); sprintf(aux->name[i],"Desconocido"); aux->place[i]=(char *)malloc(sizeof(char)*PLACESIZE); if (aux->place[i]==NULL) return NULL; memset(aux->place[i],0,sizeof(char)*PLACESIZE); strcpy(aux->place[i],"Sin especificar"); aux->points[i]=0; } return aux; } SIMPLEREG * init_simplereg(void) { SIMPLEREG *aux; aux=(struct SIMPLEREG *)malloc(sizeof(struct SIMPLEREG)); if (aux==NULL) return NULL; memset(aux,0,sizeof(struct SIMPLEREG)); aux->name=(char *)malloc(sizeof(char)*NAMESIZE); if (aux->name==NULL) return NULL; memset(aux->name,0,sizeof(char)*NAMESIZE); aux->place=(char *)malloc(sizeof(char)*PLACESIZE); if (aux->place==NULL) return NULL; memset(aux->place,0,sizeof(char)*PLACESIZE); aux->points=0; return aux; } void destroy_records(RECORDS *r) { int i; for (i=0;i<MAXRECORDS;i++) { free(r->name[i]); free(r->place[i]); } free(r); } void destroy_simplereg(SIMPLEREG *s) { free(s->name); free(s->place); free(s); } void view_records(RECORDS *r) { int i; for (i=0;i<MAXRECORDS;i++) { printf("Name:%s Points:%d Place:%s\n"\ ,r->name[i],r->points[i],r->place[i]); } } int save_records(RECORDS *r) { FILE *f; int i; f=fopen("normal.rec","wb"); if (f==NULL) return -1; for (i=0;i<MAXRECORDS;i++) { fwrite(r->name[i],sizeof(char)*NAMESIZE,1,f); fwrite(r->place[i],sizeof(char)*PLACESIZE,1,f); fwrite(&r->points[i],sizeof(int),1,f); } fclose(f); return 0; } RECORDS * load_records(char *filename, RECORDS *r) { FILE *f; int i; f=fopen(filename,"rb"); if (f==NULL) return NULL; for (i=0;i<MAXRECORDS;i++) { fread(r->name[i],sizeof(char)*NAMESIZE,1,f); fread(r->place[i],sizeof(char)*PLACESIZE,1,f); fread(&r->points[i],sizeof(int),1,f); } return r; } int compare_ints(const void *a, const void *b) { const int *da=(const int *)a; const int *db=(const int *)b; return (*db>*da)-(*db<*da); } RECORDS * input_new_record(RECORDS *r, char *name, char *place, int points) { int i=MAXRECORDS-1; while(points>=r->points[i-1]) { i--; if (i==0) break; } move_record_table(r,i); memset(r->name[i],0,sizeof(char)*NAMESIZE); memset(r->place[i],0,sizeof(char)*PLACESIZE); strcpy(r->name[i],name); strcpy(r->place[i],place); r->points[i]=points; return r; } RECORDS * move_record_table(RECORDS *r, int position) { RECORDS *aux; int i=0; aux=copy_table(r); for (i=position;i<MAXRECORDS-1;i++) { strcpy(r->name[i+1],aux->name[i]); strcpy(r->place[i+1],aux->place[i]); r->points[i+1]=aux->points[i]; } for (i=0;i<MAXRECORDS;i++) { free(aux->name[i]); free(aux->place[i]); } free(aux); return r; } RECORDS * copy_table(RECORDS *r) { RECORDS *aux; int i; aux=(struct RECORDS *)malloc(sizeof(struct RECORDS)); if (aux==NULL) return NULL; memset(aux,0,sizeof(struct RECORDS)); for (i=0;i<MAXRECORDS;i++) { aux->name[i]=(char *)malloc(sizeof(char)*NAMESIZE); if (aux->name[i]==NULL) return NULL; memset(aux->name[i],0,sizeof(char)*NAMESIZE); strcpy(aux->name[i],r->name[i]); aux->place[i]=(char *)malloc(sizeof(char)*PLACESIZE); if (aux->place[i]==NULL) return NULL; memset(aux->place[i],0,sizeof(char)*PLACESIZE); strcpy(aux->place[i],r->place[i]); aux->points[i]=r->points[i]; } return aux; } void export_html(RECORDS *r, SIMPLEREG *s) { int i; FILE *f; char *buf; unsigned long int size=0L; printf("Content-type: text/html\n\n"); f=fopen("part1.txt","rb"); fseek(f,0L,SEEK_END); size=ftell(f); fseek(f,0L,SEEK_SET); buf=(char *)malloc((sizeof(char)*size)+1); if (buf==NULL) return; memset(buf,0,(sizeof(char)*size)+1); fread(buf,(sizeof(char)*size)+1,1,f); fclose(f); printf("%s",buf); free(buf); printf("<TABLE align=center border=0 cellpadding=5 cellspacing=2>"); printf("<TR>"); printf("<TD align=center bgcolor=Black><font color=White>Nombre</font></TD>"); printf("<TD align=center bgcolor=Black><font color=White>Lugar</font></TD>"); printf("<TD align=center bgcolor=Black><font color=White>Puntuaci&oacute;n</font></TD>"); printf("</TR>"); for (i=0;i<MAXRECORDS>>1;i++) { printf("<TR>"); printf("<TD align=left bgcolor=Silver><font color=Black>%s</font></TD>",r->name[i]); printf("<TD align=center bgcolor=Silver><font color=Black>%s</font></TD>",r->place[i]); printf("<TD align=center bgcolor=Silver><font color=Black>%d</font></TD>",r->points[i]); printf("</TR>"); printf("<TR>"); printf("<TD align=left bgcolor=Gray><font color=Black>%s</font></TD>",r->name[i+1]); printf("<TD align=center bgcolor=Gray><font color=Black>%s</font></TD>",r->place[i+1]); printf("<TD align=center bgcolor=Gray><font color=Black>%d</font></TD>",r->points[i+1]); printf("</TR>"); } f=fopen("part2.txt","rb"); fseek(f,0L,SEEK_END); size=ftell(f); fseek(f,0L,SEEK_SET); buf=(char *)malloc((sizeof(char)*size)+1); if (buf==NULL) return; memset(buf,0,(sizeof(char)*size)+1); fread(buf,(sizeof(char)*size)+1,1,f); printf("%s",buf); free(buf); fclose(f); } void parse_commandline(int argc, char **argv, RECORDS *blank) { if (argc>1) { if (!strcmp(argv[1],"password")) { if (!strcmp(argv[2],"remove")) { save_records(blank); } } } } void view_env(RECORDS *r) { if (getenv("SERVER_NAME")==NULL) { printf("NULL"); }; } SIMPLEREG * parse_pathinfo(char * pathinfo, SIMPLEREG *aux) { char *buf; int i; unsigned long int namesize; unsigned long int placesize; unsigned long int pointsize; unsigned long int startnpos=0L; unsigned long int endnpos=0L; unsigned long int startppos=0L; unsigned long int endppos=0L; unsigned long int startpopos=0L; unsigned long int endpopos=0L; char *name; char *place; char *points; if (pathinfo==NULL) return NULL; buf=(char *)malloc(sizeof(char)*(strlen(pathinfo)+1)); if (buf==NULL) return NULL; memset(buf,0,sizeof(char)*(strlen(pathinfo)+1)); strcpy(buf,pathinfo); if (strlen(buf)<20) return NULL; /* Primero miramos a ver si hay caracteres especiales, si los hay salimos el / y el = no cuenta */ for (i=0;i<strlen(buf);i++) { if (buf[i]!=0) { if (buf[i]!=32) { if (buf[i]<47 || buf[i]>122) { free(buf); return NULL; } if (buf[i]>=58 && buf[i]<=60) { free(buf); return NULL; } if (buf[i]>=62 && buf[i]<=64) { free(buf); return NULL; } if (buf[i]>=91 && buf[i]<=96) { free(buf); return NULL; } } } } /* Comprobamos que no haya 2 o mas caracteres especiales permitidos seguidos */ for (i=0;i<strlen(buf)-1;i++) { if ((buf[i]=='/' && buf[i+1]=='/') || (buf[i]=='/' && buf[i+1]=='=') ||(buf[i]=='/' && buf[i+1]==' ') || (buf[i]=='=' && buf[i+1]=='/') || (buf[i]=='=' && buf[i+1]=='=') ||(buf[i]=='=' && buf[i+1]==' ') || (buf[i]==' ' && buf[i+1]=='/') || (buf[i]==' ' && buf[i+1]=='=') ||(buf[i]==' ' && buf[i+1]==' ')) { free(buf); return NULL; } } /* Bueno, la cadena parece válida, mirar a ver el tamaño de cada campo */ /* Primero el nombre */ startnpos=i=6; while(i<strlen(buf)) { if (buf[i]=='/') { namesize=i-6; endnpos=i; if (namesize>=NAMESIZE) { free(buf); return NULL; } break; } i++; } startppos=i=endnpos+7; while(i<strlen(buf)) { if (buf[i]=='/') { placesize=i-startppos; endppos=i; if (placesize>=PLACESIZE) { free(buf); return NULL; } break; } i++; } startpopos=i=endppos+8; while(buf[i]!='\0') i++; pointsize=i-startpopos; endpopos=i; if (pointsize>=40) { free(buf); return NULL; } /* Coger el nombre */ name=(char *)malloc((sizeof(char)*namesize)+1); if (name==NULL) { free(buf); return NULL; } memset(name,0,(sizeof(char)*namesize)+1); for (i=startnpos;i<endnpos;i++) { name[i-6]=buf[i]; } /* Coger el lugar */ place=(char *)malloc((sizeof(char)*placesize)+1); if (place==NULL) { free(buf); return NULL; } memset(place,0,(sizeof(char)*placesize)+1); for (i=startppos;i<endppos;i++) { place[i-startppos]=buf[i]; } /* Coger los puntos */ points=(char *)malloc((sizeof(char)*pointsize)+1); if (points==NULL) { free(buf); return NULL; } memset(points,0,(sizeof(char)*pointsize)+1); for (i=startpopos;i<endpopos;i++) { points[i-startpopos]=buf[i]; } free(buf); strcpy(aux->name,name); strcpy(aux->place,place); aux->points=(int)atoi(points); free(name); free(place); free(points); return aux; }
Lo dicho, estoy perdidísimo y cualquier ayuda será bienvenida.

Saludos y gracias.
User avatar
Popolon
Usuario avanzado
Posts: 474
Joined: Tue May 13, 2003 2:31 pm
Location: Lloret de Mar
Contact:

Postby Popolon » Sat Dec 24, 2005 2:09 pm

Buenas Traperic,

ahora no tengo mucho tiempo, o sea que no puedo mirarme con mucho detalle el código que has puesto. Pero básicamente, si quieres usar la clase F1Shttp, te explico cómo funciona:

- al constructor le pasas una URL (por ejemplo: http://www.google.com)
- di te fijas, el constructor crea un nuevo thread, que lo que hace es intentar acceder a ésa dirección web
- con la función "get_web" puedes comprobar si la web ya ha sido accedida o no. Si todavía no ha podido acceder, devuelve un 0, si ya ha accedido, devuelve el texto correspondiente a la web.

te pongo un ejemplillo: (lo estoy improvisando, o sea que a lo mejor hay algún error):

void main(void)
{
int wait_time=10; // esperar 10 segundos como mucho
F1Shttp *web;

web=new F1Shttp("http://www.google.com");
while(web->get_web()==0 && wait_time>0) {
sleep(1000); // esperar un segundo más
wait_time--;
}

if (web->get_web()!=0) {
printf("la web accedida contiene éste texto: \n%s\n",web->get_web());
} else {
print("Ha pasado demasiado tiempo...\n");
}
delete web;
}

bueno, espero que te sirva. La verdad es que yo también lo pasé fatal hasta que conseguí encontrar la librería CURL que hace casi todo el trabajo! ya me explicarás si te funciona!

un saludo

santi
User avatar
traperic
Usuario avanzado
Posts: 75
Joined: Sun Apr 10, 2005 3:06 pm
Contact:

Postby traperic » Sat Dec 24, 2005 4:27 pm

¡Muchas gracias Popolon!, ya funciona, he pasado la clase totalmente a C y a sintaxis 'phantomera' :D y con el ejemplo que me has pasado funciona perfectamente, ahora tengo que ver como eliminar las dependecias de SDL...

Ya te contaré.

Saludos.
User avatar
traperic
Usuario avanzado
Posts: 75
Joined: Sun Apr 10, 2005 3:06 pm
Contact:

Postby traperic » Sat Dec 24, 2005 4:41 pm

Si lo se no posteo, ya está hecho. La parte de recibir los datos del servidor ya está... pero ahora hay que mandarlos, es decir, pasarle la cadena que te comentaba anteriormente al cgi, ¿podrías mandarme otro ejemplillo cuando tengas un rato? 8) :roll:
User avatar
Popolon
Usuario avanzado
Posts: 474
Joined: Tue May 13, 2003 2:31 pm
Location: Lloret de Mar
Contact:

Postby Popolon » Mon Dec 26, 2005 12:17 am

Vaya! me alegro de que funcione! Si no recuerdo mal, el único vínculo entre la clase F1Shttp y SDL es una llamada que hay para crear un thread. Supongo que si subsituyes esa llamada por una utilizando la librería "pthread" o cualquier otra librería de threads, tiene que seguir funcionando... Pero bueno, si dices que ya lo has solucionado seguro que ya has hecho algo así...

Sobre cómo enviar datos al servidor, no hay que hacer nada especial, en la línia donde crees el obejto F1Shttp (o PhantomasHttp, o como le hayas llamado a tu versión) puedes hacer directamente:

web=new F1Shttp("http://www.phantomas.hiscores.com?jugad ... ntos=10000");

y ya está, no tiene más secreto que ese.
User avatar
traperic
Usuario avanzado
Posts: 75
Joined: Sun Apr 10, 2005 3:06 pm
Contact:

Postby traperic » Mon Dec 26, 2005 10:12 am

Vaya! me alegro de que funcione! Si no recuerdo mal, el único vínculo entre la clase F1Shttp y SDL es una llamada que hay para crear un thread. Supongo que si subsituyes esa llamada por una utilizando la librería "pthread" o cualquier otra librería de threads, tiene que seguir funcionando... Pero bueno, si dices que ya lo has solucionado seguro que ya has hecho algo así...
Bueno, la verdad que lo único que hice fué comentar las llamadas a SDL y unas ligeras modificaciones al código, el programa entonces se queda congelado cuando accede al servidor pero es que me parecía demasiada carga de librerías (curl+pthreads) para tan poca funcionalidad, no obstante, no se nota la congelación ya que el programa no tiene música en el momento en que consulta/manda los records ni tiene animaciones ni nada.
Sobre cómo enviar datos al servidor, no hay que hacer nada especial, en la línia donde crees el obejto F1Shttp (o PhantomasHttp, o como le hayas llamado a tu versión) puedes hacer directamente:

web=new F1Shttp("http://www.phantomas.hiscores.com?jugad ... ntos=10000");
Es lo primero que probé, pero por un estúpido error mio, pasaba un caracter incorrecto en la cadena y ya no funcionaba :oops:

Pero bueno, ya está corregido y funciona perfectamente, la próxima versión del juego ya usará la tabla de records. Muchas gracias por todo Popolon, te has ganado un merecido puesto en los créditos. :wink:
User avatar
Popolon
Usuario avanzado
Posts: 474
Joined: Tue May 13, 2003 2:31 pm
Location: Lloret de Mar
Contact:

Postby Popolon » Mon Dec 26, 2005 12:10 pm

Pues me alegro de que funcione!!

Estaremos esperando la siguiente versión!!!! :D

Return to “Desarrollo”

Who is online

Users browsing this forum: No registered users and 9 guests