Administramos tickets de soporte en tres niveles (basico, intermedio y experto) usando colas independientes y reglas de escalamiento manual.
#define CAP_TICKETS 40
#define MAX_CLIENTE 40
#define MAX_NOTA 64
typedef struct {
char cliente[MAX_CLIENTE];
char nota[MAX_NOTA];
int nivel;
} Ticket;
typedef struct {
Ticket datos[CAP_TICKETS];
int frente;
int final;
int cantidad;
} ColaTickets;
void cola_init(ColaTickets *cola) {
cola->frente = 0;
cola->final = 0;
cola->cantidad = 0;
}
int cola_push(ColaTickets *cola, Ticket t) {
if (cola->cantidad == CAP_TICKETS) {
return 0;
}
cola->datos[cola->final] = t;
cola->final = (cola->final + 1) % CAP_TICKETS;
cola->cantidad++;
return 1;
}
int cola_pop(ColaTickets *cola, Ticket *t) {
if (cola->cantidad == 0) {
return 0;
}
*t = cola->datos[cola->frente];
cola->frente = (cola->frente + 1) % CAP_TICKETS;
cola->cantidad--;
return 1;
}
typedef struct {
ColaTickets basic;
ColaTickets mid;
ColaTickets expert;
int atendidos[3];
} CentroSoporte;
void soporte_init(CentroSoporte *c) {
cola_init(&c->basic);
cola_init(&c->mid);
cola_init(&c->expert);
c->atendidos[0] = c->atendidos[1] = c->atendidos[2] = 0;
}
int registrarTicket(CentroSoporte *c, const char *cliente, const char *nota, int nivel) {
Ticket t;
strncpy(t.cliente, cliente, MAX_CLIENTE - 1);
t.cliente[MAX_CLIENTE - 1] = '\0';
strncpy(t.nota, nota, MAX_NOTA - 1);
t.nota[MAX_NOTA - 1] = '\0';
t.nivel = nivel;
ColaTickets *cola = nivel == 3 ? &c->expert : (nivel == 2 ? &c->mid : &c->basic);
return cola_push(cola, t);
}
int atenderTicket(CentroSoporte *c, Ticket *t) {
ColaTickets *colas[3] = { &c->expert, &c->mid, &c->basic };
for (int i = 0; i < 3; ++i) {
if (cola_pop(colas[i], t)) {
c->atendidos[2 - i]++;
return 1;
}
}
return 0;
}
int escalarTicket(CentroSoporte *c, int origen, int destino) {
ColaTickets *colas[3] = { &c->basic, &c->mid, &c->expert };
if (origen < 1 || origen > 3 || destino < 1 || destino > 3 || destino <= origen) {
return 0;
}
if (colas[origen - 1]->cantidad == 0) {
return 0;
}
Ticket t;
cola_pop(colas[origen - 1], &t);
t.nivel = destino;
return cola_push(colas[destino - 1], t);
}
void mostrarEstado(const CentroSoporte *c) {
printf("Experto: %d pendientes\n", c->expert.cantidad);
printf("Intermedio: %d pendientes\n", c->mid.cantidad);
printf("Basico: %d pendientes\n", c->basic.cantidad);
}
void limpiarEntrada(void) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
}
int main(void) {
CentroSoporte centro;
soporte_init(¢ro);
int opcion;
char cliente[MAX_CLIENTE];
char nota[MAX_NOTA];
Ticket ticket;
int origen, destino;
do {
puts("\n1) Registrar ticket basico");
puts("2) Registrar ticket intermedio");
puts("3) Registrar ticket experto");
puts("4) Atender siguiente ticket");
puts("5) Escalar ticket");
puts("6) Mostrar estado");
puts("0) Cerrar turno");
printf("Opcion: ");
if (scanf("%d", &opcion) != 1) {
puts("Entrada invalida");
limpiarEntrada();
continue;
}
limpiarEntrada();
switch (opcion) {
case 1:
case 2:
case 3:
printf("Cliente: ");
if (!fgets(cliente, sizeof cliente, stdin)) break;
cliente[strcspn(cliente, "\n")] = '\0';
printf("Resumen: ");
if (!fgets(nota, sizeof nota, stdin)) break;
nota[strcspn(nota, "\n")] = '\0';
if (registrarTicket(¢ro, cliente, nota, opcion)) {
puts("Ticket registrado.");
} else {
puts("Cola correspondiente llena.");
}
break;
case 4:
if (atenderTicket(¢ro, &ticket)) {
printf("Atendiendo [%d] %s - %s\n", ticket.nivel, ticket.cliente, ticket.nota);
} else {
puts("No hay tickets pendientes.");
}
break;
case 5:
printf("Nivel origen (1-3): ");
scanf("%d", &origen);
printf("Nivel destino (1-3): ");
scanf("%d", &destino);
limpiarEntrada();
if (escalarTicket(¢ro, origen, destino)) {
puts("Escalamiento realizado.");
} else {
puts("No se pudo escalar (verifica niveles y disponibilidad).");
}
break;
case 6:
mostrarEstado(¢ro);
break;
case 0:
puts("Turno cerrado.");
mostrarEstado(¢ro);
printf("Atendidos experto: %d\n", centro.atendidos[2]);
printf("Atendidos intermedio: %d\n", centro.atendidos[1]);
printf("Atendidos basico: %d\n", centro.atendidos[0]);
break;
default:
puts("Opcion no valida.");
}
} while (opcion != 0);
return 0;
}
Usa este archivo para compilar el ejemplo de punta a punta.
#include <stdio.h>
#include <string.h>
#define CAP_TICKETS 40
#define MAX_CLIENTE 40
#define MAX_NOTA 64
typedef struct {
char cliente[MAX_CLIENTE];
char nota[MAX_NOTA];
int nivel;
} Ticket;
typedef struct {
Ticket datos[CAP_TICKETS];
int frente;
int final;
int cantidad;
} ColaTickets;
typedef struct {
ColaTickets basic;
ColaTickets mid;
ColaTickets expert;
int atendidos[3];
} CentroSoporte;
void cola_init(ColaTickets *cola) { cola->frente = cola->final = cola->cantidad = 0; }
int cola_push(ColaTickets *cola, Ticket t) {
if (cola->cantidad == CAP_TICKETS) return 0;
cola->datos[cola->final] = t;
cola->final = (cola->final + 1) % CAP_TICKETS;
cola->cantidad++;
return 1;
}
int cola_pop(ColaTickets *cola, Ticket *t) {
if (cola->cantidad == 0) return 0;
*t = cola->datos[cola->frente];
cola->frente = (cola->frente + 1) % CAP_TICKETS;
cola->cantidad--;
return 1;
}
void soporte_init(CentroSoporte *c) {
cola_init(&c->basic);
cola_init(&c->mid);
cola_init(&c->expert);
c->atendidos[0] = c->atendidos[1] = c->atendidos[2] = 0;
}
int registrarTicket(CentroSoporte *c, const char *cliente, const char *nota, int nivel) {
Ticket t;
strncpy(t.cliente, cliente, MAX_CLIENTE - 1);
t.cliente[MAX_CLIENTE - 1] = '\0';
strncpy(t.nota, nota, MAX_NOTA - 1);
t.nota[MAX_NOTA - 1] = '\0';
t.nivel = nivel;
ColaTickets *cola = nivel == 3 ? &c->expert : (nivel == 2 ? &c->mid : &c->basic);
return cola_push(cola, t);
}
int atenderTicket(CentroSoporte *c, Ticket *t) {
if (cola_pop(&c->expert, t)) {
c->atendidos[2]++;
return 1;
}
if (cola_pop(&c->mid, t)) {
c->atendidos[1]++;
return 1;
}
if (cola_pop(&c->basic, t)) {
c->atendidos[0]++;
return 1;
}
return 0;
}
int escalarTicket(CentroSoporte *c, int origen, int destino) {
ColaTickets *colas[3] = { &c->basic, &c->mid, &c->expert };
if (origen < 1 || origen > 3 || destino < 1 || destino > 3 || destino <= origen) {
return 0;
}
if (colas[origen - 1]->cantidad == 0) {
return 0;
}
Ticket t;
cola_pop(colas[origen - 1], &t);
t.nivel = destino;
return cola_push(colas[destino - 1], t);
}
void mostrarEstado(const CentroSoporte *c) {
printf("Experto: %d pendientes\n", c->expert.cantidad);
printf("Intermedio: %d pendientes\n", c->mid.cantidad);
printf("Basico: %d pendientes\n", c->basic.cantidad);
}
void limpiarEntrada(void) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
}
int main(void) {
CentroSoporte centro;
soporte_init(¢ro);
int opcion;
char cliente[MAX_CLIENTE];
char nota[MAX_NOTA];
Ticket ticket;
int origen, destino;
do {
puts("\n1) Registrar ticket basico");
puts("2) Registrar ticket intermedio");
puts("3) Registrar ticket experto");
puts("4) Atender siguiente ticket");
puts("5) Escalar ticket");
puts("6) Mostrar estado");
puts("0) Cerrar turno");
printf("Opcion: ");
if (scanf("%d", &opcion) != 1) {
puts("Entrada invalida");
limpiarEntrada();
continue;
}
limpiarEntrada();
switch (opcion) {
case 1:
case 2:
case 3:
printf("Cliente: ");
if (!fgets(cliente, sizeof cliente, stdin)) break;
cliente[strcspn(cliente, "\n")] = '\0';
printf("Resumen: ");
if (!fgets(nota, sizeof nota, stdin)) break;
nota[strcspn(nota, "\n")] = '\0';
if (registrarTicket(¢ro, cliente, nota, opcion)) {
puts("Ticket registrado.");
} else {
puts("Cola correspondiente llena.");
}
break;
case 4:
if (atenderTicket(¢ro, &ticket)) {
printf("Atendiendo [%d] %s - %s\n", ticket.nivel, ticket.cliente, ticket.nota);
} else {
puts("No hay tickets pendientes.");
}
break;
case 5:
printf("Nivel origen (1-3): ");
scanf("%d", &origen);
printf("Nivel destino (1-3): ");
scanf("%d", &destino);
limpiarEntrada();
if (escalarTicket(¢ro, origen, destino)) {
puts("Escalamiento realizado.");
} else {
puts("No se pudo escalar (verifica niveles y disponibilidad).");
}
break;
case 6:
mostrarEstado(¢ro);
break;
case 0:
puts("Turno cerrado.");
mostrarEstado(¢ro);
printf("Atendidos experto: %d\n", centro.atendidos[2]);
printf("Atendidos intermedio: %d\n", centro.atendidos[1]);
printf("Atendidos basico: %d\n", centro.atendidos[0]);
break;
default:
puts("Opcion no valida.");
}
} while (opcion != 0);
return 0;
}
Una version futura incluirá persistencia de tickets y estadisticas semanales.