New version a bit more up to date.
This commit is contained in:
parent
4a851f73d4
commit
dbb108dd73
@ -33,6 +33,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'com.jjoe64:graphview:4.2.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
||||
|
||||
@ -13,9 +13,10 @@
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
|
||||
<activity
|
||||
android:name=".activities.GraphActivity"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:screenOrientation="landscape"/>
|
||||
<activity
|
||||
android:name=".activities.PrepareMeasureActivity"
|
||||
android:name=".activities.PrepareGraphActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".activities.NewMeasureOnSubjectActivity"
|
||||
|
||||
@ -11,9 +11,12 @@ import android.util.Log;
|
||||
import com.bernard.emorph.model.Group;
|
||||
import com.bernard.emorph.model.MeasureOnSubject;
|
||||
import com.bernard.emorph.model.Subject;
|
||||
import com.jjoe64.graphview.series.DataPoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class EMorphApplication extends Application {
|
||||
|
||||
@ -30,6 +33,14 @@ public class EMorphApplication extends Application {
|
||||
//putInitialData(db);
|
||||
}
|
||||
|
||||
public static double img(MeasureOnSubject mos, double age){
|
||||
return 0.098*mos.abdomen-0.170*age + 0.182*mos.bras-0.061*mos.epaules + 0.069*mos.taille + 0.036*mos.cuisse-0.077*mos.cheville-4.266;
|
||||
}
|
||||
public static double imm(MeasureOnSubject mos){
|
||||
Log.d("IMM",mos.toString()+"->"+(0.109*mos.bras + 0.093*mos.cuisse + 0.276*mos.avantBras + 0.078*mos.abdomen - 0.056*mos.taille + 0.703));
|
||||
return 0.109*mos.bras + 0.093*mos.cuisse + 0.276*mos.avantBras + 0.078*mos.abdomen - 0.056*mos.taille + 0.703;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
@ -145,6 +156,113 @@ public class EMorphApplication extends Application {
|
||||
return new MeasureOnSubject(newId, subjectId, abdomen, bras, epaules, taille, cuisse, cheville, avantBras);
|
||||
}
|
||||
|
||||
public Long getLastMeasureID(long groupID) {
|
||||
Cursor dbResult = db.query("measures",new String[]{"ID"},
|
||||
"groupID=?",new String[]{Long.toString(groupID)}, null, null, "time DESC");
|
||||
dbResult.moveToFirst();
|
||||
Long out;
|
||||
if(dbResult.isAfterLast())
|
||||
out = null;
|
||||
else
|
||||
out = dbResult.getLong(0);
|
||||
dbResult.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
public Set<Long> getXLastMeasures(long groupID, int x){
|
||||
Cursor dbResult = db.query("measures",new String[]{"ID"},
|
||||
"groupID=?",new String[]{Long.toString(groupID)}, null, null, "time DESC");
|
||||
dbResult.moveToFirst();
|
||||
Set<Long> out = new HashSet<>();
|
||||
for(int i=0;i<x && !dbResult.isAfterLast();i++) {
|
||||
out.add(dbResult.getLong(0));
|
||||
dbResult.moveToNext();
|
||||
}
|
||||
dbResult.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
public Set<Long> getMeasuresIDs(long groupID){
|
||||
Cursor dbResult = db.query("measures",new String[]{"ID"},
|
||||
"groupID=?",new String[]{Long.toString(groupID)}, null, null, null);
|
||||
dbResult.moveToFirst();
|
||||
Set<Long> out = new HashSet<>();
|
||||
while(!dbResult.isAfterLast()) {
|
||||
out.add(dbResult.getLong(0));
|
||||
dbResult.moveToNext();
|
||||
}
|
||||
dbResult.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
public Set<Long> getMeasuresSince(long groupID, long oldDate) {
|
||||
Cursor dbResult = db.query("measures",new String[]{"ID"},
|
||||
"groupID=? AND time>?",new String[]{Long.toString(groupID),Long.toString(oldDate)},
|
||||
null, null, null);
|
||||
dbResult.moveToFirst();
|
||||
Set<Long> out = new HashSet<>();
|
||||
while(!dbResult.isAfterLast()) {
|
||||
out.add(dbResult.getLong(0));
|
||||
dbResult.moveToNext();
|
||||
}
|
||||
dbResult.close();
|
||||
return out;
|
||||
}
|
||||
public MeasureOnSubject getMos(long subjectID, long measureID){
|
||||
Cursor dbResult = db.query("measuresOnSubjects",new String[]{"ID","subjectID","circAbdomen","circBras","circEpaules","circTaille","circCuisse","circCheville","circAvantBras"},
|
||||
"subjectID = ?",new String[]{Long.toString(subjectID)/*,Long.toString(measureID)*/},
|
||||
null, null, null);
|
||||
dbResult.moveToFirst();
|
||||
MeasureOnSubject out;
|
||||
if(dbResult.isAfterLast())
|
||||
out = null;
|
||||
else
|
||||
out = new MeasureOnSubject(
|
||||
dbResult.getLong(0),
|
||||
dbResult.getLong(1),
|
||||
dbResult.getFloat(2),
|
||||
dbResult.getFloat(3),
|
||||
dbResult.getFloat(4),
|
||||
dbResult.getFloat(5),
|
||||
dbResult.getFloat(6),
|
||||
dbResult.getFloat(7),
|
||||
dbResult.getFloat(8)
|
||||
);
|
||||
dbResult.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
public long dateNaissance(long subjectID){
|
||||
Cursor result = db.query("subjects",new String[]{"dateNaissance"},"ID=?", new String[]{Long.toString(subjectID)},null,null,null);
|
||||
if(result.getCount()==0)return -1;
|
||||
result.moveToFirst();
|
||||
long out = result.getLong(0);
|
||||
result.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
public void dumpTable(String tableName){
|
||||
Cursor c = db.rawQuery("SELECT * FROM "+tableName,new String[0]);
|
||||
c.moveToFirst();
|
||||
StringBuilder sb = new StringBuilder("Dumping table "+tableName+" :\n");
|
||||
while(!c.isAfterLast()){
|
||||
for(int i=0;i<c.getColumnCount();i++)
|
||||
sb.append(c.getString(i)).append(";");
|
||||
sb.append("\n");
|
||||
Log.d("DbDump",sb.toString());
|
||||
c.moveToNext();
|
||||
}
|
||||
c.close();
|
||||
|
||||
}
|
||||
|
||||
public DataPoint point(long subjectID, long measureID){
|
||||
float age = ((((float)System.currentTimeMillis())/(1000.f))-dateNaissance(subjectID))/3600f/365.24f;
|
||||
MeasureOnSubject mos = getMos(subjectID,measureID);
|
||||
if(mos==null)return null;
|
||||
return new DataPoint(imm(mos),img(mos, age));
|
||||
}
|
||||
|
||||
|
||||
public static class EMorphDbHelper extends SQLiteOpenHelper {
|
||||
// If you change the database schema, you must increment the database version.
|
||||
@ -189,13 +307,13 @@ public class EMorphApplication extends Application {
|
||||
cv.put("ID", testDatum[0]);
|
||||
cv.put("measureID", testDatum[1]);
|
||||
cv.put("subjectID", testDatum[2]);
|
||||
cv.put("circAbdomen", testDatum[3]);
|
||||
cv.put("circBras", testDatum[4]);
|
||||
cv.put("circEpaules", testDatum[5]);
|
||||
cv.put("circTaille", testDatum[6]);
|
||||
cv.put("circCuisse", testDatum[7]);
|
||||
cv.put("circCheville", testDatum[8]);
|
||||
cv.put("circAvantBras", testDatum[9]);
|
||||
cv.put("circAbdomen", testDatum[8]);
|
||||
cv.put("circBras", testDatum[6]);
|
||||
cv.put("circEpaules", testDatum[7]);
|
||||
cv.put("circTaille", testDatum[9]);
|
||||
cv.put("circCuisse", testDatum[4]);
|
||||
cv.put("circCheville", testDatum[3]);
|
||||
cv.put("circAvantBras", testDatum[5]);
|
||||
db.insert("measuresOnSubjects", null, cv);
|
||||
}
|
||||
for (Object[] testDatum : testData2) {
|
||||
|
||||
249
app/src/main/java/com/bernard/emorph/SquaringGraphSeries.java
Normal file
249
app/src/main/java/com/bernard/emorph/SquaringGraphSeries.java
Normal file
@ -0,0 +1,249 @@
|
||||
package com.bernard.emorph;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jjoe64.graphview.GraphView;
|
||||
import com.jjoe64.graphview.RectD;
|
||||
import com.jjoe64.graphview.series.BaseSeries;
|
||||
import com.jjoe64.graphview.series.DataPointInterface;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class SquaringGraphSeries extends BaseSeries<SquaringGraphSeries.DirectionalRectanglePoint> {
|
||||
|
||||
/**
|
||||
* paint to do drawing on canvas
|
||||
*/
|
||||
private final Paint mPaint;
|
||||
|
||||
/**
|
||||
* stores the coordinates of the bars to
|
||||
* trigger tap on series events.
|
||||
*/
|
||||
private final Map<RectD, SquaringGraphSeries.DirectionalRectanglePoint> mDataPoints = new HashMap<>();
|
||||
|
||||
/**
|
||||
* creates bar series with data
|
||||
*
|
||||
* @param data data points
|
||||
* important: array has to be sorted from lowest x-value to the highest
|
||||
*/
|
||||
public SquaringGraphSeries(SquaringGraphSeries.DirectionalRectanglePoint[] data) {
|
||||
super(data);
|
||||
mPaint = new Paint();
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the bars on the canvas
|
||||
*
|
||||
* @param graphView corresponding graphview
|
||||
* @param canvas canvas
|
||||
* @param isSecondScale whether we are plotting the second scale or not
|
||||
*/
|
||||
@Override
|
||||
public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) {
|
||||
|
||||
resetDataPoints();
|
||||
|
||||
// get data
|
||||
double maxX = graphView.getViewport().getMaxX(false);
|
||||
double minX = graphView.getViewport().getMinX(false);
|
||||
|
||||
double maxY;
|
||||
double minY;
|
||||
if (isSecondScale) {
|
||||
maxY = graphView.getSecondScale().getMaxY(false);
|
||||
minY = graphView.getSecondScale().getMinY(false);
|
||||
} else {
|
||||
maxY = graphView.getViewport().getMaxY(false);
|
||||
minY = graphView.getViewport().getMinY(false);
|
||||
}
|
||||
|
||||
/*
|
||||
// Iterate through all bar graph series
|
||||
// so we know how wide to make our bar,
|
||||
// and in what position to put it in
|
||||
int numBarSeries = 0;
|
||||
int currentSeriesOrder = 0;
|
||||
int numValues = 0;
|
||||
boolean isCurrentSeries;
|
||||
SortedSet<Double> xVals = new TreeSet<Double>();
|
||||
for(Series<?> inspectedSeries: graphView.getSeries()) {
|
||||
if(inspectedSeries instanceof SquaringGraphSeries) {
|
||||
isCurrentSeries = (inspectedSeries == this);
|
||||
if(isCurrentSeries) {
|
||||
currentSeriesOrder = numBarSeries;
|
||||
}
|
||||
numBarSeries++;
|
||||
|
||||
// calculate the number of slots for bars based on the minimum distance between
|
||||
// x coordinates in the series. This is divided into the range to find
|
||||
// the placement and width of bar slots
|
||||
// (sections of the x axis for each bar or set of bars)
|
||||
// TODO: Move this somewhere more general and cache it, so we don't recalculate it for each series
|
||||
Iterator<?> curValues = inspectedSeries.getValues(minX, maxX);
|
||||
if (curValues.hasNext()) {
|
||||
xVals.add(((DirectionalRectanglePoint)curValues.next()).getX());
|
||||
if(isCurrentSeries) { numValues++; }
|
||||
while (curValues.hasNext()) {
|
||||
xVals.add(((DirectionalRectanglePoint)curValues.next()).getX());
|
||||
if(isCurrentSeries) { numValues++; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numValues == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
double minGap = 0;
|
||||
|
||||
if(mDataWidth > 0.0) {
|
||||
minGap = mDataWidth;
|
||||
} else {
|
||||
Double lastVal = null;
|
||||
|
||||
for(Double curVal: xVals) {
|
||||
if(lastVal != null) {
|
||||
double curGap = Math.abs(curVal - lastVal);
|
||||
if (minGap == 0 || (curGap > 0 && curGap < minGap)) {
|
||||
minGap = curGap;
|
||||
}
|
||||
}
|
||||
lastVal = curVal;
|
||||
}
|
||||
}
|
||||
|
||||
int numBarSlots = (minGap == 0) ? 1 : (int)Math.round((maxX - minX)/minGap) + 1;
|
||||
*/
|
||||
|
||||
Iterator<SquaringGraphSeries.DirectionalRectanglePoint> values = getValues(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
|
||||
// Calculate the overall bar slot width - this includes all bars across
|
||||
// all series, and any spacing between sets of bars
|
||||
|
||||
double diffY = maxY - minY;
|
||||
double diffX = maxX - minX;
|
||||
double contentHeight = graphView.getGraphContentHeight();
|
||||
double contentWidth = graphView.getGraphContentWidth();
|
||||
double contentLeft = graphView.getGraphContentLeft();
|
||||
double contentTop = graphView.getGraphContentTop();
|
||||
|
||||
// draw data
|
||||
while (values.hasNext()) {
|
||||
SquaringGraphSeries.DirectionalRectanglePoint value = values.next();
|
||||
|
||||
double top = contentTop + (maxY-value.top)*contentHeight/diffY;
|
||||
|
||||
double bottom = contentTop + (maxY-value.bottom)*contentHeight/diffY;
|
||||
|
||||
double left = contentLeft + contentWidth*(value.left-minX)/diffX;
|
||||
|
||||
double right = contentLeft + contentWidth*(value.right-minX)/diffX;
|
||||
|
||||
|
||||
// hook for value dependent color
|
||||
if (value.color != -1) {
|
||||
int ncol = value.color&0xFFFFFF, nalp = value.color>>24;
|
||||
mPaint.setColor(ncol);
|
||||
mPaint.setAlpha(nalp);
|
||||
} else {
|
||||
mPaint.setColor(getColor());
|
||||
}
|
||||
|
||||
|
||||
// overdraw
|
||||
top = forceBetween(top, contentTop, contentTop+contentHeight);
|
||||
right = forceBetween(right, contentLeft,contentLeft+contentWidth);
|
||||
bottom = forceBetween(bottom, contentTop, contentTop+contentHeight);
|
||||
left = forceBetween(left, contentLeft,contentLeft+contentWidth);
|
||||
Log.d("SquaringGraphDrawer","Drawing rectangle "+top+";"+left+";"+bottom+";"+right);
|
||||
|
||||
mDataPoints.put(new RectD(left, top, right, bottom), value);
|
||||
|
||||
canvas.drawRect((float)left, (float)top, (float)right, (float)bottom, mPaint);
|
||||
|
||||
/*
|
||||
// set values on top of graph
|
||||
if (mDrawValuesOnTop) {
|
||||
if (reverse) {
|
||||
top = bottom + mValuesOnTopSize + 4;
|
||||
if (top > contentTop+contentHeight) top = contentTop + contentHeight;
|
||||
} else {
|
||||
top -= 4;
|
||||
if (top<=contentTop) top+=contentTop+4;
|
||||
}
|
||||
|
||||
mPaint.setColor(mValuesOnTopColor);
|
||||
canvas.drawText(
|
||||
graphView.getGridLabelRenderer().getLabelFormatter().formatLabel(value.getY(), false)
|
||||
, (float) (left+right)/2, (float) top, mPaint);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
public static double forceBetween(double value, double min, double max){
|
||||
return Math.max(Math.min(value,max),min);
|
||||
}
|
||||
|
||||
/**
|
||||
* resets the cached coordinates of the bars
|
||||
*/
|
||||
@Override
|
||||
protected void resetDataPoints() {
|
||||
mDataPoints.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* find the corresponding data point by
|
||||
* coordinates.
|
||||
*
|
||||
* @param x pixels
|
||||
* @param y pixels
|
||||
* @return datapoint or null
|
||||
*/
|
||||
@Override
|
||||
protected SquaringGraphSeries.DirectionalRectanglePoint findDataPoint(float x, float y) {
|
||||
for (Map.Entry<RectD, SquaringGraphSeries.DirectionalRectanglePoint> entry : mDataPoints.entrySet()) {
|
||||
if (x >= entry.getKey().left && x <= entry.getKey().right
|
||||
&& y >= entry.getKey().top && y <= entry.getKey().bottom) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelection(GraphView mGraphView, Canvas canvas, boolean b, DataPointInterface value) {
|
||||
// We do nothing more
|
||||
}
|
||||
|
||||
public static class DirectionalRectanglePoint implements DataPointInterface {
|
||||
|
||||
double top,left,bottom,right;
|
||||
int color;
|
||||
|
||||
public DirectionalRectanglePoint(double top, double left, double bottom, double right, int color) {
|
||||
this.top = top;
|
||||
this.left = left;
|
||||
this.bottom = bottom;
|
||||
this.right = right;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getX() {
|
||||
return left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return top;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,167 @@
|
||||
package com.bernard.emorph.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.bernard.emorph.EMorphApplication;
|
||||
import com.bernard.emorph.R;
|
||||
import com.bernard.emorph.SquaringGraphSeries;
|
||||
import com.bernard.emorph.model.ToGraph;
|
||||
import com.jjoe64.graphview.GraphView;
|
||||
import com.jjoe64.graphview.Viewport;
|
||||
import com.jjoe64.graphview.series.DataPoint;
|
||||
import com.jjoe64.graphview.series.PointsGraphSeries;
|
||||
import com.jjoe64.graphview.series.Series;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
public class GraphActivity extends AppCompatActivity {
|
||||
|
||||
public static final String TOGRAPH_TO_GRAPH_EXTRA = "com.bernard.emorph.activities.GraphActivity.toGraph";
|
||||
|
||||
ToGraph toGraph;
|
||||
GraphView gv;
|
||||
EMorphApplication theApp;
|
||||
int[] colors;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_graph);
|
||||
|
||||
Intent theIntent = getIntent();
|
||||
toGraph = theIntent.getParcelableExtra(TOGRAPH_TO_GRAPH_EXTRA);
|
||||
|
||||
theApp = (EMorphApplication) getApplication();
|
||||
|
||||
gv = findViewById(R.id.theGraphView);
|
||||
|
||||
String[] cs = getResources().getStringArray(R.array.distinctGraphColors);
|
||||
colors = new int[cs.length];
|
||||
for (int i = 0; i < colors.length; i++)
|
||||
colors[i] = Integer.parseInt(cs[i].substring(1),16);
|
||||
|
||||
|
||||
initGraph();
|
||||
|
||||
}
|
||||
|
||||
public static final double MEGA_MAX_IMG = 50;
|
||||
public static final double MEGA_MIN_IMG = -50;
|
||||
public static final double MEGA_MAX_IMM = 100;
|
||||
public static final double MEGA_MIN_IMM = 0;
|
||||
|
||||
|
||||
public void initGraph(){
|
||||
|
||||
int subjectCount = toGraph.getSubjectsID().length;
|
||||
DataPoint[] points0 = new DataPoint[subjectCount];
|
||||
double minx=1e10f,maxx=0f,miny=1e10f,maxy=0f;
|
||||
PointsGraphSeries[] pgs = new PointsGraphSeries[toGraph.getMeasuresID().length];
|
||||
for(int j=0; j<toGraph.getMeasuresID().length; j++) {
|
||||
|
||||
int realSize = 0;
|
||||
for (int i = 0; i < subjectCount; i++) {
|
||||
points0[i] = theApp.point(toGraph.getSubjectsID()[i], toGraph.getMeasuresID()[j]);
|
||||
if (points0[i] != null) {
|
||||
realSize++;
|
||||
if(minx>points0[i].getX())minx = points0[i].getX();
|
||||
if(maxx<points0[i].getX())maxx = points0[i].getX();
|
||||
if(miny>points0[i].getY())miny = points0[i].getY();
|
||||
if(maxy<points0[i].getY())maxy = points0[i].getY();
|
||||
}
|
||||
}
|
||||
Arrays.sort(points0,(d1,d2)->(d1==null)?((d2==null)?0:-1):((d2==null)?1:Double.compare(d1.getX(),d2.getX())));
|
||||
DataPoint[] points = new DataPoint[realSize];
|
||||
System.arraycopy(points0,0,points,0,realSize);
|
||||
PointsGraphSeries<DataPoint> series = new PointsGraphSeries<>(points);
|
||||
series.setShape(PointsGraphSeries.Shape.POINT);
|
||||
series.setColor(colors[j]|0xFF000000);
|
||||
series.setSize(10);
|
||||
pgs[j] = series;
|
||||
Log.d("NewSeries","Nouvelle serie de "+realSize+" points: couleur #"+Integer.toHexString(colors[j]));
|
||||
}
|
||||
|
||||
|
||||
// Calcul des valeurs limites
|
||||
double moyIMM, sdIMM, moyIMG, sdIMG;
|
||||
switch(toGraph.getBase()){
|
||||
case LABO_U11:
|
||||
moyIMM=14.9;
|
||||
sdIMM=1.3;
|
||||
moyIMG=4.4;
|
||||
sdIMG=2.5;
|
||||
break;
|
||||
case LABO_U13:
|
||||
moyIMM=15.6;
|
||||
sdIMM=1.8;
|
||||
moyIMG=4.7;
|
||||
sdIMG=1.9;
|
||||
break;
|
||||
case LABO_U15:
|
||||
moyIMM=18.5;
|
||||
sdIMM=2.0;
|
||||
moyIMG=6.7;
|
||||
sdIMG=2.4;
|
||||
break;
|
||||
default:
|
||||
// Là on s'amuse
|
||||
// On prend la moyenne et l'ecart type d'absolument toutes les valeurs.
|
||||
moyIMM = sdIMM = moyIMG = sdIMG = 0;
|
||||
int c = 0;
|
||||
for(PointsGraphSeries<?> s : pgs){
|
||||
Iterator<?> it = s.getValues(s.getLowestValueX(),s.getHighestValueX());
|
||||
while(it.hasNext()){
|
||||
DataPoint dp = (DataPoint) it.next(); // Ne devrait pas poser de problème.
|
||||
moyIMM += dp.getX();
|
||||
sdIMM += dp.getX()*dp.getX();
|
||||
moyIMG += dp.getY();
|
||||
sdIMG += dp.getY()*dp.getY();
|
||||
c++;
|
||||
}
|
||||
}
|
||||
moyIMM /= c;
|
||||
moyIMG /= c;
|
||||
sdIMM = Math.sqrt((sdIMM/c)-moyIMM*moyIMM);
|
||||
sdIMG = Math.sqrt((sdIMG/c)-moyIMG*moyIMG); // Je crois que les formules sont bonnes.
|
||||
}
|
||||
|
||||
Viewport theVP = gv.getViewport();
|
||||
theVP.setXAxisBoundsManual(true);
|
||||
theVP.setMinX(Math.min(minx,moyIMM-sdIMM)-.4);
|
||||
theVP.setMaxX(Math.max(maxx,moyIMM+sdIMM)+.4);
|
||||
theVP.setYAxisBoundsManual(true);
|
||||
theVP.setMinY(Math.min(miny,moyIMG-sdIMG)-.4);
|
||||
theVP.setMaxY(Math.max(maxy,moyIMG+sdIMG)+.4);
|
||||
|
||||
int interColor = 0x53FFFF00;
|
||||
int extremeColor = 0x53FF0000;
|
||||
|
||||
SquaringGraphSeries sgs = new SquaringGraphSeries(new SquaringGraphSeries.DirectionalRectanglePoint[]{
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(MEGA_MAX_IMG ,MEGA_MIN_IMM ,moyIMG+sdIMG,moyIMM-sdIMM,extremeColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG-sdIMG,MEGA_MIN_IMM ,MEGA_MIN_IMG,moyIMM-sdIMM,extremeColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG+sdIMG,MEGA_MIN_IMM ,moyIMG-sdIMG,moyIMM-sdIMM,interColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(MEGA_MAX_IMG ,moyIMM-sdIMM,moyIMG+sdIMG,moyIMM+sdIMM,interColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG-sdIMG,moyIMM-sdIMM,MEGA_MIN_IMG,moyIMM+sdIMM, interColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(MEGA_MAX_IMG ,moyIMM+sdIMM,moyIMG+sdIMG,MEGA_MAX_IMM,extremeColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG-sdIMG,moyIMM+sdIMM,MEGA_MIN_IMG,MEGA_MAX_IMM,extremeColor),
|
||||
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG+sdIMG,moyIMM+sdIMM,moyIMG-sdIMG,MEGA_MAX_IMM,interColor)
|
||||
});
|
||||
|
||||
gv.addSeries(sgs);
|
||||
|
||||
for (PointsGraphSeries<?> pg : pgs) gv.addSeries(pg);
|
||||
|
||||
}
|
||||
|
||||
public final int randCol(){
|
||||
Random r = new Random();
|
||||
return Color.HSVToColor(255, new float[]{r.nextFloat()*360,1.0f,1.0f});
|
||||
}
|
||||
}
|
||||
@ -49,6 +49,11 @@ public class GroupListActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
|
||||
public void startGraphGroup(Group g){
|
||||
Intent theIntent = new Intent(this, PrepareGraphActivity.class);
|
||||
theIntent.putExtra(PrepareGraphActivity.GROUPID_TO_GRAPH_EXTRA, g.id);
|
||||
startActivity(theIntent);
|
||||
}
|
||||
public void startModifyGroup(Group g){
|
||||
Intent theIntent = new Intent(this, EditSubjectListActivity.class);
|
||||
theIntent.putExtra(EditSubjectListActivity.GROUPID_EXTRA, g.id);
|
||||
@ -81,6 +86,9 @@ public class GroupListActivity extends AppCompatActivity {
|
||||
this.newDataButton = buttonsLayout.findViewById(R.id.new_data_button);
|
||||
this.modifyGroupButton = buttonsLayout.findViewById(R.id.modify_group_button);
|
||||
|
||||
this.dataViewButton.setOnClickListener((e)->{
|
||||
if(selectedIndex!=groups.size())startGraphGroup(groups.get(selectedIndex));
|
||||
});
|
||||
this.modifyGroupButton.setOnClickListener((e)->{
|
||||
if(selectedIndex==groups.size())
|
||||
startNewGroup();
|
||||
|
||||
@ -109,6 +109,8 @@ public class NewMeasureActivity extends AppCompatActivity {
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
class SubjectListAdapter extends RecyclerView.Adapter<NewMeasureActivity.SubjectListAdapter.ViewHolder> {
|
||||
|
||||
@ -0,0 +1,252 @@
|
||||
package com.bernard.emorph.activities;
|
||||
|
||||
import android.app.DatePickerDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bernard.emorph.EMorphApplication;
|
||||
import com.bernard.emorph.R;
|
||||
import com.bernard.emorph.model.Subject;
|
||||
import com.bernard.emorph.model.ToGraph;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PrepareGraphActivity extends AppCompatActivity {
|
||||
|
||||
public static final String GROUPID_TO_GRAPH_EXTRA = "com.bernard.emorph.activities.PrepareGraphActivity.GroupIDToGraph";
|
||||
|
||||
long groupID;
|
||||
|
||||
Spinner measuresSelectorSpinner;
|
||||
Set<Long> selectedMeasuresIDs;
|
||||
|
||||
CheckBox everySubjectCheckbox;
|
||||
List<Subject> subjects;
|
||||
Set<Long> selectedSubjects;
|
||||
RecyclerView rv;
|
||||
|
||||
Spinner basisSelectorSpinner;
|
||||
|
||||
Button okButton;
|
||||
|
||||
EMorphApplication theApp;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_prepare_graph);
|
||||
|
||||
Intent theIntent = getIntent();
|
||||
groupID = theIntent.getLongExtra(GROUPID_TO_GRAPH_EXTRA,-1L);
|
||||
|
||||
theApp = (EMorphApplication) getApplication();
|
||||
|
||||
measuresSelectorSpinner = findViewById(R.id.measureSelector);
|
||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.measureSelectorsTypes, android.R.layout.simple_spinner_item);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
measuresSelectorSpinner.setAdapter(adapter);
|
||||
|
||||
everySubjectCheckbox = findViewById(R.id.everySubjectCheckbox);
|
||||
|
||||
rv = findViewById(R.id.subjectsList);
|
||||
SubjectListAdapter sla = new SubjectListAdapter();
|
||||
rv.setAdapter(sla);
|
||||
rv.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
||||
basisSelectorSpinner = findViewById(R.id.basisSelector);
|
||||
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(this,
|
||||
R.array.basisTypes, android.R.layout.simple_spinner_item);
|
||||
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
basisSelectorSpinner.setAdapter(adapter2);
|
||||
|
||||
okButton = findViewById(R.id.okButton);
|
||||
|
||||
|
||||
selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID));
|
||||
measuresSelectorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
|
||||
switch(i){
|
||||
case 0: // Dernière
|
||||
selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID));
|
||||
return;
|
||||
case 1: // 5 dernières
|
||||
selectedMeasuresIDs = theApp.getXLastMeasures(groupID, 5);
|
||||
return;
|
||||
case 2: // x dernières
|
||||
|
||||
final AlertDialog.Builder d = new AlertDialog.Builder(PrepareGraphActivity.this);
|
||||
LayoutInflater inflater = PrepareGraphActivity.this.getLayoutInflater();
|
||||
View dialogView = inflater.inflate(R.layout.number_picker_dialog, null);
|
||||
d.setTitle(R.string.measureCountDialogTitle);
|
||||
d.setMessage(R.string.measureCountDialogMessage);
|
||||
d.setView(dialogView);
|
||||
final NumberPicker numberPicker = (NumberPicker) dialogView.findViewById(R.id.dialog_number_picker);
|
||||
numberPicker.setMaxValue(100);
|
||||
numberPicker.setMinValue(1);
|
||||
numberPicker.setWrapSelectorWheel(false);
|
||||
d.setPositiveButton(android.R.string.ok, (di,j)->selectedMeasuresIDs = theApp.getXLastMeasures(groupID, numberPicker.getValue()));
|
||||
d.setNegativeButton(android.R.string.cancel, (di,j)->selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID)));
|
||||
AlertDialog alertDialog = d.create();
|
||||
alertDialog.show();
|
||||
return;
|
||||
case 3: // à partir du
|
||||
Calendar mcurrentDate=Calendar.getInstance();
|
||||
int year = mcurrentDate.get(Calendar.YEAR);
|
||||
int month = mcurrentDate.get(Calendar.MONTH);
|
||||
int day = mcurrentDate.get(Calendar.DAY_OF_MONTH);
|
||||
DatePickerDialog mDatePicker=new DatePickerDialog(PrepareGraphActivity.this,
|
||||
(datepicker, selectedYear, selectedMonth, selectedDay) -> {
|
||||
Log.d("Date Selected", "Month: " + selectedMonth + " Day: " + selectedDay + " Year: " + selectedYear);
|
||||
Calendar selected = Calendar.getInstance();
|
||||
selected.set(selectedYear, selectedMonth, selectedDay);
|
||||
|
||||
selectedMeasuresIDs = theApp.getMeasuresSince(groupID, selected.getTimeInMillis()/1000);
|
||||
},year, month, day);
|
||||
mDatePicker.setOnDismissListener((e) -> measuresSelectorSpinner.setSelection(0));
|
||||
mDatePicker.setOnCancelListener((e) -> measuresSelectorSpinner.setSelection(0));
|
||||
mDatePicker.setTitle(R.string.sinceWhenDialog);
|
||||
mDatePicker.show();
|
||||
return;
|
||||
case 4: // Toutes
|
||||
selectedMeasuresIDs = theApp.getMeasuresIDs(groupID);
|
||||
return;
|
||||
default: // Spécifique
|
||||
//TODO: Faire un dialog permetant de sélectionner les mesures
|
||||
selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID));
|
||||
measuresSelectorSpinner.setSelection(0);
|
||||
Toast.makeText(PrepareGraphActivity.this, R.string.notImplementedYet, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
selectedMeasuresIDs = Collections.emptySet();
|
||||
}
|
||||
});
|
||||
|
||||
everySubjectCheckbox.setSelected(true);
|
||||
rv.setEnabled(false);
|
||||
everySubjectCheckbox.setOnCheckedChangeListener((e,b)-> {rv.setEnabled(!b);Log.d("Résultat","Check: "+b+"; Enablé: "+rv.isEnabled());});
|
||||
|
||||
subjects = theApp.getSubjects(groupID);
|
||||
selectedSubjects = new HashSet<>();
|
||||
for(Subject s : subjects)
|
||||
selectedSubjects.add(s.id);
|
||||
|
||||
|
||||
okButton.setOnClickListener((e)->drawGraph());
|
||||
|
||||
}
|
||||
|
||||
public ToGraph.Base selectedBasis(){
|
||||
//TODO Rework this
|
||||
switch(basisSelectorSpinner.getSelectedItemPosition()) {
|
||||
case 0:
|
||||
return ToGraph.Base.LABO_U11;
|
||||
case 1:
|
||||
return ToGraph.Base.LABO_U13;
|
||||
case 2:
|
||||
return ToGraph.Base.LABO_U15;
|
||||
default:
|
||||
return ToGraph.Base.GROUPE;
|
||||
}
|
||||
}
|
||||
|
||||
public void drawGraph(){
|
||||
ToGraph tg;
|
||||
if(everySubjectCheckbox.isChecked())
|
||||
tg = ToGraph.getS(selectedMeasuresIDs, subjects, selectedBasis());
|
||||
else
|
||||
tg = ToGraph.get(selectedMeasuresIDs, selectedSubjects, selectedBasis());
|
||||
|
||||
if(tg.getMeasuresID().length==0 || tg.getSubjectsID().length==0){
|
||||
Toast.makeText(this, R.string.cantGraphNoInput, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent drawGraphIntent = new Intent(this, GraphActivity.class);
|
||||
drawGraphIntent.putExtra(GraphActivity.TOGRAPH_TO_GRAPH_EXTRA, tg);
|
||||
startActivity(drawGraphIntent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class SubjectListAdapter extends RecyclerView.Adapter<PrepareGraphActivity.SubjectListAdapter.ViewHolder> {
|
||||
|
||||
public SubjectListAdapter(){}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PrepareGraphActivity.SubjectListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View theView = LayoutInflater.from(parent.getContext()).inflate(R.layout.preparegraph_subject_list_item, parent, false);
|
||||
|
||||
return new PrepareGraphActivity.SubjectListAdapter.ViewHolder(theView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PrepareGraphActivity.SubjectListAdapter.ViewHolder holder, int position) {
|
||||
holder.titleText.setText(subjects.get(position).name);
|
||||
|
||||
holder.subjectBox.setOnCheckedChangeListener((e,b) -> checkSubject(subjects.get(position),b));
|
||||
}
|
||||
|
||||
public void checkSubject(Subject s, boolean isChecked){
|
||||
if(isChecked)
|
||||
selectedSubjects.add(s.id);
|
||||
else
|
||||
selectedSubjects.remove(s.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return subjects.size();
|
||||
}
|
||||
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder{
|
||||
|
||||
TextView titleText;
|
||||
CheckBox subjectBox;
|
||||
View theView;
|
||||
|
||||
public ViewHolder(View theView) {
|
||||
super(theView);
|
||||
this.theView = theView;
|
||||
this.titleText = theView.findViewById(R.id.subjectNameText);
|
||||
this.subjectBox = theView.findViewById(R.id.subjectCheckbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,4 +64,19 @@ public class MeasureOnSubject implements Parcelable {
|
||||
p.writeFloat(cheville);
|
||||
p.writeFloat(avantBras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MeasureOnSubject{" +
|
||||
"mosId=" + mosId +
|
||||
", subjectID=" + subjectID +
|
||||
", abdomen=" + abdomen +
|
||||
", bras=" + bras +
|
||||
", epaules=" + epaules +
|
||||
", taille=" + taille +
|
||||
", cuisse=" + cuisse +
|
||||
", cheville=" + cheville +
|
||||
", avantBras=" + avantBras +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
package com.bernard.emorph.model;
|
||||
|
||||
public class ToGraph {
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ToGraph implements Parcelable {
|
||||
|
||||
long[] measuresID;
|
||||
|
||||
@ -8,8 +13,86 @@ public class ToGraph {
|
||||
|
||||
Base base;
|
||||
|
||||
enum Base {
|
||||
LABO, GROUPE;
|
||||
public enum Base {
|
||||
LABO_U11, LABO_U13, LABO_U15, GROUPE
|
||||
}
|
||||
public ToGraph(long[] measuresID, long[] subjectsID, Base base) {
|
||||
this.measuresID = measuresID;
|
||||
this.subjectsID = subjectsID;
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public static ToGraph get(Collection<Long> measuresID, Collection<Long> subjectsID, Base base) {
|
||||
return new ToGraph(longCollectionToLongArray(measuresID),longCollectionToLongArray(subjectsID),base);
|
||||
}
|
||||
|
||||
public static ToGraph getS(Collection<Long> measuresID, Collection<Subject> subjects, Base base) {
|
||||
return new ToGraph(longCollectionToLongArray(measuresID),subjectsCollectionToLongArray(subjects),base);
|
||||
}
|
||||
|
||||
private ToGraph(Parcel p){
|
||||
this.measuresID = new long[p.readInt()];
|
||||
p.readLongArray(this.measuresID);
|
||||
this.subjectsID = new long[p.readInt()];
|
||||
p.readLongArray(this.subjectsID);
|
||||
base = Base.values()[p.readInt()];
|
||||
}
|
||||
|
||||
public static final Creator<ToGraph> CREATOR = new Creator<ToGraph>() {
|
||||
@Override
|
||||
public ToGraph createFromParcel(Parcel parcel) {
|
||||
return new ToGraph(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToGraph[] newArray(int i) {
|
||||
return new ToGraph[i];
|
||||
}
|
||||
};
|
||||
|
||||
public long[] getMeasuresID() {
|
||||
return measuresID;
|
||||
}
|
||||
|
||||
public long[] getSubjectsID() {
|
||||
return subjectsID;
|
||||
}
|
||||
|
||||
public Base getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeInt(measuresID.length);
|
||||
parcel.writeLongArray(this.measuresID);
|
||||
parcel.writeInt(subjectsID.length);
|
||||
parcel.writeLongArray(this.subjectsID);
|
||||
parcel.writeInt(base.ordinal());
|
||||
}
|
||||
|
||||
public static long[] longCollectionToLongArray(Collection<Long> c){
|
||||
long[] mi = new long[c.size()];
|
||||
int i=0;
|
||||
for(Long m : c){
|
||||
mi[i] = m;
|
||||
i++;
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
public static long[] subjectsCollectionToLongArray(Collection<Subject> c){
|
||||
long[] mi = new long[c.size()];
|
||||
int i=0;
|
||||
for(Subject s : c){
|
||||
mi[i] = s.id;
|
||||
i++;
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activities.GraphActivity">
|
||||
|
||||
<com.jjoe64.graphview.GraphView
|
||||
android:id="@+id/theGraphView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
148
app/src/main/res/layout/activity_prepare_graph.xml
Normal file
148
app/src/main/res/layout/activity_prepare_graph.xml
Normal file
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activities.PrepareGraphActivity">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/app_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/measureSelectorLayout"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:elevation="4dp"
|
||||
app:title="@string/prepareGraphTitle"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/measureSelectorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/app_toolbar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/subjectsFieldLayout">
|
||||
<TextView
|
||||
android:id="@+id/measureSelectorLabel"
|
||||
android:labelFor="@id/measureSelector"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/measureSelector"
|
||||
android:text="@string/measureSelectorTitle"
|
||||
android:minHeight="48dp"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/measureSelector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/measureSelectorLabel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:minHeight="48dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/subjectsFieldLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/measureSelectorLayout"
|
||||
app:layout_constraintBottom_toTopOf="@id/basisSelectorLayout"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subjectFieldLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/subjectSelectTitle"
|
||||
app:layout_constraintBottom_toTopOf="@id/subjectsListScroll"
|
||||
app:layout_constraintEnd_toStartOf="@id/everySubjectCheckbox"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/everySubjectCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/subjectsListScroll"
|
||||
app:layout_constraintStart_toEndOf="@id/subjectFieldLabel"
|
||||
app:layout_constraintEnd_toStartOf="@id/everySubjectCheckboxLabel"
|
||||
android:checked="true"/>
|
||||
<TextView
|
||||
android:id="@+id/everySubjectCheckboxLabel"
|
||||
android:labelFor="@id/everySubjectCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/subjectsListScroll"
|
||||
app:layout_constraintStart_toEndOf="@id/everySubjectCheckbox"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textAppearance="@style/preparegraph_subjects_list_item"
|
||||
android:text="@string/everybody"/>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/subjectsListScroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/subjectFieldLabel">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/subjectsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</ScrollView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/basisSelectorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/subjectsFieldLayout"
|
||||
app:layout_constraintBottom_toTopOf="@id/okButton">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/basisSelectorLabel"
|
||||
android:labelFor="@id/basisSelector"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/basisSelector"
|
||||
android:minHeight="48dp"
|
||||
android:text="@string/basis"/>
|
||||
<Spinner
|
||||
android:id="@+id/basisSelector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/basisSelectorLabel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:minHeight="48dp"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/okButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/basisSelectorLayout"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:text="@string/drawGraph"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
13
app/src/main/res/layout/number_picker_dialog.xml
Normal file
13
app/src/main/res/layout/number_picker_dialog.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<NumberPicker
|
||||
android:id="@+id/dialog_number_picker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
32
app/src/main/res/layout/preparegraph_subject_list_item.xml
Normal file
32
app/src/main/res/layout/preparegraph_subject_list_item.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/subjectCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/subjectNameText"
|
||||
android:checked="true"/>
|
||||
<TextView
|
||||
android:id="@+id/subjectNameText"
|
||||
android:labelFor="@id/subjectCheckbox"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/subjectCheckbox"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:contentDescription="@string/subjectNameDesc"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
21
app/src/main/res/values/arrays.xml
Normal file
21
app/src/main/res/values/arrays.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="basisTypes">
|
||||
<item>@string/lab11Basis</item>
|
||||
<item>@string/lab13Basis</item>
|
||||
<item>@string/lab15Basis</item>
|
||||
<item>@string/localBasis</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="measureSelectorsTypes">
|
||||
<item>@string/lastMeasure</item>
|
||||
<item>@string/last5Measures</item>
|
||||
<item>@string/xlastMeasures</item>
|
||||
<item>@string/sinceMeasures</item>
|
||||
<item>@string/everyMeasure</item>
|
||||
<item>@string/customMeasures</item>
|
||||
</string-array>
|
||||
<string name="lab11Basis">Données U11</string>
|
||||
<string name="lab13Basis">Données U13</string>
|
||||
<string name="lab15Basis">Données U15</string>
|
||||
</resources>
|
||||
@ -7,4 +7,136 @@
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
|
||||
<string-array name="distinctGraphColors">
|
||||
|
||||
<item>#000000</item>
|
||||
<item>#FFFF00</item>
|
||||
<item>#1CE6FF</item>
|
||||
<item>#FF34FF</item>
|
||||
<item>#FF4A46</item>
|
||||
<item>#008941</item>
|
||||
<item>#006FA6</item>
|
||||
<item>#A30059</item>
|
||||
<item>#FFDBE5</item>
|
||||
<item>#7A4900</item>
|
||||
<item>#0000A6</item>
|
||||
<item>#63FFAC</item>
|
||||
<item>#B79762</item>
|
||||
<item>#004D43</item>
|
||||
<item>#8FB0FF</item>
|
||||
<item>#997D87</item>
|
||||
<item>#5A0007</item>
|
||||
<item>#809693</item>
|
||||
<item>#FEFFE6</item>
|
||||
<item>#1B4400</item>
|
||||
<item>#4FC601</item>
|
||||
<item>#3B5DFF</item>
|
||||
<item>#4A3B53</item>
|
||||
<item>#FF2F80</item>
|
||||
<item>#61615A</item>
|
||||
<item>#BA0900</item>
|
||||
<item>#6B7900</item>
|
||||
<item>#00C2A0</item>
|
||||
<item>#FFAA92</item>
|
||||
<item>#FF90C9</item>
|
||||
<item>#B903AA</item>
|
||||
<item>#D16100</item>
|
||||
<item>#DDEFFF</item>
|
||||
<item>#000035</item>
|
||||
<item>#7B4F4B</item>
|
||||
<item>#A1C299</item>
|
||||
<item>#300018</item>
|
||||
<item>#0AA6D8</item>
|
||||
<item>#013349</item>
|
||||
<item>#00846F</item>
|
||||
<item>#372101</item>
|
||||
<item>#FFB500</item>
|
||||
<item>#C2FFED</item>
|
||||
<item>#A079BF</item>
|
||||
<item>#CC0744</item>
|
||||
<item>#C0B9B2</item>
|
||||
<item>#C2FF99</item>
|
||||
<item>#001E09</item>
|
||||
<item>#00489C</item>
|
||||
<item>#6F0062</item>
|
||||
<item>#0CBD66</item>
|
||||
<item>#EEC3FF</item>
|
||||
<item>#456D75</item>
|
||||
<item>#B77B68</item>
|
||||
<item>#7A87A1</item>
|
||||
<item>#788D66</item>
|
||||
<item>#885578</item>
|
||||
<item>#FAD09F</item>
|
||||
<item>#FF8A9A</item>
|
||||
<item>#D157A0</item>
|
||||
<item>#BEC459</item>
|
||||
<item>#456648</item>
|
||||
<item>#0086ED</item>
|
||||
<item>#886F4C</item>
|
||||
<item>#34362D</item>
|
||||
<item>#B4A8BD</item>
|
||||
<item>#00A6AA</item>
|
||||
<item>#452C2C</item>
|
||||
<item>#636375</item>
|
||||
<item>#A3C8C9</item>
|
||||
<item>#FF913F</item>
|
||||
<item>#938A81</item>
|
||||
<item>#575329</item>
|
||||
<item>#00FECF</item>
|
||||
<item>#B05B6F</item>
|
||||
<item>#8CD0FF</item>
|
||||
<item>#3B9700</item>
|
||||
<item>#04F757</item>
|
||||
<item>#C8A1A1</item>
|
||||
<item>#1E6E00</item>
|
||||
<item>#7900D7</item>
|
||||
<item>#A77500</item>
|
||||
<item>#6367A9</item>
|
||||
<item>#A05837</item>
|
||||
<item>#6B002C</item>
|
||||
<item>#772600</item>
|
||||
<item>#D790FF</item>
|
||||
<item>#9B9700</item>
|
||||
<item>#549E79</item>
|
||||
<item>#FFF69F</item>
|
||||
<item>#201625</item>
|
||||
<item>#72418F</item>
|
||||
<item>#BC23FF</item>
|
||||
<item>#99ADC0</item>
|
||||
<item>#3A2465</item>
|
||||
<item>#922329</item>
|
||||
<item>#5B4534</item>
|
||||
<item>#FDE8DC</item>
|
||||
<item>#404E55</item>
|
||||
<item>#0089A3</item>
|
||||
<item>#CB7E98</item>
|
||||
<item>#A4E804</item>
|
||||
<item>#324E72</item>
|
||||
<item>#6A3A4C</item>
|
||||
<item>#83AB58</item>
|
||||
<item>#001C1E</item>
|
||||
<item>#D1F7CE</item>
|
||||
<item>#004B28</item>
|
||||
<item>#C8D0F6</item>
|
||||
<item>#A3A489</item>
|
||||
<item>#806C66</item>
|
||||
<item>#222800</item>
|
||||
<item>#BF5650</item>
|
||||
<item>#E83000</item>
|
||||
<item>#66796D</item>
|
||||
<item>#DA007C</item>
|
||||
<item>#FF1A59</item>
|
||||
<item>#8ADBB4</item>
|
||||
<item>#1E0200</item>
|
||||
<item>#5B4E51</item>
|
||||
<item>#C895C5</item>
|
||||
<item>#320033</item>
|
||||
<item>#FF6832</item>
|
||||
<item>#66E1D3</item>
|
||||
<item>#CFCDAC</item>
|
||||
<item>#D0AC94</item>
|
||||
<item>#7ED379</item>
|
||||
<item>#012C58</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@ -48,5 +48,24 @@
|
||||
<string name="terminerLaMesure">Terminer la mesure</string>
|
||||
<string name="completeMeasureWithoutEveryoneTitle">Terminer la mesure ?</string>
|
||||
<string name="completeMeasureWithoutEveryone">Voulez-vous vraiment terminer la mesure, bien que %s n\'ai pas de nouvelle entrée ?</string>
|
||||
|
||||
<string name="measureSelectorTitle">"Mesure : "</string>
|
||||
<string name="everybody">Tous</string>
|
||||
<string name="basis">"Base : "</string>
|
||||
<string name="drawGraph">Dessiner !</string>
|
||||
<string name="labBasis">Échantillon du labo</string>
|
||||
<string name="localBasis">Échantillon local</string>
|
||||
<string name="lastMeasure">Dernière</string>
|
||||
<string name="last5Measures">5 dernières</string>
|
||||
<string name="xlastMeasures">x dernières</string>
|
||||
<string name="sinceMeasures">depuis le</string>
|
||||
<string name="everyMeasure">Toutes</string>
|
||||
<string name="customMeasures">Défini</string>
|
||||
<string name="cantGraphNoInput">Aucune mesure ou aucun sujet sélectionné.</string>
|
||||
<string name="subjectNameDesc">Nom du sujet</string>
|
||||
<string name="sinceWhenDialog">Depuis quelle date voulez vous voir les mesures ?</string>
|
||||
<string name="measureCountDialogTitle">Selection des mesures</string>
|
||||
<string name="measureCountDialogMessage">Combien de mesures en arrière faut-il observer ?</string>
|
||||
<string name="notImplementedYet">Fonctionnalitée pas encore implémentée.</string>
|
||||
<string name="subjectSelectTitle">Sélection des sujets</string>
|
||||
<string name="prepareGraphTitle">Préparation du graphique</string>
|
||||
</resources>
|
||||
@ -11,6 +11,10 @@
|
||||
<style name="group_list_newgroup_item_text" parent="TextAppearance.AppCompat.Body1">
|
||||
<item name="android:textStyle">italic</item>
|
||||
</style>
|
||||
<style name="preparegraph_subjects_list_item" parent="TextAppearance.AppCompat.Body1">
|
||||
<item name="android:textStyle">italic</item>
|
||||
<item name="sizePercent">60</item>
|
||||
</style>
|
||||
|
||||
<style name="group_list_item_text_selected" parent="group_list_item_text">
|
||||
<item name="android:textStyle">bold</item>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user