Preciso da sua dica

Olá meus amigos,
primeiramente gostaria de pedir desculpa pelo título do tópico genérico demais, mas eu não achei algo melhor …

Estou desenvolvendo um sistema (struts 2 e hibernate) para controlar radio taxi, cada carro usa um GPS com 3G conectado ao servidor.
Quando a atendente da rádio táxi recebe uma solicitação do cliente, uma nova corrida é gerada, assim o sistema deve calcular qual taxi está mais perto daquele cliente e informar na tela do GPS do taxi que ele deve atender aquele cliente. O taxista tem 15 segundos para clicar em aceitar corrida, caso contrário o sistema deve localizar o proximo taxi e assim por diante. Por fim, caso nenhum taxi seja encontrado ou aceite a corrida dentro do raio maximo configurado no sistema, o operador do sistema pega o rádio e solicita um voluntário, quando este voluntário aparece o operador deve poder direcionar aquela corrida para um taxi em especial.

Cada taxi é identificado pelo seu registro (RT)

O sistema já está cadastrando usuario, cliente, taxi, etc…
O sistema já calcula a distancia a partir de coordenada e informa qual o taxi mais próximo.

Agora estou precisando de dicas de como fazer os outros detalhes que coloquei acima.

Para acessar o sistema entre em sistaxi.dyndns.org usuario: guj senha:guj
no menu tem um botão para fazer download do .war para importar no eclipse, com todos os fontes, etc…

não se assustem com a feiura do sistema, agora estou preocupado em fazer as regras de negócio funcionarem, depois eu enfeito com jquery, etc …
minha maior dúvida é com a classe que faz a regra de negócio, mas se puderem me ajudar tbm com o jsp que deve ter ajax e eu não faço idéia de como usa ajax

package br.com.sistaxi.controle.action;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;

import br.com.sistaxi.auxiliar.CalculaDistancia;
import br.com.sistaxi.beans.Cliente;
import br.com.sistaxi.beans.Corrida;
import br.com.sistaxi.beans.Taxi;
import br.com.sistaxi.hibernate.Dao;

public class GeraCorridaAction {

	private ArrayList<Cliente> listaCliente = new ArrayList<Cliente>();
	private Dao dao = new Dao();
	private String mensagem;
	private double distancia;
	private ArrayList<Taxi> listaTaxi = new ArrayList<Taxi>();
	private Taxi taxi = new Taxi();
	private double latitude;
	private double longitude;
	private double menorDistancia;
	private Taxi proximoTaxi = new Taxi();
	private String menorDistanciaStr;
	private String funcao;
	private Cliente cliente = new Cliente();
	private CalculaDistancia cd = new CalculaDistancia();
	private Corrida corrida = new Corrida();
	private String corridaObservacao;
	private List<Corrida> listaCorrida = new ArrayList<Corrida>();


	@Action(value = "/gerarCorrida", results = {
			@Result(name = "goListarCliente", location = "/jsp/listarClientePage.jsp"),
			@Result(name = "goGeraCorrida", location = "/jsp/geraCorridaPage.jsp"),
			@Result(name = "goLogin", location = "/index.jsp") })
	public String execute() {
		
		// Função iniciar uma nova corrida
		if ("gerarCorrida".equals(funcao)) {
			
			// inicializa variaveis
			distancia = 0;
			
			// raio máximo de busca
			menorDistancia = 100000000;
			
			// carrega toda lista de taxi
			listaTaxi = dao.listaTaxi(taxi);
			
			// converte os dados que vieram da form como string para double
			latitude = Double.parseDouble(cliente.getLatitude());
			longitude = Double.parseDouble(cliente.getLongitude());
			
			// percorre todos os taxis procurando pelo mais proximo
			for (int i = 0; i < listaTaxi.size(); i++) {
				
				// chama a função que calcula a distancia entre o taxi e o
				// cliente
				distancia = cd.btw(latitude, longitude, listaTaxi.get(i)
						.getLatitude(), listaTaxi.get(i).getLongitude());
				
				// coloca os dados do taxi mais proximo e da distancia nas
				// variaveis abaixo
				if ((menorDistancia > distancia) && ("livre".equals(listaTaxi.get(i).getStatus()))){
					menorDistancia = distancia;
					proximoTaxi = listaTaxi.get(i);
				}
				//aqui entra funcao que aguarda o taxista aceitar a corrida e em caso
				//de recusa ou timeout procura um novo taxi
				//importante, fazer esta função
			}
			// faz arredondamento da distancia para duas casas decimais
			DecimalFormat decimalFormat = new DecimalFormat();
			decimalFormat.setMinimumFractionDigits(1);
			setMenorDistanciaStr(decimalFormat.format(menorDistancia));
			
			//salva ou atualiza o cliente da corrida
			mensagem = dao.salva(cliente);
			
			//muda o status do taxi q aceitou para ocupado
			proximoTaxi.setStatus("ocupado");
			
			//insere cliente e taxi na corrida
			//ainda falta inserir taxista e usuario na corrida para log e relatorio
			//importante !!!!
			corrida.setCliente(cliente);
			corrida.setTaxi(proximoTaxi);
			corrida.setObservacao(corridaObservacao);
			//tambem deve deixar a corrida como ativa
			corrida.setSituacao("ativa");
			
			
			//salva a nova corrida
			mensagem = dao.salva(corrida);
			
			//mensagem de retorno confirmando a nova corrida
			mensagem = " O Taxi mais proximo é o RT " + corrida.getTaxi().getRt()
					+ " a " + menorDistanciaStr + " KM" + " para o cliente "+ corrida.getCliente().getNome();
		}
		//se a função for cancelar corrida
		if ("cancelarCorrida".equals(funcao)) 
		{
			//carrega todos os dados da corrida selecionada pelo id
			corrida = (Corrida) dao.getCorridaById(corrida.getId());
			//altera o status da corrida para cancelada
			corrida.setSituacao("cancelada");
			corrida.getTaxi().setStatus("livre");
			//faz update na corrida
			mensagem = dao.salva(corrida);
		}
		
		//ao selecionar um cliente na combobox, pegar todos os dados no banco
		if ("clienteSelecionado".equals(funcao)) 
		{
			//carrega as informações do cliente selecionado no combobox pelo nome
			cliente = (Cliente) dao.getClienteByNome(cliente);
		}
			
		
		
		//o codigo abaixo roda independentemente do comando que vier do jsp
		//gera uma lista com todos os clientes
		listaCliente = dao.listarCliente(cliente);

		//gera uma lista com as corridas ativas
		listaCorrida = dao.getCorridasAtivas();
		
		

		return "goGeraCorrida";

	}

//ggas

}

Muito obrigado a todos que dedicarem seu tempo a me auxiliar nessa …

Boa noite,

Cara, quanto à aparência do sistema, recomendaria que você utilizasse Flex. Eu uso, gosto e para mim faz mais sucesso entre os usuários.
Agora quanto à sua regra de negócio, não entendo muito de gps, no caso deveria ter um sistema no gps que buscasse dados no banco de dados do servidor e exibisse para o motorista para que o mesmo interagisse.

Agora não sei se existe gps com esses recursos de desenvolvimento, mas acredito que sim :lol:

Olá amigo,

Obrigado pela resposta,

Quanto ao flex, sou usuário mac, vou ver se tem pra mac e estudar sobre a curva de aprendizado, como é um projeto de faculdade, não pode ser algo que demore muito.

Quanto ao GPS não se preocupe com ele, essa parte por enquanto está resolvida, para fins didáticos tem 3 carros atualizando sua posição no banco, pego essas coordenada com taxi.getLatitude() e taxi.getLongitude()

a linha abaixo pega a latitude e longitude do endereço do cliente e faz um calculo contra as coodenadas do taxi, a variavel distancia, recebe a distancia entre o cliente e cada taxi
distancia = cd.btw(latitude, longitude, listaTaxi.get(i)
.getLatitude(), listaTaxi.get(i).getLongitude());

tudo isso já está funcionando.

Minha dúvida não se refere a GPS, e sim sobre como lidar com tempo de espera até o taxista aceitar a corrida, o sistema fica parado ou uso uma thread ? se o taxista não aceitar como faço pra chamar outro taxi, monto uma fila de taxis ou chamo a função de escolher taxi com alguma flag pra não chamar o q recusou ? e se nenhum taxista aceitar, como faz pro adm do sistema direcionar um taxi em especial ?

minhas dúvidas são puramente relacionadas a como tratar o envio da corrida para o taxi, e não sobre fazer o envio propriamente dito…

não sei se consegui me explicar direito…

Bem, você pode montar um banco de dados no servidor com tabelas específicas para isso, tipo uma tabela com as colunas principais: id_taxi, id_corrida, status, onde id_taxi possui uma referência para o taxi, id_corrida, para os dados da corrida em questão, status, se a corrida foi aceita pelo taxista ou não. O default do status fica sendo 0. Daí você monta uma thread na aplicação do taxista que fica lendo todas as linhas referente o taxi dele com status 0. Se ele rejeitar, muda para 2, se aceitar 1. Mudando de 0 para 1 ou 2, aquele convite deixa de existir. Caso seja 2 o sistema no lado servidor deverá tratar o dado e criar uma nova linha nessa tabela mas com outro id_taxi.

Já utlizei essa lógica em outra situação e funcionou bem.

Não sei se me fiz entender, mas tamo ae. :smiley:

Pois é estou seguindo nessa linha, inclusive tenho essa tabela que chama tabCorrida e tem essas chaves, mas travei no pepino de que se ele recusar e mudar pra “2” uma nova corrida que pode estar inclusive rodando em paralelo não o chamará tbm, o que não pode acontecer…

Ja quebrei muito a cabeça e não estou conseguindo encontrar uma solução…

o melhor seria com thread mesmo, mas como não estou conseguindo achar uma solução e o projeto é pra faculdade, não precisa ser perfeito, talvez o melhor seja rodar uma corrida por vez, reiniciando as flags, mas mesmo assim ainda não achei uma solução ideal …

se vc entrar no menu gerar corrida e gerar alguma corrida vai ver que ele já busca o taxi mais próximo e inclusive informa a distancia …

novamente obrigado

Não, porque o 2 não diz que o taxista está indisponível, e sim que o taxista para aquela corrida está indisponível.

Veja que a tabela não pode tratar apenas o taxista, mas as corridas também. Para cada corrida solicitada haverá um registro.

id_taxi ----- id_corrida ----- status
2 -------------------10---------------2
5 ------------------- 5----------------1
7 ------------------- 6----------------2
2 ------------------- 12---------------2
2 ------------------- 13---------------1

Veja que na tabela acima o taxi com id 2 foi chamado três vezes, há registro das 3 chamadas, o fato da primeira chamada ter resultado em 2 não o impede de receber outro convite até ele aceitar.

Fui claro? Era esse mesmo a sua dúvida, talvez tenha entendido errado. :wink:

Abraço

pensei, pensei e ainda não cheguei a uma conclusão

toda corrida tem uma id e uma id do cliente, a id do taxi só entra nela depois que a corrida for aceita, então não consigo marcar aquela flag de recusado…

Seu pensamento está correto, só que antes de ir para a tabela corrida, ela vai para a tabela digamos tabela_em_aberto, daí sim todas as corridas que receberem 1 irão para a tabela_corrida, enquanto no tabela_em_Aberto houver corridas com status 2, estas ficarão rodando até um taxista setar como 1.

:wink:

opa, assim seria perfeito, mas como fazer o sistema ficar monitorando essa tabela corridas em aberto enquanto o atendente gera outras corridas ? thread ?

Eu usaria triggers no banco de dados, assim evita o uso excessivo de threads.

Usaria threads com esse intuito apenas no lado cliente. Minha opinião!

tem algum exemplo de como fazer com trigguer ? seria algo do tipo se algum taxi pegar determinada corrida ele faz alguma coisa ?

Sim, seria… tipo quando o valor for alterado faça…

Que banco você está utilizando?

mysql e administro pelo phpmyadmin

dessa meneira tbm resolveria o problema do q fazer se todos os carros estiverem ocupados ou fora do raio máximo configurado ?

Legal,

Dá uma olhada nesses guias:

http://dev.mysql.com/doc/refman/5.0/en/triggers.html
http://www.devmedia.com.br/post-8088-MySQL-TRIGGERS.html
http://wiki.locaweb.com.br/pt-br/Manipulação_de_triggers_no_MySQL
http://profissionais.ws/programacao/mysql-programacao/como-criar-triggers-no-mysql.html

Para mysql nunca criei uma trigger, deve ser de boa tanto quanto no sqlserver. Tenta criar e se não conseguir me manda o código que eu tento aqui. :smiley:

Não, na verdade tem que ter uma aplicação no lado servidor fazendo esse controle com trheads mesmo. Pois se não houver carros, o sistema deverá tomar outra ação. É melhor esquecer as triggers. #fail. :?

certo, já vi que o bixo vai pegar mesmo … kkkkk

não faço idéia de como usar thread nem ajax e pelo jeito sem essa dupla não vai dar certo

Relaxa,

Comece a trabalhar com a tabela_em_aberto. Conforme as dúvidas forem surgindo, vai postando aqui…

Esse foi meu modo de pensar… De imediato acho que esse é o caminho, mas talvez os mais experientes tenham formas mais eficientes de solucionar esse problema.
Qualquer coisa e ou novidade, posta ae.

Abraço