corrigir os novos erros amnhã e adicionar qual tipo de sexo a pessoa é no register
This commit is contained in:
@@ -43,8 +43,9 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
private float litrosAgua = 0.0f;
|
||||
|
||||
private ActivityResultLauncher<Intent> videoLauncher;
|
||||
private AlertDialog popupCarregamento; // A janela de loading
|
||||
private AlertDialog popupCarregamento;
|
||||
|
||||
// COLOCA AQUI A TUA CHAVE DO OPENROUTER:
|
||||
private final String MINHA_API_KEY = "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";
|
||||
|
||||
@Override
|
||||
@@ -53,7 +54,6 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
setContentView(R.layout.activity_desafios);
|
||||
|
||||
tvStatusGeralIA = findViewById(R.id.tvStatusGeralIA);
|
||||
// Esconde o texto antigo do topo, já não precisamos dele!
|
||||
tvStatusGeralIA.setVisibility(View.GONE);
|
||||
|
||||
tvStatusAgua = findViewById(R.id.tvStatusAgua);
|
||||
@@ -146,7 +146,7 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
SharedPreferences prefs = getSharedPreferences("DadosGamificacao", MODE_PRIVATE);
|
||||
|
||||
litrosAgua = prefs.getFloat("agua_litros", 0.0f);
|
||||
tvStatusAgua.setText(String.format(Locale.getDefault(), "Progresso: %.1f / 2.0 L", litrosAgua));
|
||||
tvStatusAgua.setText(String.format(Locale.getDefault(), "Progresso: %.2f / 2.0 L", litrosAgua));
|
||||
|
||||
atualizarTextoDesafio(tvStatusD1, prefs.getBoolean("d1_concluido", false));
|
||||
atualizarTextoDesafio(tvStatusD2, prefs.getBoolean("d2_concluido", false));
|
||||
@@ -164,15 +164,12 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// NOVOS POP-UPS DE LOADING E RESULTADOS
|
||||
// ==========================================
|
||||
private void mostrarLoading() {
|
||||
runOnUiThread(() -> {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle("A analisar o vídeo... ⏳");
|
||||
builder.setMessage("A Inteligência Artificial está a avaliar o teu desempenho. Por favor, aguarda um momento.");
|
||||
builder.setCancelable(false); // Impede que o utilizador feche sem querer
|
||||
builder.setCancelable(false);
|
||||
|
||||
popupCarregamento = builder.create();
|
||||
popupCarregamento.show();
|
||||
@@ -181,12 +178,10 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
|
||||
private void mostrarResultadoFinal(String titulo, String mensagem) {
|
||||
runOnUiThread(() -> {
|
||||
// Fecha a janela de "A aguardar..."
|
||||
if (popupCarregamento != null && popupCarregamento.isShowing()) {
|
||||
popupCarregamento.dismiss();
|
||||
}
|
||||
|
||||
// Abre a janela com o resultado final
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(titulo);
|
||||
builder.setMessage(mensagem);
|
||||
@@ -197,9 +192,23 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
|
||||
private void enviarVideoParaIA(Uri uri) {
|
||||
bloquearBotoes(false);
|
||||
mostrarLoading(); // Mostra a janela de loading logo aqui!
|
||||
mostrarLoading();
|
||||
|
||||
new Thread(() -> {
|
||||
|
||||
// 🔥 TRUQUE DE MESTRE: Se for o desafio da água (0), não enviamos para a IA!
|
||||
// Fingimos que processa e damos sempre 250ml diretos.
|
||||
if (desafioAtualSendoGravado == 0) {
|
||||
try {
|
||||
Thread.sleep(1500); // Finge que está a processar durante 1.5s
|
||||
} catch (InterruptedException e) {}
|
||||
|
||||
// Vai direto para o processamento com código de sucesso!
|
||||
processarResposta("SUCESSO_AGUA");
|
||||
return;
|
||||
}
|
||||
|
||||
// Daqui para baixo é SÓ para os vídeos de exercício físico (D1, D2, D3, D4)
|
||||
String base64Video = converterVideo(uri);
|
||||
if (base64Video == null) {
|
||||
mostrarResultadoFinal("Erro no Vídeo ⚠️", "Não foi possível ler o vídeo gravado.");
|
||||
@@ -207,13 +216,9 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
String instrucao = "";
|
||||
if (desafioAtualSendoGravado == 0) {
|
||||
instrucao = "Analisa a pessoa a beber água. Devolve apenas os litros consumidos. Formato exato: Litros: [valor_decimal]";
|
||||
} else {
|
||||
instrucao = "Analisa o exercício físico do vídeo. Verifica se a pessoa fez o movimento corretamente. Devolve apenas o formato: Status: Concluido ou Status: Falhou";
|
||||
}
|
||||
String instrucao = "Analisa o exercício físico do vídeo. Verifica se a pessoa fez o movimento corretamente. Devolve apenas o formato: Status: Concluido ou Status: Falhou";
|
||||
|
||||
// OpenRouter utiliza a tag "video_url"
|
||||
AiRequest request = new AiRequest(Collections.singletonList(
|
||||
new Message("user", java.util.Arrays.asList(
|
||||
new ContentPart("text", instrucao),
|
||||
@@ -251,25 +256,23 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
SharedPreferences.Editor perfilEditor = perfilPrefs.edit();
|
||||
|
||||
runOnUiThread(() -> {
|
||||
|
||||
// LÓGICA DA ÁGUA FIXA (250ml / 0.25L)
|
||||
if (desafioAtualSendoGravado == 0) {
|
||||
if (texto.contains("Litros:")) {
|
||||
try {
|
||||
String valorStr = texto.substring(texto.indexOf("Litros:") + 7).trim().replaceAll("[^0-9.]", "");
|
||||
float lido = Float.parseFloat(valorStr);
|
||||
litrosAgua += lido;
|
||||
|
||||
editor.putFloat("agua_litros", litrosAgua);
|
||||
editor.putInt("agua_hoje", (int) (litrosAgua / 0.25f));
|
||||
float copo = 0.25f; // 250 ml = 0.25 Litros
|
||||
litrosAgua += copo; // Soma à água total
|
||||
|
||||
editor.putFloat("agua_litros", litrosAgua);
|
||||
|
||||
// "agua_hoje" conta o número de copos (que reflete nas Estatísticas)
|
||||
int coposAtuais = prefs.getInt("agua_hoje", 0);
|
||||
editor.putInt("agua_hoje", coposAtuais + 1);
|
||||
|
||||
mostrarResultadoFinal("Bom trabalho! 💧", "Registaste +250ml de água! Mantém-te hidratado!");
|
||||
|
||||
// Mostra o resultado da Água!
|
||||
mostrarResultadoFinal("Bom trabalho! 💧", "A IA detetou que bebeste +" + lido + " Litros!");
|
||||
} catch (Exception e) {
|
||||
mostrarResultadoFinal("Oops! 🤔", "A IA teve dificuldade em ler a quantidade exata. Tenta gravar de novo.");
|
||||
}
|
||||
} else {
|
||||
mostrarResultadoFinal("Oops! 🤔", "A IA não percebeu o vídeo. Garante que o copo ou garrafa se vê bem!");
|
||||
}
|
||||
} else {
|
||||
// LÓGICA DOS EXERCÍCIOS
|
||||
if (texto.contains("Status: Concluido")) {
|
||||
|
||||
int caloriasAQueimar = 0;
|
||||
@@ -285,14 +288,13 @@ public class DesafiosActivity extends AppCompatActivity {
|
||||
perfilEditor.putInt("desafios_concluidos", perfilPrefs.getInt("desafios_concluidos", 0) + 1);
|
||||
perfilEditor.apply();
|
||||
|
||||
// Mostra o resultado do Exercício!
|
||||
mostrarResultadoFinal("Desafio Validado! ✅", "Ganhaste +50 Pontos e queimaste " + caloriasAQueimar + " kcal. Continua assim!");
|
||||
} else {
|
||||
mostrarResultadoFinal("Desafio Falhou ❌", "A IA acha que o movimento não foi claro ou bem feito. Tenta outra vez!");
|
||||
}
|
||||
}
|
||||
editor.apply();
|
||||
carregarEstadosNaTela();
|
||||
carregarEstadosNaTela(); // Atualiza logo os números da água na tela dos Desafios
|
||||
bloquearBotoes(true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,22 +26,18 @@ public class LoginActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
|
||||
// Ligar o código aos IDs do ecrã
|
||||
etLoginEmail = findViewById(R.id.etLoginEmail);
|
||||
etLoginPassword = findViewById(R.id.etLoginPassword);
|
||||
btnLogin = findViewById(R.id.btnLogin);
|
||||
tvGoToRegister = findViewById(R.id.tvGoToRegister);
|
||||
|
||||
// Iniciar a memória do telemóvel
|
||||
sharedPreferences = getSharedPreferences("MeusDadosApp", MODE_PRIVATE);
|
||||
|
||||
// Enviar para o Registo
|
||||
tvGoToRegister.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
// Botão de Entrar
|
||||
btnLogin.setOnClickListener(v -> {
|
||||
String email = etLoginEmail.getText().toString().trim();
|
||||
String password = etLoginPassword.getText().toString().trim();
|
||||
@@ -59,12 +55,22 @@ public class LoginActivity extends AppCompatActivity {
|
||||
public void onResponse(Call<SupabaseResponse> call, Response<SupabaseResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
|
||||
// Guardar o token e o email para usar nas Definições
|
||||
String token = response.body().access_token;
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString("access_token", token);
|
||||
editor.putString("access_token", response.body().access_token);
|
||||
editor.putString("email", email);
|
||||
editor.apply();
|
||||
|
||||
// NOVO: Puxar os teus dados de saúde do Supabase e guardar na memória!
|
||||
if (response.body().user != null && response.body().user.user_metadata != null) {
|
||||
UserMetadata meta = response.body().user.user_metadata;
|
||||
|
||||
if (meta.nome != null) editor.putString("nome", meta.nome);
|
||||
editor.putInt("idade", meta.idade);
|
||||
editor.putFloat("altura", meta.altura);
|
||||
editor.putFloat("peso", meta.peso);
|
||||
if (meta.sexo != null) editor.putString("sexo", meta.sexo);
|
||||
}
|
||||
|
||||
editor.apply(); // Tranca a gaveta com todos os dados lá dentro
|
||||
|
||||
Toast.makeText(LoginActivity.this, "Entraste com sucesso! 🚀", Toast.LENGTH_SHORT).show();
|
||||
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
|
||||
|
||||
@@ -10,15 +10,12 @@ import java.util.Map;
|
||||
|
||||
public interface SupabaseApi {
|
||||
|
||||
// 1. Rota para criar a conta
|
||||
@POST("auth/v1/signup")
|
||||
Call<SupabaseResponse> signUp(@Header("apikey") String apiKey, @Body UserCredentials credentials);
|
||||
|
||||
// 2. Rota para fazer login
|
||||
@POST("auth/v1/token?grant_type=password")
|
||||
Call<SupabaseResponse> login(@Header("apikey") String apiKey, @Body UserCredentials credentials);
|
||||
|
||||
// 3. Rota para atualizar a palavra-passe ou dados do utilizador
|
||||
@PUT("auth/v1/user")
|
||||
Call<Void> updateUserData(
|
||||
@Header("apikey") String apikey,
|
||||
@@ -32,20 +29,16 @@ public interface SupabaseApi {
|
||||
class UserCredentials {
|
||||
String email;
|
||||
String password;
|
||||
Map<String, Object> data; // O Supabase exige que os dados extras fiquem aqui dentro!
|
||||
Map<String, Object> data;
|
||||
|
||||
// Construtor 1: Usado para o LOGIN (só precisa de email e password)
|
||||
public UserCredentials(String email, String password) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
// Construtor 2: Usado para o REGISTO (arruma os dados de saúde na pasta "data")
|
||||
public UserCredentials(String email, String password, String nome, int idade, float altura, float peso, String sexo) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
|
||||
// Empacotar os dados exatamente como o Supabase pede
|
||||
this.data = new HashMap<>();
|
||||
this.data.put("nome", nome);
|
||||
this.data.put("idade", idade);
|
||||
@@ -55,6 +48,20 @@ class UserCredentials {
|
||||
}
|
||||
}
|
||||
|
||||
// O SEGREDO ESTÁ AQUI: Ensinar a app a ler os dados de saúde do Supabase!
|
||||
class SupabaseResponse {
|
||||
public String access_token;
|
||||
public SupabaseUser user; // Puxa o objeto do utilizador
|
||||
}
|
||||
|
||||
class SupabaseUser {
|
||||
public UserMetadata user_metadata; // Puxa os dados que guardaste no registo
|
||||
}
|
||||
|
||||
class UserMetadata {
|
||||
public String nome;
|
||||
public int idade;
|
||||
public float altura;
|
||||
public float peso;
|
||||
public String sexo;
|
||||
}
|
||||
Reference in New Issue
Block a user