Integrado el nuevo sistema del PCBContext. Añadido popup de Cargando datos.

parent 60ea3ee3
...@@ -21,7 +21,7 @@ android { ...@@ -21,7 +21,7 @@ android {
resValue "bool", "force_img_download", "false" resValue "bool", "force_img_download", "false"
resValue "integer", "netservice_timing", "20" resValue "integer", "netservice_timing", "20"
resValue "integer", "rows", "5" resValue "integer", "rows", "5"
resValue "integer", "columns", "10" resValue "integer", "columns", "8"
} }
debug { debug {
...@@ -31,7 +31,7 @@ android { ...@@ -31,7 +31,7 @@ android {
resValue "bool", "force_img_download", "false" resValue "bool", "force_img_download", "false"
resValue "integer", "netservice_timing", "20" resValue "integer", "netservice_timing", "20"
resValue "integer", "rows", "5" resValue "integer", "rows", "5"
resValue "integer", "columns", "10" resValue "integer", "columns", "8"
} }
} }
productFlavors { productFlavors {
......
...@@ -32,6 +32,11 @@ package com.yottacode.net; ...@@ -32,6 +32,11 @@ package com.yottacode.net;
* *
* @author dofer * @author dofer
*/ */
/**
* Modificado por: magc
* LastUpdate: 22 de enero de 2016
*/
public class RestapiWrapper { public class RestapiWrapper {
String server; String server;
String token; String token;
...@@ -53,6 +58,8 @@ public class RestapiWrapper { ...@@ -53,6 +58,8 @@ public class RestapiWrapper {
} }
public void ask(String operation, Hashtable<String, String> params, String postOrGet, iRestapiListener listener) { public void ask(String operation, Hashtable<String, String> params, String postOrGet, iRestapiListener listener) {
// call preExecute listener to show loading window
listener.preExecute();
// call AsynTask to perform network operation on separate thread // call AsynTask to perform network operation on separate thread
if (this.token != null) { if (this.token != null) {
......
...@@ -12,6 +12,7 @@ import org.json.JSONObject; ...@@ -12,6 +12,7 @@ import org.json.JSONObject;
* @author dofer * @author dofer
*/ */
public interface iRestapiListener { public interface iRestapiListener {
public void preExecute();
public void result(JSONArray result); public void result(JSONArray result);
public void result(JSONObject result); public void result(JSONObject result);
public void error(Exception e); public void error(Exception e);
......
...@@ -61,6 +61,11 @@ public class ActionLog implements iRestapiListener { ...@@ -61,6 +61,11 @@ public class ActionLog implements iRestapiListener {
} }
@Override @Override
public void preExecute() {
}
@Override
public void result(JSONArray result) { public void result(JSONArray result) {
} }
......
...@@ -134,12 +134,17 @@ public class Vocabulary implements Iterable<Picto>, iRestapiListener, iVocabular ...@@ -134,12 +134,17 @@ public class Vocabulary implements Iterable<Picto>, iRestapiListener, iVocabular
imageInFile.read(imageData); imageInFile.read(imageData);
Hashtable<String,String> params=new Hashtable<>(3); Hashtable<String,String> params=new Hashtable<>(3);
params.put("filename", name); params.put("filename", name);
params.put("folder","custompictos"); params.put("folder", "custompictos");
params.put("id",String.valueOf(PCBcontext.getPcbdb().getCurrentUser().get_id_stu())); params.put("id", String.valueOf(PCBcontext.getPcbdb().getCurrentUser().get_id_stu()));
params.put("file", String.valueOf(imageData)); params.put("file", String.valueOf(imageData));
PCBcontext.getRestapiWrapper().ask("upload", params, "post", new iRestapiListener() { PCBcontext.getRestapiWrapper().ask("upload", params, "post", new iRestapiListener() {
@Override @Override
public void preExecute() {
}
@Override
public void result(JSONArray result) { public void result(JSONArray result) {
} }
...@@ -291,6 +296,11 @@ public class Vocabulary implements Iterable<Picto>, iRestapiListener, iVocabular ...@@ -291,6 +296,11 @@ public class Vocabulary implements Iterable<Picto>, iRestapiListener, iVocabular
} }
@Override @Override
public void preExecute() {
}
@Override
public void result(JSONArray result) { public void result(JSONArray result) {
if (result!=null) { if (result!=null) {
......
...@@ -3,6 +3,7 @@ package com.yottacode.pictogram.gui; ...@@ -3,6 +3,7 @@ package com.yottacode.pictogram.gui;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
...@@ -43,14 +44,23 @@ import java.util.Vector; ...@@ -43,14 +44,23 @@ import java.util.Vector;
public class LoginActivity extends FragmentActivity implements iRestapiListener, iImgDownloaderListener { public class LoginActivity extends FragmentActivity implements iRestapiListener, iImgDownloaderListener {
private static final String TAG_STUDENT = "student"; private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_SURNAME = "surname";
private static final String TAG_GENDER = "gender";
private static final String TAG_PIC = "pic";
private static final String TAG_LANG = "lang";
private static final String TAG_ATTRIBUTES = "attributes";
private static final String TAG_SUPERVISOR = "supervisor"; private int sup_id;
// String constant for logs // String constant for logs
private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName() private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName()
//PCBcontext pcb; //A ProgressDialog object
private ProgressDialog progressDialog;
private String token=null;
/** /**
* If there is Internet connection it calls the WS to recover the pairs student-supervisor * If there is Internet connection it calls the WS to recover the pairs student-supervisor
...@@ -91,15 +101,11 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -91,15 +101,11 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
//startLockTask(); //startLockTask();
// FIN del modo Kiosko // FIN del modo Kiosko
// Singleton getInstance
//pcb = PCBcontext.getInstance();
//NetService service= PCBcontext.getNetService();
// Llamo al WS para coger los usuarios y los supervisores de este dispositivo // Llamo al WS para coger los usuarios y los supervisores de este dispositivo
SSLDummyContext.init(getResources().getBoolean(R.bool.ssl_connect)); SSLDummyContext.init(getResources().getBoolean(R.bool.ssl_connect));
PCBcontext.init(this); PCBcontext.init(this);
// Compruebo si tengo acceso a internet
//if (!PCBcontext.getRestapiWrapper().ping("/server/ping", this)) {
// Compruebo si tengo acceso a internet
if (!RestapiWrapper.ping(getResources().getString(R.string.server),"server/ping",this)) { if (!RestapiWrapper.ping(getResources().getString(R.string.server),"server/ping",this)) {
// No puedo comprobar si el serial es válido. Muestro un alertdialog de error, y cierro la aplicación // No puedo comprobar si el serial es válido. Muestro un alertdialog de error, y cierro la aplicación
AlertDialog alertDialog = new AlertDialog.Builder( AlertDialog alertDialog = new AlertDialog.Builder(
...@@ -114,19 +120,16 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -114,19 +120,16 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
}); });
alertDialog.show(); alertDialog.show();
} else{ } else{
// QUITAR LUEGO !!!! // NUEVO
// Esto lo hago porque la reinstalar la app cada vez que lo pruebo, borra la bbdd y no deja guardados los datos de deviceID y token sup_id = getIntent().getExtras().getInt("sup_id");
//PCBcontext.getDevice().setDeviceID("85"); token = getIntent().getExtras().getString("token");
//PCBcontext.getDevice().setToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkZXNjIjoiU00tVDMzMCIsImlkIjoxNzYsImlkRmlybXdhcmUiOiJwcnVlYmFfMTIzNSIsImlhdCI6MTQ0NDM5MDQ5M30.SRJSMWxdenCwecsHIshqh4QEYqFCytI_aHajeVHTT20");
//String deviceID = PCBcontext.getDevice().getDeviceID();
RestapiWrapper wrapper = new RestapiWrapper(
getApplicationContext().getResources().getString(R.string.server),token);
RestapiWrapper wrapper = PCBcontext.getRestapiWrapper(); String operation = "sup/" + sup_id + "/students"; // SEGUIR
//String operation = "/dev/" + deviceID + "/users";
String operation = ""; // SEGUIR
Log.d("LoginActivity onCreate", "operation:" + operation); Log.d(LOG_TAG, "operation:" + operation);
//Este método es el que lanza la peticion asincrona //Este método es el que lanza la peticion asincrona
wrapper.ask(operation, this); wrapper.ask(operation, this);
...@@ -141,10 +144,16 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -141,10 +144,16 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
} }
@Override @Override
public void preExecute(){
progressDialog = ProgressDialog.show(LoginActivity.this,"Cargando...",
"Cargando datos de los alumnos, espere por favor...", false, false);
}
@Override
public void result(JSONArray students_supervisors) { //FERNANDO public void result(JSONArray students_supervisors) { //FERNANDO
try { try {
// Saco los pares estudiante-supervisor // Saco los pares estudiante-supervisor
Log.d("LoginActivity:result", "students_supervisors size:" + students_supervisors.length()); Log.d(LOG_TAG, "students_supervisors size:" + students_supervisors.length());
// looping through All Students // looping through All Students
Vector<User> users = new Vector<User>(students_supervisors.length()); Vector<User> users = new Vector<User>(students_supervisors.length());
...@@ -165,52 +174,53 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -165,52 +174,53 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
alert.show(); alert.show();
} }
User student = null;
for (int i = 0; i < students_supervisors.length(); i++) { for (int i = 0; i < students_supervisors.length(); i++) {
//Log.e("onPostExecute", "i vale:" + i); //Log.e("onPostExecute", "i vale:" + i);
JSONObject st = students_supervisors.getJSONObject(i); JSONObject st = students_supervisors.getJSONObject(i);
/* Integer st_id = st.getInt(TAG_ID);
JSONObject student = st.getJSONObject(TAG_STUDENT); String st_name = st.getString(TAG_NAME);
Integer st_id = student.getInt(TAG_ID); String st_surname = st.getString(TAG_SURNAME);
String st_name = student.getString(TAG_NAME); String st_pic = st.getString(TAG_PIC);
String st_surname = student.getString(TAG_SURNAME); String st_gender = st.getString(TAG_GENDER);
String st_pic = student.getString(TAG_PIC); String st_lang = st.getString(TAG_LANG);
String st_gender = student.getString(TAG_GENDER); //st_lang = "es-es";
String st_lang = student.getString(TAG_LANG); String st_attributes = st.getString(TAG_ATTRIBUTES);
st_lang = "es-es";
String st_attributes = student.getString(TAG_ATTRIBUTES); //Log.d(LOG_TAG, "student pic:" + st_pic);
Log.d("LoginActivity:result", "student pic:" + st_pic);
// ESTA PARTE DE SUPERVISORES SE PUEDE ELIMINAR
JSONObject supervisor = st.getJSONObject(TAG_SUPERVISOR);
Integer su_id = supervisor.getInt(TAG_ID);
String su_name = supervisor.getString(TAG_NAME);
String su_surname = supervisor.getString(TAG_SURNAME);
String su_pic = supervisor.getString(TAG_PIC);
String su_gender = supervisor.getString(TAG_GENDER);
String su_lang = supervisor.getString(TAG_LANG);
//if (su_lang.equals("es"))
su_lang = "es-es"; // QUITAR Y DESCOMENTAR LO ANTERIOR
String su_tts_engine_sup = supervisor.getString(TAG_TTSENGINE);
// Añado un par <student-supervisor> // Añado un par <student-supervisor>
int st_id_int = st_id.intValue(); int st_id_int = st_id.intValue();
int su_id_int = su_id.intValue(); student = new User(st_id_int, st_name, st_surname, st_pic, st_gender, st_lang, st_attributes,
sup_id, "", "", "", "M", "es-es", "");
// NOTA !!!! Esta parte se puede optimizar porque sólo debe salir un supervisor a partir del registro users.add(student);
}
users.add(new User(st_id_int, st_name, st_surname, st_pic, st_gender, st_lang, st_attributes, // Si sólo hay 1 estudiante, cargo el st_id
su_id_int, su_name, su_surname, su_pic, su_gender, su_lang, su_tts_engine_sup)); if (students_supervisors.length() == 1){
*/ //User student = PCBcontext.getDevice().findUser(st_id_int, sup_id);
PCBcontext.set_user(student, token, this);
} else{
student = new User(-1, "", "", "", "M", "es-es", "",
sup_id, "", "", "", "M", "es-es", "");
PCBcontext.set_user(student, token, this);
} }
//Device device = new Device(getApplicationContext(), null, 1); //Device device = new Device(getApplicationContext(), null, 1);
if (students_supervisors.length() > 0){ if (users.size() > 0){
PCBcontext.getDevice().synchronizeUsers(users, this); PCBcontext.getDevice().synchronizeUsers(users, this);
PCBcontext.getDevice().deleteDeprecatedImgs(); PCBcontext.getDevice().deleteDeprecatedImgs();
// Si sólo hay 1 estudiante paso a Pictogram
if (users.size() == 1){
//close the progress dialog
progressDialog.dismiss();
Intent pictogramActivity = new Intent(this, PictogramActivity.class);
startActivity(pictogramActivity);
}
} else{ } else{
AlertDialog.Builder builder = AlertDialog.Builder builder =
new AlertDialog.Builder(this); new AlertDialog.Builder(this);
...@@ -236,7 +246,6 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -236,7 +246,6 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
@Override @Override
public void result(JSONObject result) { public void result(JSONObject result) {
} }
@Override @Override
...@@ -248,19 +257,10 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -248,19 +257,10 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
Vector<User> users = PCBcontext.getDevice().getUsers(); Vector<User> users = PCBcontext.getDevice().getUsers();
if (users.size()>1){ if (users.size()>1){
setContentView(R.layout.activity_login); //close the progress dialog
} progressDialog.dismiss();
else{
// SEGUIR. Sólo tengo 1 usuario, así que no hace falta que cargue Login
PCBcontext.getDevice().setLastStuId(users.elementAt(0).get_id_stu());
// Si tiene SupID se saca del registro
//PCBcontext.getDevice().setSupId(-1);
//Log.d(LOG_TAG, "SET id_alumno:" + students_ids.elementAt(pos) + " /id_supervisor:-1"); setContentView(R.layout.activity_login);
Intent pictogramActivity = new Intent(this, PictogramActivity.class);
startActivity(pictogramActivity);
} }
}catch(NullPointerException e){ }catch(NullPointerException e){
e.printStackTrace(); e.printStackTrace();
...@@ -275,7 +275,16 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener, ...@@ -275,7 +275,16 @@ public class LoginActivity extends FragmentActivity implements iRestapiListener,
@Override @Override
public void loadImg(Img img) { public void loadImg(Img img) {
Log.d(LOG_TAG, "Load a single image with ID: " + img.get_id()); Log.d(LOG_TAG, "Load a single image with ID: " + img.get_id());
setContentView(R.layout.activity_login); // Aquí filtro si sólo tiene un único usuario o varios
Vector<User> users = null;
try {
users = PCBcontext.getDevice().getUsers();
if (users.size()>1){
setContentView(R.layout.activity_login);
}
} catch (JSONException e) {
e.printStackTrace();
}
} }
@Override protected void onResume() { @Override protected void onResume() {
......
...@@ -58,21 +58,16 @@ import java.util.Locale; ...@@ -58,21 +58,16 @@ import java.util.Locale;
import android.provider.Settings.Secure; import android.provider.Settings.Secure;
public class PictogramActivity extends Activity implements iVocabularyListener, iImgDownloaderListener, TextToSpeech.OnInitListener { public class PictogramActivity extends Activity implements iVocabularyListener, TextToSpeech.OnInitListener {
PanelAdapter panelAdapter; PanelAdapter panelAdapter;
TapeAdapter tapeAdapter; TapeAdapter tapeAdapter;
//PCBDBHelper pcbdb;
//Device device;
//Room room;
Vocabulary vocabulary; Vocabulary vocabulary;
User student; User student;
Context context; Context context;
//PCBcontext pcb;
Picto actualCategory; Picto actualCategory;
TextToSpeech tts; TextToSpeech tts;
...@@ -98,30 +93,31 @@ public class PictogramActivity extends Activity implements iVocabularyListener, ...@@ -98,30 +93,31 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
Log.d(LOG_TAG, "1) Opening PCB"); Log.d(LOG_TAG, "1) Opening PCB");
SSLDummyContext.init(getResources().getBoolean(R.bool.ssl_connect)); SSLDummyContext.init(getResources().getBoolean(R.bool.ssl_connect));
PCBcontext.init(this);
Log.d(LOG_TAG, "PCBcontext iniciado");
// Redundante, pero lo hago para forzarlo
/*
student = PCBcontext.getPcbdb().getCurrentUser();
String jsonToken = PCBcontext.getRestapiWrapper().getToken();
Log.d(LOG_TAG, "student name:" + student.get_name_stu());
PCBcontext.set_user(student,jsonToken, this);
*/
// Cargo los datos del alumno y el supervisor seleccionado // Adapter for grid
panelAdapter = new PanelAdapter(new LinkedList<Picto>());
//Log.d(LOG_TAG, "student name:" + student.get_name_stu());
// Create user. QUITAR cuando cargue bien el student con find_user
//student = new User(73, "Alumno", "Con Pictogramas", "http://www4.ujaen.es/~dofer/pictures/student/rosa.jpg", "M", "es-es", "");
// QUITAR cuando esté funcionando, porque debe coger de antes estos valores
//PCBcontext.getDevice().setToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkZXNjIjoiTlZpZGlhIFNoaWVsZCIsImlkIjoxNjUsImlkRmlybXdhcmUiOiJBTkRST0lEXzMyIiwiaWF0IjoxNDQyOTAzMzY3fQ.m-jbcEBQceWLZKda6fKMow_dg_fAwK9Nys00QA-gNwY");
//PCBcontext.getDevice().setSerial("serial1");
//PCBcontext.getDevice().setDeviceID("deviceID");
//Log.d(LOG_TAG, "2) OnCreate - Serial:" + pcb.getDevice().getSerial() + " dev. id:" + pcb.getDevice().getDeviceID() + " token:" + pcb.getDevice().getToken());
// Init PCB DB
this.vocabulary=PCBcontext.getVocabulary();
// Open websocket connection
vocabulary.listen(PCBcontext.getRoom(),this);
this.vocabulary=PCBcontext.getVocabulary();
if (this.vocabulary != null && this.vocabulary.size() > 0){
Log.d(LOG_TAG, "Vocabulario correcto de tam:" + this.vocabulary.size());
LinkedList<Picto> ll;
if(actualCategory != null) ll = order(vocabulary.next(actualCategory));
else ll = order(vocabulary.startSentence());
panelAdapter.clear();
panelAdapter.addAll(ll);
}
// Open websocket connection
vocabulary.listen(PCBcontext.getRoom(),this);
// Connect the views // Connect the views
final GridView tapeGridView = (GridView) findViewById(R.id.tape_grid_view); final GridView tapeGridView = (GridView) findViewById(R.id.tape_grid_view);
...@@ -144,8 +140,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener, ...@@ -144,8 +140,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
if (pictogramSize==0) panelGridView.setNumColumns(10); if (pictogramSize==0) panelGridView.setNumColumns(10);
else if (pictogramSize==1) panelGridView.setNumColumns(4); else if (pictogramSize==1) panelGridView.setNumColumns(4);
// Adapter for grid
panelAdapter = new PanelAdapter(new LinkedList<Picto>());
panelGridView.setAdapter(panelAdapter); panelGridView.setAdapter(panelAdapter);
// Adapter for tape // Adapter for tape
...@@ -377,7 +371,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener, ...@@ -377,7 +371,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
/** /**
* Load pictos. Asociado a botón provisional para cargar el vocabulario en el adapter * Load pictos. Asociado a botón provisional para cargar el vocabulario en el adapter
* @param v * @param v
* BORRAR. Ya funciona la carga asíncrona del vocabulario
*/ */
public void load_pictos(View v) { public void load_pictos(View v) {
if(vocabulary != null) if(vocabulary != null)
...@@ -397,26 +390,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener, ...@@ -397,26 +390,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
} }
/** /**
* Go back. Asociado al botón "volver" carga los pictos anteriores al actual del vocabulario
* @param v
* TODO ¿Quitar? ¿O asociar a otro evento?
*/
public void go_back(View v) {
try {
actualCategory = null;
LinkedList<Picto> ll = order(vocabulary.startSentence());
panelAdapter.clear();
panelAdapter.addAll(ll);
} catch (NullPointerException e){
Log.d(LOG_TAG, "El vocabulario todavía no se ha cargado");
}
}
/**
* Order a linked list of pictos with "blank spaces" between them * Order a linked list of pictos with "blank spaces" between them
* @param list * @param list
* @return * @return
...@@ -527,31 +500,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener, ...@@ -527,31 +500,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
} }
} }
// De la interfaz iImgDownloaderListener
@Override
public void loadComplete() {
Log.d(LOG_TAG, "Load images complete");
try {
vocabulary = PCBcontext.getVocabulary();
LinkedList<Picto> ll;
if(actualCategory != null) ll = order(vocabulary.next(actualCategory));
else ll = order(vocabulary.startSentence());
panelAdapter.clear();
panelAdapter.addAll(ll);
}catch(NullPointerException e){
Log.d(LOG_TAG, "El vocabulario todavía no se ha cargado");
}
}
// De la interfaz iImgDownloaderListener
@Override
public void loadImg(Img img) {
Log.d(LOG_TAG, "Load a single image with ID: " + img.get_id());
}
// Disable Back Button --> Kiosk mode // Disable Back Button --> Kiosk mode
@Override @Override
public void onBackPressed() { public void onBackPressed() {
......
...@@ -2,6 +2,7 @@ package com.yottacode.pictogram.gui; ...@@ -2,6 +2,7 @@ package com.yottacode.pictogram.gui;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
...@@ -61,13 +62,10 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -61,13 +62,10 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
Context context; Context context;
//String s_serial = new String();
//String _ANDROIDID = new String();
private static final String TAG_USER = "user"; private static final String TAG_USER = "user";
private static final String TAG_ISSTUDENT = "isStudent";
private static final String TAG_TOKEN = "token"; private static final String TAG_TOKEN = "token";
private static final String TAG_ID = "id"; private static final String TAG_ID = "id";
private static final String TAG_USERNAME = "username";
private static final String TAG_NAME = "name"; private static final String TAG_NAME = "name";
private static final String TAG_SURNAME = "surname"; private static final String TAG_SURNAME = "surname";
private static final String TAG_GENDER = "gender"; private static final String TAG_GENDER = "gender";
...@@ -76,11 +74,16 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -76,11 +74,16 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
private static final String TAG_ATTRIBUTES = "attributes"; private static final String TAG_ATTRIBUTES = "attributes";
//private static final String TAG_TTSENGINE = "ttsEngine"; //private static final String TAG_TTSENGINE = "ttsEngine";
Integer st_id=-1, su_id=-1; private Integer st_id=-1;
// String constant for logs // String constant for logs
private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName() private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName()
private String username = null;
//A ProgressDialog object
private ProgressDialog progressDialog;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
...@@ -123,31 +126,20 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -123,31 +126,20 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
mEntrarButton.setOnClickListener(new OnClickListener() { mEntrarButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
// No necesita token username = mSerialViewMail.getText().toString();
//String token = "0";
/* QUITAR
String username = mSerialViewMail.getText().toString();
String password = mSerialViewPass.getText().toString(); String password = mSerialViewPass.getText().toString();
*/
// DE PRUEBA // DE PRUEBA
/* // Alumno
String username = "faf0001"; //username = "faf0001";
String password = "faf0001"; //password = "faf0001";
*/ // Supervisor
String username = "dofer@ujaen.es"; username = "dofer@ujaen.es";
String password = "dofer"; password = "dofer";
RestapiWrapper wrapper = PCBcontext.getRestapiWrapper(); RestapiWrapper wrapper = PCBcontext.getRestapiWrapper();
//String serial = mSerialView.getText().toString();
//String serial = "0yhHcxMUcm"; // QUITAR
if (username.contains("@")){ if (username.contains("@")){
// Es un supervisor // Es un supervisor
String operation = "sup/login"; String operation = "sup/login";
//s_serial = serial;
//String _ANDROIDID = Settings.Secure.getString(getContentResolver(),Settings.Secure.ANDROID_ID);
//SecureRandom random = new SecureRandom();
//Log.d("SerialActivity onCreate", "ANDROID ID:" + _ANDROIDID);
//String _MODEL = android.os.Build.MODEL;
Hashtable<String, String> postDataParams = new Hashtable<String, String>(); Hashtable<String, String> postDataParams = new Hashtable<String, String>();
postDataParams.put("email", username); postDataParams.put("email", username);
...@@ -161,11 +153,6 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -161,11 +153,6 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
} else{ } else{
// Es un estudiante // Es un estudiante
String operation = "stu/login"; String operation = "stu/login";
//s_serial = serial;
//String _ANDROIDID = Settings.Secure.getString(getContentResolver(),Settings.Secure.ANDROID_ID);
//SecureRandom random = new SecureRandom();
//Log.d("SerialActivity onCreate", "ANDROID ID:" + _ANDROIDID);
//String _MODEL = android.os.Build.MODEL;
Hashtable<String, String> postDataParams = new Hashtable<String, String>(); Hashtable<String, String> postDataParams = new Hashtable<String, String>();
postDataParams.put("username", username); postDataParams.put("username", username);
...@@ -179,45 +166,14 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -179,45 +166,14 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
} }
} }
}); });
}
}
/* @Override
Button mOmitirButton = (Button) findViewById(R.id.omitir_button); public void preExecute(){
mOmitirButton.setOnClickListener(new OnClickListener() { if (!username.contains("@")){
@Override progressDialog = ProgressDialog.show(SerialActivity.this,"Cargando...",
public void onClick(View view) { "Cargando datos, espere por favor...", false, false);
// Al pulsar aquí no es un tablet Yotta y no se registra como tal. Muestro una ventana informativa con el ANDROID ID
AlertDialog.Builder builder = new AlertDialog.Builder(SerialActivity.this);
builder.setMessage(getString(R.string.tabletNoYotta) + ": " + _ANDROIDID)
.setCancelable(false)
.setPositiveButton("Entendido", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//do things
// No necesita token
String token = "0";
RestapiWrapper wrapper = new RestapiWrapper(
getApplicationContext().getResources().getString(R.string.server),token);
String serial = "";
s_serial = serial;
String operation = "/dev/register";
//String _ANDROIDID = Settings.Secure.getString(getContentResolver(),Settings.Secure.ANDROID_ID);
//SecureRandom random = new SecureRandom();
Log.d("SerialActivity onCreate", "ANDROID ID:" + _ANDROIDID);
String _MODEL = android.os.Build.MODEL;
Hashtable<String, String> postDataParams = new Hashtable<String, String>();
postDataParams.put("idFirmware", _ANDROIDID);
postDataParams.put("desc", _MODEL);
postDataParams.put("serial", serial);
wrapper.ask(operation, postDataParams, "post", (iRestapiListener) context);
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
*/
} }
} }
...@@ -236,34 +192,50 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -236,34 +192,50 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
String jsonToken = result.getString(TAG_TOKEN); String jsonToken = result.getString(TAG_TOKEN);
JSONObject user = result.getJSONObject(TAG_USER); JSONObject user = result.getJSONObject(TAG_USER);
st_id = user.getInt(TAG_ID); try{
int st_id_int = st_id.intValue(); Boolean is_student = user.has(TAG_ISSTUDENT);
String st_name = user.getString(TAG_NAME);
String st_surname = user.getString(TAG_SURNAME); if (is_student) {
String st_pic = user.getString(TAG_PIC); // Es un estudiante
String st_gender = user.getString(TAG_GENDER); st_id = user.getInt(TAG_ID);
String st_lang = user.getString(TAG_LANG); int st_id_int = st_id.intValue();
//String st_attributes = user.getString(TAG_ATTRIBUTES); String st_name = user.getString(TAG_NAME);
String st_attributes = ""; // COMPROBAR CONSTRAINT PORQUE FALLA String st_surname = user.getString(TAG_SURNAME);
String st_pic = user.getString(TAG_PIC);
users.add(new User(st_id_int, st_name, st_surname, st_pic, st_gender, st_lang, st_attributes, String st_gender = user.getString(TAG_GENDER);
-1, "", "", "", "M", "es-es", "")); String st_lang = user.getString(TAG_LANG);
String st_attributes = user.getString(TAG_ATTRIBUTES);
PCBcontext.getDevice().synchronizeUsers(users, this);
PCBcontext.getDevice().deleteDeprecatedImgs(); users.add(new User(st_id_int, st_name, st_surname, st_pic, st_gender, st_lang, st_attributes,
-1, "", "", "", "M", "es-es", ""));
//JSONObject jDevice = result.getJSONObject("device");
//Object jsonId = jDevice.get("id"); Log.d(LOG_TAG, "jsonToken válido:" + jsonToken);
//String jsonIdString = jsonId.toString(); User student = PCBcontext.getDevice().findUser(st_id, -1);
PCBcontext.set_user(student, jsonToken, null);
Log.d(LOG_TAG, "jsonToken válido:" + jsonToken); PCBcontext.getDevice().synchronizeUsers(users, this);
//Log.d(LOG_TAG, "jsonIdString:" + jsonIdString); PCBcontext.getDevice().deleteDeprecatedImgs();
// Guardo el deviceID, token y serial en la bbdd } else{
//PCBcontext.getDevice().setDeviceID(jsonIdString); // Es un Supervisor
User student = PCBcontext.getDevice().findUser(st_id, su_id); Log.d(LOG_TAG, "Es un SUPERVISOR. Sigo...");
PCBcontext.set_user(student, jsonToken, this); Log.d(LOG_TAG, "jsonToken válido:" + jsonToken);
Integer su_id = user.getInt(TAG_ID);
int su_id_int = su_id.intValue();
//close the progress dialog
if (!username.contains("@")){
progressDialog.dismiss();
}
// Llamo a LoginActivity
Intent loginActivity = new Intent(this, LoginActivity.class);
loginActivity.putExtra("token", jsonToken);
loginActivity.putExtra("sup_id", su_id_int);
startActivity(loginActivity);
}
} catch (JSONException ex){
ex.printStackTrace();
}
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
...@@ -276,7 +248,7 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -276,7 +248,7 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
Log.e(this.getClass().getName(), " Server restapi error: " + e.getLocalizedMessage()); Log.e(this.getClass().getName(), " Server restapi error: " + e.getLocalizedMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(SerialActivity.this); AlertDialog.Builder builder = new AlertDialog.Builder(SerialActivity.this);
builder.setMessage(getString(R.string.serialRepeated)+":"+e.getLocalizedMessage()) builder.setMessage(getString(R.string.serverError)+":"+e.getLocalizedMessage())
.setCancelable(false) .setCancelable(false)
.setPositiveButton("Entendido", new DialogInterface.OnClickListener() { .setPositiveButton("Entendido", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
...@@ -290,7 +262,9 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo ...@@ -290,7 +262,9 @@ public class SerialActivity extends Activity implements iRestapiListener, iImgDo
@Override @Override
public void loadComplete() { public void loadComplete() {
Log.d(LOG_TAG, "Load images complete"); Log.d(LOG_TAG, "Load images complete");
//close the progress dialog
progressDialog.dismiss();
// Entro directamente a Pictogram con ese alumno
Intent pictogramActivity = new Intent(this, PictogramActivity.class); Intent pictogramActivity = new Intent(this, PictogramActivity.class);
startActivity(pictogramActivity); startActivity(pictogramActivity);
} }
......
...@@ -11,9 +11,11 @@ import java.util.Vector; ...@@ -11,9 +11,11 @@ import java.util.Vector;
import android.app.Fragment; import android.app.Fragment;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
...@@ -23,6 +25,9 @@ import android.widget.Toast; ...@@ -23,6 +25,9 @@ import android.widget.Toast;
import com.yottacode.pictogram.R; import com.yottacode.pictogram.R;
import com.yottacode.pictogram.dao.User; import com.yottacode.pictogram.dao.User;
import com.yottacode.pictogram.grammar.Vocabulary;
import com.yottacode.pictogram.net.iImgDownloaderListener;
import com.yottacode.pictogram.tools.Img;
import com.yottacode.pictogram.tools.PCBcontext; import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONException; import org.json.JSONException;
...@@ -42,7 +47,7 @@ public class StudentFragmentGrid extends Fragment{ ...@@ -42,7 +47,7 @@ public class StudentFragmentGrid extends Fragment{
Map<String, Bitmap> map_supervisor_pictures = new TreeMap<String, Bitmap>(); Map<String, Bitmap> map_supervisor_pictures = new TreeMap<String, Bitmap>();
Vector<Bitmap> imageStudents = new Vector<Bitmap>(); Vector<Bitmap> imageStudents = new Vector<Bitmap>();
*/ */
Boolean modoSupervisor; //Boolean modoSupervisor;
// NEW // NEW
Map<Integer, Vector<Integer>> ids_stu_sup = new TreeMap<Integer, Vector<Integer>>(); Map<Integer, Vector<Integer>> ids_stu_sup = new TreeMap<Integer, Vector<Integer>>();
...@@ -54,26 +59,19 @@ public class StudentFragmentGrid extends Fragment{ ...@@ -54,26 +59,19 @@ public class StudentFragmentGrid extends Fragment{
// String constant for logs // String constant for logs
private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName() private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName()
//A ProgressDialog object
private ProgressDialog progressDialog;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setRetainInstance(true); setRetainInstance(true);
// Singleton getInstance
//pcb = PCBcontext.getInstance();
/*
Set<String> s_students;
List<String> l_supervisors = new ArrayList<String>();
students_ids = new Vector<Integer>();
supervisor_ids = new Vector<Integer>();
*/
modoSupervisor = false;
try { try {
// Cargo los datos de los estudiantes // Cargo los datos de los estudiantes
Vector<User> users = PCBcontext.getDevice().getUsers(); Vector<User> users = PCBcontext.getDevice().getUsers();
if (users!=null){ if (users!=null){
Log.d(LOG_TAG, "Cargo " + users.size() + " alumnos");
// Recorro el vector para sacar los nombres de estudiantes y las imágenes // Recorro el vector para sacar los nombres de estudiantes y las imágenes
for( int i = 0 ; i < users.size() ; i++ ){ for( int i = 0 ; i < users.size() ; i++ ){
int st_id = users.elementAt(i).get_id_stu(); int st_id = users.elementAt(i).get_id_stu();
...@@ -91,40 +89,7 @@ public class StudentFragmentGrid extends Fragment{ ...@@ -91,40 +89,7 @@ public class StudentFragmentGrid extends Fragment{
ids_stu_sup.put(st_id, sups); ids_stu_sup.put(st_id, sups);
} }
} }
/*
String st_name = users.elementAt(i).get_name_stu();
String st_surname = users.elementAt(i).get_surname_stu();
Bitmap st_picture = users.elementAt(i).get_bitmap_stu(getActivity());
String su_name = users.elementAt(i).get_name_sup();
String su_surname = users.elementAt(i).get_surname_sup();
Bitmap su_picture = users.elementAt(i).get_bitmap_sup(getActivity());
if (!map_students.containsKey(st_name + " " + st_surname)){
// Creo un nuevo supervisor y lo añado
if (su_id!=-1){
l_supervisors = new ArrayList<String>();
l_supervisors.add(su_name + " " + su_surname);
map_supervisor_pictures.put(su_name + " " + su_surname, su_picture);
supervisor_ids.add(su_id);
}
imageStudents.add(st_picture);
map_students.put(st_name + " " + st_surname, l_supervisors);
students_ids.add(st_id);
} else{
// Saco los supervisores, añado uno más y grabo
if (su_id!=-1){
l_supervisors = map_students.get(st_name + " " + st_surname);
l_supervisors.add(su_name + " " + su_surname);
supervisor_ids.add(su_id);
}
map_students.put(st_name + " " + st_surname, l_supervisors);
}
*/
} }
// Saco los estudiantes
/*
s_students = map_students.keySet();
students = s_students.toArray(new String[s_students.size()]);
*/
} else{ } else{
// TRATO EL ERROR. COMO ????? // TRATO EL ERROR. COMO ?????
} }
...@@ -144,11 +109,12 @@ public class StudentFragmentGrid extends Fragment{ ...@@ -144,11 +109,12 @@ public class StudentFragmentGrid extends Fragment{
try { try {
List<String> l_students_name = new ArrayList<String>(); List<String> l_students_name = new ArrayList<String>();
Vector<Bitmap> imageStudents = new Vector<Bitmap>(); Vector<Bitmap> imageStudents = new Vector<Bitmap>();
int id_sup = PCBcontext.getPcbdb().getCurrentUser().get_id_sup();
students_ids = new Vector<Integer>(); students_ids = new Vector<Integer>();
for(Map.Entry<Integer,Vector<Integer>> entry : ids_stu_sup.entrySet()) { for(Map.Entry<Integer,Vector<Integer>> entry : ids_stu_sup.entrySet()) {
Integer id_stu = entry.getKey(); Integer id_stu = entry.getKey();
students_ids.add(id_stu); students_ids.add(id_stu);
User currentUser = PCBcontext.getDevice().findUser(id_stu, -1); User currentUser = PCBcontext.getDevice().findUser(id_stu, id_sup);
String st_name = currentUser.get_name_stu(); String st_name = currentUser.get_name_stu();
Bitmap st_picture = currentUser.get_bitmap_stu(getActivity()); Bitmap st_picture = currentUser.get_bitmap_stu(getActivity());
l_students_name.add(st_name); l_students_name.add(st_name);
...@@ -161,30 +127,33 @@ public class StudentFragmentGrid extends Fragment{ ...@@ -161,30 +127,33 @@ public class StudentFragmentGrid extends Fragment{
@Override @Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) { public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
//Log.d("onitemclick", " " + pos + " pulsado"); int id_sup = PCBcontext.getPcbdb().getCurrentUser().get_id_sup();
/* User student = null;
if (modoSupervisor){ try {
// Llamo al fragment de Supervisores para cargarlos en la misma ventana student = PCBcontext.getDevice().findUser(students_ids.elementAt(pos), id_sup);
Toast.makeText(getActivity().getBaseContext(), "Modo Supervisor activado", Toast.LENGTH_SHORT).show(); } catch (JSONException e) {
PCBcontext.getDevice().setStuId(students_ids.elementAt(pos)); e.printStackTrace();
// Llamo al fragment de los supervisores para cargar sus datos }
SupervisorFragmentGrid supervisores = (SupervisorFragmentGrid)getFragmentManager().findFragmentById(R.id.supervisores); String jsonToken = PCBcontext.getRestapiWrapper().getToken();
// Cojo el nombre y apellidos de ese estudiante
//String name_surname_st = students[pos]; progressDialog = ProgressDialog.show(getActivity(),"Cargando...",
supervisores.change(ids_stu_sup, pos); "Cargando datos del alumno seleccionado, espere por favor...", false, false);
} else{ PCBcontext.set_user(student, jsonToken, new iImgDownloaderListener() {
*/ @Override
// Entro en pictogram con ese valor de alumno y con supervisor a null public void loadComplete() {
Toast.makeText(getActivity().getBaseContext(), "Modo Supervisor desactivado", Toast.LENGTH_SHORT).show(); //Vocabulary vocabulary = PCBcontext.getVocabulary();
PCBcontext.getDevice().setLastStuId(students_ids.elementAt(pos)); //Log.d(LOG_TAG, "Vocabulario de tam:" + vocabulary.size());
PCBcontext.getDevice().setLastSupId(-1); progressDialog.dismiss();
Intent pictogramActivity = new Intent(getActivity(), PictogramActivity.class);
//Log.d(LOG_TAG, "SET id_alumno:" + students_ids.elementAt(pos) + " /id_supervisor:-1"); startActivity(pictogramActivity);
}
Intent pictogramActivity = new Intent(getActivity(), PictogramActivity.class);
startActivity(pictogramActivity); @Override
//} public void loadImg(Img image) {
}
});
} }
}); });
} catch (JSONException e) { } catch (JSONException e) {
...@@ -197,20 +166,4 @@ public class StudentFragmentGrid extends Fragment{ ...@@ -197,20 +166,4 @@ public class StudentFragmentGrid extends Fragment{
} }
return v; return v;
} }
/*
public void changeSupervisorMode(boolean value){
modoSupervisor = value;
Toast.makeText(getActivity().getBaseContext(), "Modo Supervisor " + value, Toast.LENGTH_SHORT).show();
SupervisorFragmentGrid supervisores = (SupervisorFragmentGrid)getFragmentManager().findFragmentById(R.id.supervisores);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
if (supervisores.isHidden()) {
ft.show(supervisores);
} else {
ft.hide(supervisores);
}
ft.commit();
}
*/
} }
...@@ -51,6 +51,11 @@ public class NetService implements Runnable, iRestapiListener { ...@@ -51,6 +51,11 @@ public class NetService implements Runnable, iRestapiListener {
} }
@Override @Override
public void preExecute() {
}
@Override
public void result(JSONArray result) { public void result(JSONArray result) {
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<fragment <fragment
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="300px" android:layout_height="600px"
class="com.yottacode.pictogram.gui.StudentFragmentGrid" class="com.yottacode.pictogram.gui.StudentFragmentGrid"
android:id="@+id/alumnos" android:id="@+id/alumnos"
android:layout_below="@+id/logintitle"/> android:layout_below="@+id/logintitle"/>
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<GridView <GridView
android:id="@+id/tape_grid_view" android:id="@+id/tape_grid_view"
android:layout_width="860dp" android:layout_width="560dp"
android:layout_height="85dp" android:layout_height="85dp"
android:gravity="center" android:gravity="center"
android:numColumns="@integer/columns" android:numColumns="@integer/columns"
...@@ -44,8 +44,8 @@ ...@@ -44,8 +44,8 @@
android:src="@drawable/ic_action" android:src="@drawable/ic_action"
android:background="@null" android:background="@null"
android:id="@+id/button_delete" android:id="@+id/button_delete"
android:layout_below="@+id/button_tts" android:layout_toRightOf="@+id/tape_grid_view"
android:layout_toRightOf="@+id/tape_grid_view"/> android:layout_alignParentTop="true"/>
<GridView <GridView
android:id="@+id/panel_grid_view" android:id="@+id/panel_grid_view"
......
...@@ -37,5 +37,6 @@ ...@@ -37,5 +37,6 @@
<string name="systemMessage">System message</string> <string name="systemMessage">System message</string>
<string name="noInternetConnection">There is no Internet connection. Try again later</string> <string name="noInternetConnection">There is no Internet connection. Try again later</string>
<string name="exitingApp">Exiting the app</string> <string name="exitingApp">Exiting the app</string>
<string name="serverError">There is a server error. Try again later</string>
</resources> </resources>
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
<string name="systemMessage">Mensaje del sistema</string> <string name="systemMessage">Mensaje del sistema</string>
<string name="noInternetConnection">No hay conexión a internet. Inténtelo más tarde</string> <string name="noInternetConnection">No hay conexión a internet. Inténtelo más tarde</string>
<string name="exitingApp">Saliendo de la aplicación</string> <string name="exitingApp">Saliendo de la aplicación</string>
<string name="serverError">Error en el servidor de datos. Inténtelo más tarde</string>
<item type="integer" name="maxInTape">8</item> <item type="integer" name="maxInTape">8</item>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment