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 float litrosAgua = 0.0f;
|
||||||
|
|
||||||
private ActivityResultLauncher<Intent> videoLauncher;
|
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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";
|
private final String MINHA_API_KEY = "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";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -53,7 +54,6 @@ public class DesafiosActivity extends AppCompatActivity {
|
|||||||
setContentView(R.layout.activity_desafios);
|
setContentView(R.layout.activity_desafios);
|
||||||
|
|
||||||
tvStatusGeralIA = findViewById(R.id.tvStatusGeralIA);
|
tvStatusGeralIA = findViewById(R.id.tvStatusGeralIA);
|
||||||
// Esconde o texto antigo do topo, já não precisamos dele!
|
|
||||||
tvStatusGeralIA.setVisibility(View.GONE);
|
tvStatusGeralIA.setVisibility(View.GONE);
|
||||||
|
|
||||||
tvStatusAgua = findViewById(R.id.tvStatusAgua);
|
tvStatusAgua = findViewById(R.id.tvStatusAgua);
|
||||||
@@ -146,7 +146,7 @@ public class DesafiosActivity extends AppCompatActivity {
|
|||||||
SharedPreferences prefs = getSharedPreferences("DadosGamificacao", MODE_PRIVATE);
|
SharedPreferences prefs = getSharedPreferences("DadosGamificacao", MODE_PRIVATE);
|
||||||
|
|
||||||
litrosAgua = prefs.getFloat("agua_litros", 0.0f);
|
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(tvStatusD1, prefs.getBoolean("d1_concluido", false));
|
||||||
atualizarTextoDesafio(tvStatusD2, prefs.getBoolean("d2_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() {
|
private void mostrarLoading() {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
builder.setTitle("A analisar o vídeo... ⏳");
|
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.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 = builder.create();
|
||||||
popupCarregamento.show();
|
popupCarregamento.show();
|
||||||
@@ -181,12 +178,10 @@ public class DesafiosActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void mostrarResultadoFinal(String titulo, String mensagem) {
|
private void mostrarResultadoFinal(String titulo, String mensagem) {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
// Fecha a janela de "A aguardar..."
|
|
||||||
if (popupCarregamento != null && popupCarregamento.isShowing()) {
|
if (popupCarregamento != null && popupCarregamento.isShowing()) {
|
||||||
popupCarregamento.dismiss();
|
popupCarregamento.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Abre a janela com o resultado final
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
builder.setTitle(titulo);
|
builder.setTitle(titulo);
|
||||||
builder.setMessage(mensagem);
|
builder.setMessage(mensagem);
|
||||||
@@ -197,9 +192,23 @@ public class DesafiosActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void enviarVideoParaIA(Uri uri) {
|
private void enviarVideoParaIA(Uri uri) {
|
||||||
bloquearBotoes(false);
|
bloquearBotoes(false);
|
||||||
mostrarLoading(); // Mostra a janela de loading logo aqui!
|
mostrarLoading();
|
||||||
|
|
||||||
new Thread(() -> {
|
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);
|
String base64Video = converterVideo(uri);
|
||||||
if (base64Video == null) {
|
if (base64Video == null) {
|
||||||
mostrarResultadoFinal("Erro no Vídeo ⚠️", "Não foi possível ler o vídeo gravado.");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String instrucao = "";
|
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";
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// OpenRouter utiliza a tag "video_url"
|
||||||
AiRequest request = new AiRequest(Collections.singletonList(
|
AiRequest request = new AiRequest(Collections.singletonList(
|
||||||
new Message("user", java.util.Arrays.asList(
|
new Message("user", java.util.Arrays.asList(
|
||||||
new ContentPart("text", instrucao),
|
new ContentPart("text", instrucao),
|
||||||
@@ -251,25 +256,23 @@ public class DesafiosActivity extends AppCompatActivity {
|
|||||||
SharedPreferences.Editor perfilEditor = perfilPrefs.edit();
|
SharedPreferences.Editor perfilEditor = perfilPrefs.edit();
|
||||||
|
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
|
|
||||||
|
// LÓGICA DA ÁGUA FIXA (250ml / 0.25L)
|
||||||
if (desafioAtualSendoGravado == 0) {
|
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);
|
float copo = 0.25f; // 250 ml = 0.25 Litros
|
||||||
editor.putInt("agua_hoje", (int) (litrosAgua / 0.25f));
|
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 {
|
} else {
|
||||||
|
// LÓGICA DOS EXERCÍCIOS
|
||||||
if (texto.contains("Status: Concluido")) {
|
if (texto.contains("Status: Concluido")) {
|
||||||
|
|
||||||
int caloriasAQueimar = 0;
|
int caloriasAQueimar = 0;
|
||||||
@@ -285,14 +288,13 @@ public class DesafiosActivity extends AppCompatActivity {
|
|||||||
perfilEditor.putInt("desafios_concluidos", perfilPrefs.getInt("desafios_concluidos", 0) + 1);
|
perfilEditor.putInt("desafios_concluidos", perfilPrefs.getInt("desafios_concluidos", 0) + 1);
|
||||||
perfilEditor.apply();
|
perfilEditor.apply();
|
||||||
|
|
||||||
// Mostra o resultado do Exercício!
|
|
||||||
mostrarResultadoFinal("Desafio Validado! ✅", "Ganhaste +50 Pontos e queimaste " + caloriasAQueimar + " kcal. Continua assim!");
|
mostrarResultadoFinal("Desafio Validado! ✅", "Ganhaste +50 Pontos e queimaste " + caloriasAQueimar + " kcal. Continua assim!");
|
||||||
} else {
|
} else {
|
||||||
mostrarResultadoFinal("Desafio Falhou ❌", "A IA acha que o movimento não foi claro ou bem feito. Tenta outra vez!");
|
mostrarResultadoFinal("Desafio Falhou ❌", "A IA acha que o movimento não foi claro ou bem feito. Tenta outra vez!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
editor.apply();
|
editor.apply();
|
||||||
carregarEstadosNaTela();
|
carregarEstadosNaTela(); // Atualiza logo os números da água na tela dos Desafios
|
||||||
bloquearBotoes(true);
|
bloquearBotoes(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,22 +26,18 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_login);
|
setContentView(R.layout.activity_login);
|
||||||
|
|
||||||
// Ligar o código aos IDs do ecrã
|
|
||||||
etLoginEmail = findViewById(R.id.etLoginEmail);
|
etLoginEmail = findViewById(R.id.etLoginEmail);
|
||||||
etLoginPassword = findViewById(R.id.etLoginPassword);
|
etLoginPassword = findViewById(R.id.etLoginPassword);
|
||||||
btnLogin = findViewById(R.id.btnLogin);
|
btnLogin = findViewById(R.id.btnLogin);
|
||||||
tvGoToRegister = findViewById(R.id.tvGoToRegister);
|
tvGoToRegister = findViewById(R.id.tvGoToRegister);
|
||||||
|
|
||||||
// Iniciar a memória do telemóvel
|
|
||||||
sharedPreferences = getSharedPreferences("MeusDadosApp", MODE_PRIVATE);
|
sharedPreferences = getSharedPreferences("MeusDadosApp", MODE_PRIVATE);
|
||||||
|
|
||||||
// Enviar para o Registo
|
|
||||||
tvGoToRegister.setOnClickListener(v -> {
|
tvGoToRegister.setOnClickListener(v -> {
|
||||||
Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
|
Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Botão de Entrar
|
|
||||||
btnLogin.setOnClickListener(v -> {
|
btnLogin.setOnClickListener(v -> {
|
||||||
String email = etLoginEmail.getText().toString().trim();
|
String email = etLoginEmail.getText().toString().trim();
|
||||||
String password = etLoginPassword.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) {
|
public void onResponse(Call<SupabaseResponse> call, Response<SupabaseResponse> response) {
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
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();
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
editor.putString("access_token", token);
|
editor.putString("access_token", response.body().access_token);
|
||||||
editor.putString("email", email);
|
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();
|
Toast.makeText(LoginActivity.this, "Entraste com sucesso! 🚀", Toast.LENGTH_SHORT).show();
|
||||||
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
|
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
|
||||||
|
|||||||
@@ -10,15 +10,12 @@ import java.util.Map;
|
|||||||
|
|
||||||
public interface SupabaseApi {
|
public interface SupabaseApi {
|
||||||
|
|
||||||
// 1. Rota para criar a conta
|
|
||||||
@POST("auth/v1/signup")
|
@POST("auth/v1/signup")
|
||||||
Call<SupabaseResponse> signUp(@Header("apikey") String apiKey, @Body UserCredentials credentials);
|
Call<SupabaseResponse> signUp(@Header("apikey") String apiKey, @Body UserCredentials credentials);
|
||||||
|
|
||||||
// 2. Rota para fazer login
|
|
||||||
@POST("auth/v1/token?grant_type=password")
|
@POST("auth/v1/token?grant_type=password")
|
||||||
Call<SupabaseResponse> login(@Header("apikey") String apiKey, @Body UserCredentials credentials);
|
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")
|
@PUT("auth/v1/user")
|
||||||
Call<Void> updateUserData(
|
Call<Void> updateUserData(
|
||||||
@Header("apikey") String apikey,
|
@Header("apikey") String apikey,
|
||||||
@@ -32,20 +29,16 @@ public interface SupabaseApi {
|
|||||||
class UserCredentials {
|
class UserCredentials {
|
||||||
String email;
|
String email;
|
||||||
String password;
|
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) {
|
public UserCredentials(String email, String password) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
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) {
|
public UserCredentials(String email, String password, String nome, int idade, float altura, float peso, String sexo) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
|
||||||
// Empacotar os dados exatamente como o Supabase pede
|
|
||||||
this.data = new HashMap<>();
|
this.data = new HashMap<>();
|
||||||
this.data.put("nome", nome);
|
this.data.put("nome", nome);
|
||||||
this.data.put("idade", idade);
|
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 {
|
class SupabaseResponse {
|
||||||
public String access_token;
|
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