S2 : MVP et première interface graphique

This commit is contained in:
Erwann PHILIPPE 2026-02-03 14:16:26 +01:00
parent 36d6ab1b5b
commit 7b0e6c6e09
10 changed files with 257 additions and 26 deletions

View file

@ -4,6 +4,14 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-02-03T12:06:28.141777700Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=QGP7K78LKBMVZTRC" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState> </SelectionState>
</selectionStates> </selectionStates>
</component> </component>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

View file

@ -12,7 +12,7 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Coach"> android:theme="@style/Theme.Coach">
<activity <activity
android:name=".MainActivity" android:name=".view.MainActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View file

@ -1,24 +0,0 @@
package com.example.coach;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}

View file

@ -0,0 +1,5 @@
package com.example.coach.contract;
public interface ICalculView {
void AfficherResultat(String image, double img, String message, boolean normal);
}

View file

@ -0,0 +1,74 @@
package com.example.coach.model;
public class Profil {
private static final int MIN_FEMME = 25;
private static final int MAX_FEMME = 30;
private static final int MIN_HOMME = 15;
private static final int MAX_HOMME = 20;
private static final String[] MESSAGE = {"trop faible", "normal", "trop élevé"};
private static final String[] IMAGE = {"maigre", "normal", "graisse"};
private Integer poids;
private Integer taille;
private Integer age;
private Integer sexe;
private double img;
private int indice;
public Profil(Integer poids, Integer taille, Integer age, Integer sexe) {
this.poids = poids;
this.taille = taille;
this.age = age;
this.sexe = sexe;
this.img = calculImg();
this.indice = calculIndice();
}
private double calculImg()
{
double img;
double tailleM = (double) taille/100.0;
img = (1.2*poids/(tailleM*tailleM)) + (0.23*age) - (10.83*sexe) - 5.4;
return img;
}
private int calculIndice()
{
int min;
int max;
if(sexe == 0){
min = MIN_FEMME;
max = MAX_FEMME;
}else{
min = MIN_HOMME;
max = MAX_HOMME;
}
if(img < min){
return 0;
} else if (img > max) {
return 2;
}else{
return 1;
}
}
public double getImg(){
return this.img;
}
public String getMessage(){
return MESSAGE[this.indice];
}
public String getImage(){
return IMAGE[this.indice];
}
public boolean normal(){
if(indice == 1){
return true;
}else{
return false;
}
}
}

View file

@ -0,0 +1,18 @@
package com.example.coach.presenter;
import com.example.coach.contract.ICalculView;
import com.example.coach.model.Profil;
public class CalculPresenter {
private ICalculView vue;
public CalculPresenter(ICalculView vue) {
this.vue = vue;
}
public void creerProfil(Integer sexe, Integer poids, Integer taille, Integer age)
{
Profil profil = new Profil(poids, taille, age, sexe);
vue.AfficherResultat(profil.getImage(), profil.getImg(), profil.getMessage(), profil.normal());
}
}

View file

@ -0,0 +1,109 @@
package com.example.coach.view;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.example.coach.R;
import com.example.coach.contract.ICalculView;
import com.example.coach.presenter.CalculPresenter;
public class MainActivity extends AppCompatActivity implements ICalculView {
private EditText txtPoids;
private EditText txtTaille;
private EditText txtAge;
private RadioButton rdHomme;
private RadioButton rdFemme;
private TextView lblIMG;
private ImageView imgSmiley;
private Button btnCalc;
private CalculPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
init();
}
@Override
public void AfficherResultat(String image, double img, String message, boolean normal) {
int iamgeId = getResources().getIdentifier(image, "drawable", getPackageName());
String texte = String.format("%.01f", img) + " : IMG " + message;
if(iamgeId == 0){
imgSmiley.setImageResource(R.drawable.normal);
}else{
imgSmiley.setImageResource(iamgeId);
}
lblIMG.setText(texte);
if(!normal){
lblIMG.setTextColor(Color.RED);
}else{
lblIMG.setTextColor(Color.GREEN);
}
}
private void init()
{
chargeObjetsGraphiques();
presenter = new CalculPresenter(this);
btnCalc.setOnClickListener(v -> btnCalcClic());
}
private void chargeObjetsGraphiques()
{
txtPoids = (EditText) findViewById(R.id.txtPoids);
txtTaille = (EditText) findViewById(R.id.txtTaille);
txtAge = (EditText) findViewById(R.id.txtAge);
rdHomme = (RadioButton) findViewById(R.id.rdHomme);
rdFemme = (RadioButton) findViewById(R.id.rdFemme);
lblIMG = (TextView) findViewById(R.id.lblResultat);
imgSmiley = (ImageView) findViewById(R.id.imgSmiley);
btnCalc = (Button) findViewById(R.id.btnCalc);
}
private void btnCalcClic()
{
int poids = 0, taille = 0, age = 0, sexe = 0;
try {
poids = Integer.parseInt(txtPoids.getText().toString());
taille = Integer.parseInt(txtTaille.getText().toString());
age = Integer.parseInt(txtAge.getText().toString());
}catch (Exception ignored){}
if(rdHomme.isChecked()){
sexe = 1;
}
if(poids == 0 || taille == 0 || age == 0){
Toast.makeText(this, "Veuillez remplir tous les champs", Toast.LENGTH_SHORT).show();
}else{
presenter.creerProfil(sexe, poids, taille, age);
}
}
}

View file

@ -5,7 +5,7 @@
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity"> tools:context=".view.MainActivity">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -0,0 +1,40 @@
package com.example.coach.model;
import static org.junit.Assert.*;
import org.junit.Test;
public class ProfilTest {
private Profil profilMaigre = new Profil (45, 170, 20, 0);
private Profil profilNormal = new Profil (70, 180, 40, 1);
private Profil profilGras = new Profil (67, 165, 35, 0);
@Test
public void getImg() {
assertEquals(17.9, profilMaigre.getImg(), 0.1);
assertEquals(18.9, profilNormal.getImg(), 0.1);
assertEquals(32.2, profilGras.getImg(), 0.1);
}
@Test
public void getMessage() {
assertEquals("trop faible", profilMaigre.getMessage());
assertEquals("normal", profilNormal.getMessage());
assertEquals("trop élevé", profilGras.getMessage());
}
@Test
public void getImage() {
assertEquals("maigre", profilMaigre.getImage());
assertEquals("normal", profilNormal.getImage());
assertEquals("graisse", profilGras.getImage());
}
@Test
public void normal() {
assertFalse(profilMaigre.normal());
assertTrue(profilNormal.normal());
assertFalse(profilGras.normal());
}
}