Commit 148cb19d by Arturo Montejo Ráez

updating pre version

Merge branch 'master' of http://scm.ujaen.es/softuno/pictogram
parents f814e842 d69dfc9d
Showing with 1065 additions and 1424 deletions
......@@ -27,6 +27,7 @@ sails/src/assets/upload
sails/src/assets/app/js/lib/sails.io.js
sails/src/config/local.js
sails/src/assets/app/js/config.js
sails/src/assets/app/js/local.js
sails/src/config/ssl
sails/src/config/logs
sails/src/node_modules
......
deny from all
Este proyecto contiene el código de Pictogram, que se divide en tres:
* sails: API REST del servidor (sails.js)
* angular: Aplicación web con el dashboard para supervisores (Angular.js)
* android: aplicación para tablet para estudiantes
\ No newline at end of file
- [Servidor](sails): API REST del servidor
- [Cliente web](sails/src/assets/app): aplicación web con el dashboard para supervisores
- [Cliente android](android/Pictogram): aplicación android para tablet para estudiantes
......@@ -31,7 +31,7 @@ android {
debug {
resValue "string", "db_name", "PCB.db"
resValue "bool", "force_db_create", "true"
resValue "bool", "force_db_create", "false"
resValue "bool", "ssl_connect", "false"
resValue "bool", "force_img_download", "false"
resValue "integer", "netservice_timing", "20"
......
......@@ -48,6 +48,41 @@ public class Translate extends Activity implements iVocabularyListener, iImgDown
// String constan for token
private final String TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJvZmZpY2UiOnsiaWQiOjM4MywibmFtZSI6IkNvbXVuaWNhY2nDs24gQXVtZW50YXRpdmEgSkHDqW4gKENBSkEpIiwiYWRkcmVzcyI6IlBhcmFqZSBMYXMgTGFndW5pbGxhcywgRWQgQTMsIHByaW1lcmEgcGxhdGEsIDIzMDcxLiBKYcOpbiIsImVtYWlsIjoiZG9mZXJAdWphZW4uZXMiLCJwaG9uZTEiOiIrMzQgOTUzIDIxIDI4IDg4IiwicGhvbmUyIjpudWxsLCJsYW5nIjoiZXMtZXMiLCJjb3VudHJ5IjoiRVMiLCJhZG1pbiI6MjMsImNvbnRhY3RQZXJzb24iOiJGZXJuYW5kbyBNYXJ0w61uZXogU2FudGlhZ28iLCJtYXhTdHVkZW50cyI6MiwiY3VycmVudFN0dWRlbnRzIjowfSwiaWQiOjIzLCJuYW1lIjoiRmVybmFuZG8iLCJzdXJuYW1lIjoiTWFydMOtbmV6IFNhbnRpYWdvIiwiZ2VuZGVyIjoiTSIsInBpYyI6Imh0dHA6Ly93d3dkaS51amFlbi5lcy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3lvLmpwZz8xNDQ4MDE5MzU2IiwiYWRkcmVzcyI6bnVsbCwiY291bnRyeSI6bnVsbCwiZW1haWwiOiJkb2ZlckB1amFlbi5lcyIsInBob25lIjoiKzM0OTUzMjEyODg4IiwibGFuZyI6ImVzLWVzIiwiYWN0aXZlIjp0cnVlLCJ0dHNFbmdpbmUiOm51bGwsImlzU3VwQWRtaW4iOnRydWUsImlhdCI6MTQ1Mjg4NjE1NSwiZXhwIjoxNDUyODkzMzU1fQ.dmxKE4qH1DqBM7BYakgwD0L6y1437_2Ba3T7rHnOIcE";
private login() {
if (RestapiWrapper.ping(context.getResources().getString(R.string.server),"server/ping",null)) {
// Tengo conexión a internet. Compruebo ONLINE
RestapiWrapper wrapper = PCBcontext.getRestapiWrapper();
if (username.contains("@")){
// Es un supervisor
String operation = "sup/login";
Hashtable<String, String> postDataParams = new Hashtable<String, String>();
postDataParams.put("email", username);
postDataParams.put("password", password);
wrapper.ask(operation, postDataParams, "post", (iRestapiListener) context);
} else{
// Es un estudiante
String operation = "stu/login";
Hashtable<String, String> postDataParams = new Hashtable<String, String>();
postDataParams.put("username", username);
postDataParams.put("password", password);
wrapper.ask(operation, postDataParams, "post", (iRestapiListener) context);
}
} else{
// NO Tengo conexión a internet. Compruebo OFFLINE
if (username.contains("@")) {
// Es un supervisor
// Necesito una función local que dado el username y pass me devuelva el listado de usuarios o el usuario, si es correcto
// ....
} else {
// Es un estudiante
}
// ....
}
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
......
package com.yottacode.net;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Hashtable;
import java.util.concurrent.Executor;
import java.net.UnknownHostException;
import java.util.Hashtable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.util.Log;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.util.Log;
import com.google.gson.JsonParser;
import com.koushikdutta.async.parser.JSONObjectParser;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.HttpsURLConnection;
/**
......@@ -55,7 +52,8 @@ public class RestapiWrapper {
this.token=token;
}
public String getToken() {
if (token==null) throw new java.lang.NullPointerException("Token has no value. Use constructor properly or RestapiWrapper.setToken must be invoked previously"); return token;
if (token==null) throw new java.lang.NullPointerException("Token has no value. Use constructor properly or RestapiWrapper.setToken must be invoked previously");
return token;
}
public String getServer() {
return server;
......@@ -85,7 +83,7 @@ public class RestapiWrapper {
}
public void ask(String operation, iRestapiListener listener) {
this.ask(operation, null, "get", listener);
this.ask(operation, null, "get", listener);
}
/**
......@@ -110,19 +108,22 @@ public class RestapiWrapper {
/**
* synchronous ping
* @param ping_op
* @param error_listener
* @return
*/
public static boolean ping(String server, String ping_op, iRestapiListener error_listener) {
public static boolean ping(String server, String ping_op) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
boolean pingResult = false;
try {
pingResult = GET(server + "/" + ping_op, null)!=null;
} catch (UnknownHostException e){
//e.printStackTrace();
Log.i(RestapiWrapper.class.getName(), "ping failed at "+ping_op);
return false;
} catch (IOException e) {
e.printStackTrace();
Log.e(com.yottacode.net.RestapiWrapper.class.getName(), "ping failed at"+ping_op);
error_listener.error(e);
Log.i(com.yottacode.net.RestapiWrapper.class.getName(), "ping failed at"+ping_op);
//error_listener.error(e);
}
return pingResult;
}
......@@ -133,12 +134,12 @@ public class RestapiWrapper {
URL url = null;
if (params!=null) {
surl += '?';
for (String param : params.keySet()) {
String value = params.get(param);
surl += param + '=' + value + '&';
}
surl=surl.substring(0,surl.length()-1);
surl += '?';
for (String param : params.keySet()) {
String value = params.get(param);
surl += param + '=' + value + '&';
}
surl=surl.substring(0,surl.length()-1);
}
url = new URL(surl);
HttpURLConnection urlConnection = null;
......@@ -154,60 +155,60 @@ public class RestapiWrapper {
if (inputStream!=null) result = convertInputStreamToString(inputStream);
return result;
}
public String POST(String surl, String request_method, Hashtable<String, String> params, boolean json_params) throws IOException {
URL url = null;
String response = "";
url = new URL(surl);
HttpURLConnection urlConnection = null;
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setReadTimeout(60000);
urlConnection.setConnectTimeout(60000);
urlConnection.setRequestMethod(request_method);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
if (json_params) {
urlConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
urlConnection.setRequestProperty("Accept", "application/json, text/plain, */*");
}
String sparams;
if (json_params) {
sparams = params.get("json");
params.remove("json");
} else
sparams="";
for (String param : params.keySet()) {
String value = params.get(param);
if (param.equals("token"))
urlConnection.setRequestProperty("Authorization", "Bearer " + value);
else {
if (sparams.length() > 0) sparams += '&';
sparams += param + '=' + value;
}
url = new URL(surl);
HttpURLConnection urlConnection = null;
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setReadTimeout(60000);
urlConnection.setConnectTimeout(60000);
urlConnection.setRequestMethod(request_method);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
if (json_params) {
urlConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
urlConnection.setRequestProperty("Accept", "application/json, text/plain, */*");
}
String sparams;
if (json_params) {
sparams = params.get("json");
params.remove("json");
} else
sparams="";
for (String param : params.keySet()) {
String value = params.get(param);
if (param.equals("token"))
urlConnection.setRequestProperty("Authorization", "Bearer " + value);
else {
if (sparams.length() > 0) sparams += '&';
sparams += param + '=' + value;
}
}
//Send request
DataOutputStream wr = new DataOutputStream (
urlConnection.getOutputStream ());
wr.writeBytes(sparams);
wr.flush();
wr.close();
//Send request
DataOutputStream wr = new DataOutputStream (
urlConnection.getOutputStream ());
wr.writeBytes(sparams);
wr.flush();
wr.close();
OutputStream os = urlConnection.getOutputStream();
os.close();
int responseCode=urlConnection.getResponseCode();
OutputStream os = urlConnection.getOutputStream();
os.close();
int responseCode=urlConnection.getResponseCode();
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(responseCode == HttpsURLConnection.HTTP_OK
? urlConnection.getInputStream()
: urlConnection.getErrorStream()));
while ((line=br.readLine()) != null) {
response+=line;
}
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(responseCode == HttpsURLConnection.HTTP_OK
? urlConnection.getInputStream()
: urlConnection.getErrorStream()));
while ((line=br.readLine()) != null) {
response+=line;
}
return response;
}
......@@ -241,8 +242,8 @@ public class RestapiWrapper {
protected HttpAsyncTaskParams doInBackground(HttpAsyncTaskParams... params) {
try {
params[0].result = params[0].request_method.equalsIgnoreCase("GET")
? GET(params[0].url, params[0].url_params)
: POST(params[0].url, params[0].request_method, params[0].url_params, params[0].json_params);
? GET(params[0].url, params[0].url_params)
: POST(params[0].url, params[0].request_method, params[0].url_params, params[0].json_params);
} catch (IOException e) {
Log.e(com.yottacode.net.RestapiWrapper.class.getName(), "Error:" + e.getLocalizedMessage() + " when asking for " + params[0].url);
params[0].result=null;
......
package com.yottacode.pictogram.dao;
/**
* Created by Fernando on 15/03/2016.
*/
public class LoginException extends Exception{
public static final int UNKNOWN_USERNAME=0;
public static final int BAD_PASSWORD=1;
public static final int NO_STUDENTS=2;
int code;
public LoginException(String msg, int code) {
super(msg);
this.code=code;
}
public boolean no_username_found() {return this.code==LoginException.UNKNOWN_USERNAME;}
public boolean no_pwd_found() {return this.code==LoginException.BAD_PASSWORD;}
public boolean no_supervisor_students() {return this.code==LoginException.NO_STUDENTS;}
}
......@@ -63,7 +63,7 @@ class DeviceHelper {
public class PCBDBHelper extends SQLiteOpenHelper {
User currentUser;
boolean user_online; //true if the given user logged into the server
/**
* Create a helper object to create, open, and/or manage a database.
......@@ -74,9 +74,13 @@ public class PCBDBHelper extends SQLiteOpenHelper {
*/
public PCBDBHelper(CursorFactory factory, int version, User user) {
super(PCBcontext.getContext(), DeviceHelper.getDBName(PCBcontext.getContext()), factory, version);
this.user_online=false;
this.setCurrentUser(user == null ? this.getCurrentUser() : user);
}
public boolean isUser_online() {return this.user_online;}
public void user_online(boolean user_online) {this.user_online=user_online;}
/**
* Save the current user of the PCB. It is required to retrieve the last user.
*
......@@ -102,8 +106,8 @@ public class PCBDBHelper extends SQLiteOpenHelper {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
try {
last_user = new User(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4), cursor.getString(5), cursor.getString(6),
cursor.getInt(7), cursor.getString(8), cursor.getString(9), cursor.getString(10), cursor.getString(11), cursor.getString(12), cursor.getString(13));
last_user = new User(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4), cursor.getString(5), cursor.getString(6), cursor.getString(7), cursor.getString(8),
cursor.getInt(9), cursor.getString(10), cursor.getString(11), cursor.getString(12), cursor.getString(13), cursor.getString(14), cursor.getString(15), cursor.getString(16), cursor.getString(17));
} catch (JSONException e) {
Log.e(this.getClass().getName(), e.getMessage() + " BAD FORMED JSON: " + cursor.getString(5));
System.exit(-1);
......@@ -257,7 +261,7 @@ public class PCBDBHelper extends SQLiteOpenHelper {
new String[]{ Integer.toString(this.currentUser.get_id_stu()),
Integer.toString(picto_id)});
db.close();
PCBcontext.getDevice().deleteDeprecatedImgs();
}
/**
* Update a picto of the current collection's student.
......
......@@ -11,6 +11,8 @@ import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Serializable;
/**
* A object which represents a pictogram
* *
......@@ -71,7 +73,11 @@ public class Picto extends Img {
}
/**
*
* @return true if it's a local pictogram
*/
public boolean is_local() {return this.get_id()<0;}
/**
*
* @return de id of the picto
......@@ -253,7 +259,7 @@ public class Picto extends Img {
int color = this.get_color();
int red = Color.red(color)+LIGHT, blue = Color.blue(color)+LIGHT, green = Color.green(color)+LIGHT;
return Color.rgb(red,green,blue);
return Color.rgb(red, green, blue);
}
/**
......@@ -297,7 +303,7 @@ public class Picto extends Img {
* @return
*/
public boolean is_category() {
return this.get_category()==Picto.NO_CATEGORY && this.get_row()!=Picto.ROW_UNCATEGORIZED_CONCEPTS;
return this.get_category()==Picto.NO_CATEGORY && this.get_column()!=Picto.ROW_UNCATEGORIZED_CONCEPTS;
}
/**
*
......@@ -325,12 +331,14 @@ public class Picto extends Img {
try {
this.attributes.put(JSON_ATTTRS.STATUS, status);
set_local_status(true);
new PictoUploader(this).uploadState();
if (!is_local()) {
new PictoUploader(this).uploadState();
PCBcontext.getActionLog().log(new VocabularyAction(VocabularyAction.ALTERATTRS, this));
}
} catch (JSONException e) {
e.printStackTrace();
Log.e(this.getClass().getCanonicalName(),e.getMessage());
}
PCBcontext.getActionLog().log(new VocabularyAction(VocabularyAction.ALTERATTRS,this));
return is_enabled();
}
......
......@@ -15,12 +15,12 @@ import com.yottacode.pictogram.grammar.Vocabulary;
* A user of the PCB. A user can be an Student or a Supervisor using a student configuration
* *
* @author Fernando Martinez Santiago
* @version 1.0
* @version 1.1
*/
public class User {
private static final int NO_SUPERVISOR = -1;
public static final int NO_SUPERVISOR = -1;
public boolean has_supervisor() {
return this.get_id_sup()!=User.NO_SUPERVISOR;
}
......@@ -34,18 +34,20 @@ public class User {
static String TTS_VOICE = "tts voice";
}
private Img img_stu;
private String name_stu, surname_stu, gender_stu, lang_stu;
private String nickname_stu, pwd_stu, name_stu, surname_stu, gender_stu, lang_stu;
private JSONObject attributes_stu;
private Img img_sup;
private String name_sup, surname_sup, gender_sup, lang_sup, tts_engine_sup;
private String email_sup, pwd_sup, name_sup, surname_sup, gender_sup, lang_sup, tts_engine_sup;
public User(int id_stu, String name_stu, String surname_stu, String url_img_stu, String gender_stu, String lang_stu, String attributes_stu) throws JSONException {
this(id_stu, name_stu, surname_stu, url_img_stu, gender_stu, lang_stu, attributes_stu,User.NO_SUPERVISOR,"","","","M","es-es",null);
public User(int id_stu, String nickname_stu, String pwd_stu, String name_stu, String surname_stu, String url_img_stu, String gender_stu, String lang_stu, String attributes_stu) throws JSONException {
this(id_stu, nickname_stu, pwd_stu, name_stu, surname_stu, url_img_stu, gender_stu, lang_stu, attributes_stu,User.NO_SUPERVISOR,"","","","","","M","es-es",null);
}
public User(int id_stu, String name_stu, String surname_stu, String url_img_stu, String gender_stu, String lang_stu, String attributes_stu,
int id_sup,String name_sup, String surname_sup, String url_img_sup, String gender_sup, String lang_sup, String tts_engine_sup) throws JSONException {
public User(int id_stu, String nickname_stu, String pwd_stu, String name_stu, String surname_stu, String url_img_stu, String gender_stu, String lang_stu, String attributes_stu,
int id_sup, String email_sup, String pwd_sup, String name_sup, String surname_sup, String url_img_sup, String gender_sup, String lang_sup, String tts_engine_sup) throws JSONException {
this.img_stu=new Img(id_stu,url_img_stu,Img.STUDENT);
this.nickname_stu=nickname_stu;
this.pwd_stu=pwd_stu;
this.name_stu=name_stu;
this.surname_stu=surname_stu;
this.gender_stu=gender_stu;
......@@ -53,6 +55,8 @@ public class User {
this.attributes_stu= attributes_stu!=null && attributes_stu.trim().length()>0 ? new JSONObject(attributes_stu) : new JSONObject();
this.img_sup=new Img(id_sup,url_img_sup,Img.SUPERVISOR);
this.email_sup=email_sup;
this.pwd_sup=pwd_sup;
this.name_sup=name_sup;
this.surname_sup=surname_sup;
this.gender_sup=gender_sup;
......@@ -70,6 +74,19 @@ public class User {
public int get_id_stu() {return this.img_stu.get_id();}
/**
*
* @return nickname (username) of the student
*/
public String get_nickname_stu() {return this.nickname_stu;}
/**
*
* @return pwd of the student
*/
public String get_pwd_stu() {return this.pwd_stu;}
/**
* @ return the RESTAPI operator for the current student
*/
public String get_restapi_operation_stu() {
......@@ -131,6 +148,18 @@ public class User {
/**
*
* @return nickname (username) of the student
*/
public String get_email_sup() {return this.email_sup;}
/**
*
* @return pwd of the student
*/
public String get_pwd_sup() {return this.pwd_sup;}
/**
*
* @return name of the supervisor
*/
public String get_name_sup() {return this.name_sup;}
......
......@@ -51,7 +51,8 @@ public class Vocabulary implements Iterable<Picto> {
}else
try {
PCBcontext.getPcbdb().getStudentVocabulary(this);
listener.loadComplete();
if (listener!=null)
listener.loadComplete();
} catch (JSONException e) {
Log.e(this.getClass().getName(),"Local vocabulary recover failed: "+e.getMessage());
}
......@@ -261,7 +262,7 @@ public class Vocabulary implements Iterable<Picto> {
LinkedList<Picto> pictos_cat=this.pictos.get(pic_cat);
int index = find_picto_index(pic_cat, pic_id);
if (index>=0) { //puede ocurrir que se intente borrar un pictograma dos veces
pictos_cat.remove();
pictos_cat.remove(index);
PCBcontext.getPcbdb().deletePicto(pic_id);
}
else
......@@ -321,6 +322,7 @@ public class Vocabulary implements Iterable<Picto> {
public boolean isVisibleCategory(int id) {
if (empty_category(id)) return false;
if (PCBcontext.getPcbdb().getCurrentUser().is_supervisor()) return true;
boolean visible=false;
for (Picto picto : this.pictos.get(id)) {
......@@ -332,7 +334,7 @@ public class Vocabulary implements Iterable<Picto> {
/*
* It saves locally a new picto obtained from the PCB
*/
public Picto saveLocalPicto(String url, String exp, int cat, int coord_x, int coord_y) {
public Picto saveLocalPicto(String url, String exp, int cat, int coord_x, int coord_y, final iLocalPicto listener) {
int id= PCBcontext.getDevice().getNextLocalPictoID();
final Picto picto[]=new Picto[1];
try {
......@@ -340,19 +342,13 @@ public class Vocabulary implements Iterable<Picto> {
addPicto(picto[0], ImgDownloader.tsource.local, new iImgDownloaderListener() {
@Override
public void loadComplete() {
try {
new PictoUploader(picto[0]).upload(); //id<0 iif it is a local id
} catch (IOException e) {
e.printStackTrace();
}
listener.saved(picto[0]);
}
@Override
public void loadImg(Img image) {
}
});
} catch (Exception e) {
picto[0]=null;
e.printStackTrace();
......
package com.yottacode.pictogram.grammar; import android.util.Log; import com.github.nkzawa.emitter.Emitter; import org.json.JSONException;import org.json.JSONObject; import com.yottacode.pictogram.dao.Picto;import com.yottacode.pictogram.action.Room; /** * Websocket Vocabulary Room based on Room * @author Fernando Martinez Santiago * @version 1.0 */public class VocabularyTalk implements Emitter.Listener { private static final String URL ="vocabulary"; private Room room; iVocabularyListener listeners[]; public VocabularyTalk(Room room, iVocabularyListener listeners[]) { this.room = room; this.room.listen(URL, this); this.listeners=listeners; } @Override public void call(Object... args) { final String param_action="action"; final String param_attributes="attributes"; final String param_picto="picto"; final String param_picto_id="id"; final String param_picto_cat="id_cat"; final String action_update="update"; final String action_add="add"; final String action_delete="delete"; JSONObject msg = (JSONObject) args[0]; try { String action = msg.getString(param_action).toLowerCase(); JSONObject picto= msg.getJSONObject(param_attributes).getJSONObject(param_picto); JSONObject attrs_picto = picto.getJSONObject(param_attributes); int picto_id = picto.getInt(param_picto_id); int picto_cat = attrs_picto.optInt(param_picto_cat, Picto.NO_CATEGORY); Log.d(this.getClass().getName(), "Received message '" + action + "' for picto " + picto_id + " (cat " + picto_cat + ", attrs: "+attrs_picto); for (iVocabularyListener listener: this.listeners) listener.change(action.equals(action_update) ? iVocabularyListener.action.update : action.equals(action_add) ? iVocabularyListener.action.add : iVocabularyListener.action.delete , picto_cat, picto_id, attrs_picto); } catch (JSONException e) { Log.e(this.getClass().getCanonicalName(), e.getClass().getCanonicalName() + "--" + e); } }}
\ No newline at end of file
package com.yottacode.pictogram.grammar; import android.util.Log; import com.github.nkzawa.emitter.Emitter; import org.json.JSONException;import org.json.JSONObject; import com.yottacode.pictogram.dao.Picto;import com.yottacode.pictogram.action.Room; /** * Websocket Vocabulary Room based on Room * @author Fernando Martinez Santiago * @version 1.0 */public class VocabularyTalk implements Emitter.Listener { private static final String URL ="vocabulary"; private Room room; iVocabularyListener listeners[]; public VocabularyTalk(Room room, iVocabularyListener listeners[]) { this.room = room; this.room.listen(URL, this); this.listeners=listeners; } @Override public void call(Object... args) { final String param_action="action"; final String param_attributes="attributes"; final String param_picto="picto"; final String param_picto_id="id"; final String param_picto_cat="id_cat"; final String action_update="update"; final String action_add="add"; final String action_delete="delete"; JSONObject msg = (JSONObject) args[0]; try { Log.i(this.getClass().getName(), "raw Received message " +msg.toString()); String action = msg.getString(param_action).toLowerCase(); JSONObject picto= msg.getJSONObject(param_attributes).getJSONObject(param_picto); JSONObject attrs_picto = picto.optJSONObject(param_attributes); int picto_id = picto.getJSONObject(param_picto).getInt(param_picto_id); int picto_cat = attrs_picto!=null ? attrs_picto.optInt(param_picto_cat, Picto.NO_CATEGORY) : 0; Log.i(this.getClass().getName(), "Received message '" + action + "' for picto " + picto_id + " (cat " + picto_cat + ", attrs: " + attrs_picto); for (iVocabularyListener listener: this.listeners) listener.change(action.equals(action_update) ? iVocabularyListener.action.update : action.equals(action_add) ? iVocabularyListener.action.add : iVocabularyListener.action.delete , picto_cat, picto_id, attrs_picto); } catch (JSONException e) { Log.e(this.getClass().getCanonicalName(), e.getClass().getCanonicalName() + "--" + e); } }}
\ No newline at end of file
......
package com.yottacode.pictogram.grammar;
import com.yottacode.pictogram.dao.Picto;
/**
* Created by Fernando on 14/03/2016.
*/
public interface iLocalPicto {
public void saved(Picto localPicto);
}
......@@ -14,6 +14,7 @@ import android.widget.Toast;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.dao.Device;
import com.yottacode.pictogram.dao.LoginException;
import com.yottacode.pictogram.dao.PCBDBHelper;
import com.yottacode.pictogram.dao.User;
import com.yottacode.pictogram.tools.PCBcontext;
......@@ -43,10 +44,9 @@ public class MainActivity extends Activity {
PCBcontext.init(this);
Log.d(LOG_TAG, "PCBcontext iniciado.");
// Nota magc: al pasar ya siempre por serial no tiene sentido tener main ¿no?
Intent serialActivity = new Intent(this, SerialActivity.class);
serialActivity.putExtra("activity_name","MainActivity");
serialActivity.putExtra("resetPrevUser", false);
startActivity(serialActivity);
}
......
package com.yottacode.pictogram.gui;
/**
* Created by miguelangel on 29/4/15.
*/
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
......@@ -38,7 +38,8 @@ import java.util.LinkedList;
public class PanelAdapter extends ArrayAdapter {
private LinkedList<Picto> lPictos;
private int color;
int color;
private Bitmap square_bmp = BitmapFactory.decodeResource(PCBcontext.getContext().getResources(), R.drawable.square);
//private Context mContext;
// String constant for logs
......@@ -95,7 +96,7 @@ public class PanelAdapter extends ArrayAdapter {
//if (position==0 || position==2)
if (pictogramSize==0)
imageView.setLayoutParams(new GridView.LayoutParams(getPx(110), getPx(70)));// ancho y alto
imageView.setLayoutParams(new GridView.LayoutParams(110,70));// ancho y alto
else if (pictogramSize==1)
imageView.setLayoutParams(new GridView.LayoutParams(140, 140));// ancho y alto
......@@ -106,7 +107,7 @@ public class PanelAdapter extends ArrayAdapter {
imageView = (ImageView) convertView;
}
imageView.setBackgroundColor(color);
// QUITAR imageView.setBackgroundColor(color);
// Propiedades de pictos
// Fuera de la comprobación de convertView y con los else para dejar el estado normal
......@@ -147,7 +148,8 @@ public class PanelAdapter extends ArrayAdapter {
// Pruebo a poner una X encima de la imagen
if (lPictos.get(position) == null){
// Es un hueco en blanco
imageView.setImageAlpha(0);
imageView.setImageAlpha(50);
imageView.setImageBitmap(this.square_bmp);
} else{
Picto picto =lPictos.get(position);
Bitmap bmp1 = picto.get_bitmap(PCBcontext.getContext());
......@@ -163,10 +165,8 @@ public class PanelAdapter extends ArrayAdapter {
if(picto.is_invisible()) {
imageView.setImageAlpha(PCBcontext.getPcbdb().getCurrentUser().is_supervisor() ? 50 : 0);
imageView.setImageBitmap(bmp1);
Log.d(LOG_TAG, "POSITION:" + position + " / STATUS: " + picto.get_status());
//imageView.setImageBitmap(bmp1);
imageView.setImageAlpha(50);
imageView.setImageBitmap(PCBcontext.getPcbdb().getCurrentUser().is_supervisor() ? bmp1 : this.square_bmp);
}
if(picto.is_disabled()){
imageView.setImageAlpha(100); // Entre 0 y 255
......
package com.yottacode.pictogram.gui;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import java.util.ArrayList;
/**
* Created by magc on 17/03/15.
*/
public class PanelAdapterUsers extends BaseAdapter{
private Context mContext;
//private int mNumRows;
//private ArrayList<Integer> imagenes;
private ArrayList<UserBasicInfo> users;
public PanelAdapterUsers(Context context){
mContext = context;
//imagenes = new ArrayList<Integer>();
users = new ArrayList<UserBasicInfo>();
// Añado los objetos de usuario, desde la bbdd
// ...
// Pongo una imagen dinámica de prueba
//users.add("http://wwwdi.ujaen.es/sites/default/files/yo.jpg");
}
@Override
public int getCount(){
return users.size();
}
// AÑADIR ITEM AL ADAPTADOR
public void addView(UserBasicInfo user){
users.add(user);
}
// ELIMINAR ITEM DEL ADAPTADOR
public void deleteView(int position){
users.remove(position);
}
// Devolver la URL de la imagen por posición
@Override
public UserBasicInfo getItem(int position){
return users.get(position);
}
@Override
public long getItemId(int position){
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
//TextView view;
//Button view;
ImageView view;
if(convertView == null){
//view = new TextView(this.mContext);
//view = new Button(this.mContext);
//view.setTextSize(18);
view = new ImageView(this.mContext);
// Ancho y alto de la imagen en la vista donde se va a colocar (en pixels)
view.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getPx(100)));
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setPadding(5,5,5,5);
}else{
//view = (TextView) convertView;
//view = (Button) convertView;
view = (ImageView) convertView;
}
//view.setText(" Fila " + position);
//view.setTextColor(Color.rgb(position * 10, 255 - position * 10, 200));
//Q-view.setImageResource(imagenes.get(position));
//Drawable drawable = DownloadFullFromUrl(imagenes.get(position));
//view.setImageBitmap(DownloadFullFromUrl("http://www.androidpeople.com/wp-content/uploads/2010/03/android.png"));
return view;
}
// Función que devuelve los píxeles equivalentes a los dps pasados
public int getPx(int dimensionDp) {
float density = mContext.getResources().getDisplayMetrics().density;
return (int) (dimensionDp * density + 0.5f);
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package com.yottacode.pictogram.gui;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Point;
......@@ -43,15 +44,23 @@ import com.yottacode.pictogram.action.VocabularyAction;
import com.yottacode.pictogram.dao.Picto;
import com.yottacode.pictogram.dao.User;
import com.yottacode.pictogram.grammar.Vocabulary;
import com.yottacode.pictogram.grammar.iLocalPicto;
import com.yottacode.pictogram.grammar.iVocabularyListener;
import com.yottacode.pictogram.net.PictoUploader;
import com.yottacode.pictogram.net.iImgDownloaderListener;
import com.yottacode.pictogram.tools.Img;
import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Vector;
import android.provider.Settings.Secure;
......@@ -76,18 +85,6 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
private int count_deletelong = 0;
private boolean isSupervisor = false;
private String selectedImagePath;
/*
float xAxis = 0f;
float yAxis = 0f;
float lastXAxis = 0f;
float lastYAxis = 0f;
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -96,32 +93,12 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
setContentView(R.layout.activity_pictogram);
Intent intent = getIntent();
isSupervisor = intent.getBooleanExtra("isSupervisor", false);
//isSupervisor = true;// QUITAR
//Log.d(LOG_TAG, "isSupervisor vale " + isSupervisor);
currentCategory = null; // this for refresh vocabulary when a websocket action arrived from the dashboard
count_deletelong = 0;
// Singleton getInstance
//pcb = PCBcontext.getInstance();
//FERNANDO he comentado esta llamada a PCBcontext.init ¿es realmente necesaria? ¿dónde está la llamada a set_user ---> token queda a nulo!!!
//Log.d(LOG_TAG, "1) Opening PCB");
//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);
*/
// Adapter for grid
panelAdapter = new PanelAdapter(new LinkedList<Picto>());
......@@ -145,8 +122,9 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
Point size = new Point();
display.getSize(size);
int width = size.x;
//int height = size.y;
int height = size.y;
tapeGridView.getLayoutParams().width = width - 120;
//tapeGridView.getLayoutParams().height = height - 40;
tapeGridView.requestLayout();
/*
......@@ -193,8 +171,9 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
//final Button deleteAllButton = (Button) findViewById(R.id.button_delete_all);
final ImageButton ttsButton = (ImageButton) findViewById(R.id.button_tts);
// Si los pictogramas son grandes pongo una configuración. Si son pequeños otra...
// Si los pictogramas son grandes pongo una configuración. Si son pequeños otra
int pictogramSize = 0; // ESTE VALOR SE COGE DE LA CONFIGURACION DEL USUARIO (0:normal; 1:large)
if (pictogramSize == 0) panelGridView.setNumColumns(10);
else if (pictogramSize == 1) panelGridView.setNumColumns(4);
......@@ -225,6 +204,7 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
//rowNumberAdapter.notifyDataSetChanged();
Picto p = panelAdapter.getItem(position);
if (p != null && !p.is_invisible() && p.is_enabled()) {
Log.d(LOG_TAG, "Clic en picto: " + p.toString());
//Log.d(LOG_TAG, "STATUS: " + p.get_status());
......@@ -293,7 +273,7 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
panelGridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (isSupervisor) {
if (PCBcontext.getPcbdb().getCurrentUser().is_supervisor()) {
// Si es supervisor al hacer longClick deshabilito ese pictograma o lo habilito
Picto p = panelAdapter.getItem(position);
if (p == null) {
......@@ -423,7 +403,7 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
//Log.d(LOG_TAG, "SALTO A LOGIN");
// Paso un parámetro a la SerialActivity, para controlar de dónde viene
Intent serialActivity = new Intent(getBaseContext(), SerialActivity.class);
serialActivity.putExtra("activity_name", "PictogramActivity");
serialActivity.putExtra("resetPrevUser", true);
startActivity(serialActivity);
}
......@@ -542,12 +522,7 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
return ll;
}
// De la interfaz iVocabularyListener
@Override
public void change(action action, int picto_cat, int picto_id, JSONObject args) {
Log.d(LOG_TAG, "Vocabulary action listened: " + action);
if(args!=null) Log.d(LOG_TAG, "args: " + args.toString());
public void refresh() {
// Background task that updates the ui into the main thread.
runOnUiThread(new Runnable() {
@Override
......@@ -567,6 +542,13 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
}
});
}
// De la interfaz iVocabularyListener
@Override
public void change(action action, int picto_cat, int picto_id, JSONObject args) {
Log.d(LOG_TAG, "Vocabulary action listened: " + action);
if(args!=null) Log.d(LOG_TAG, "args: " + args.toString());
refresh();
}
// Disable Back Button --> Kiosk mode
@Override
......@@ -850,26 +832,35 @@ public class PictogramActivity extends Activity implements iVocabularyListener,
// Set up the input
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT );
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
// Set up the buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int cat=PictogramActivity.this.currentCategory != null ? PictogramActivity.this.currentCategory.get_id() : Picto.NO_CATEGORY;
Picto localPicto=PCBcontext.getVocabulary().saveLocalPicto(
int cat = PictogramActivity.this.currentCategory != null ? PictogramActivity.this.currentCategory.get_id() : Picto.NO_CATEGORY;
PCBcontext.getVocabulary().saveLocalPicto(
selectedImagePath,
input.getText().toString(),
cat,
row,
col);
change(action.add, cat, localPicto.get_id(),null); //gui must be refresh
col, new iLocalPicto() {
@Override
public void saved(Picto localPicto) {
PictogramActivity.this.refresh();
try {
new PictoUploader(localPicto).upload();
} catch (IOException e) {
Log.e(Vocabulary.class.getCanonicalName(), e.getMessage());
}
}
});
}
});
builder.show();
}
/**
* Función para la selección de una foto del carrete
......
package com.yottacode.pictogram.gui;
import android.app.ListFragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.dao.Device;
import com.yottacode.pictogram.dao.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
/**
* StudentFragment show the list of the students of the device
* @author Miguel Ángel García Cumbreras
* @version 1.0
*/
public class StudentFragment extends ListFragment {
// Almaceno los estudiantes, los ids de estudiantes y supervisores
String[] students;
Vector<Integer> students_ids;
Vector<Integer> supervisor_ids;
Map<String, List<String>> map_students = new TreeMap<String, List<String>>();
Map<String, Bitmap> map_supervisor_pictures = new TreeMap<String, Bitmap>();
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Vector<User> users;
Vector<Bitmap> imageStudents = new Vector<Bitmap>();
students_ids = new Vector<Integer>();
supervisor_ids = new Vector<Integer>();
try {
Device device = new Device(getActivity(), null, 1);
// Cargo los datos de los estudiantes
users = device.getUsers();
Set<String> s_students;
List<String> l_supervisors = new ArrayList<String>();
if (users!=null){
// Recorro el vector para sacar los nombres de estudiantes y las imágenes
for( int i = 0 ; i < users.size() ; i++ ){
int st_id = users.elementAt(i).get_id_stu();
int su_id = users.elementAt(i).get_id_sup();
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
l_supervisors = new ArrayList<String>();
l_supervisors.add(su_name + " " + su_surname);
imageStudents.add(st_picture);
map_supervisor_pictures.put(su_name + " " + su_surname, su_picture);
map_students.put(st_name + " " + st_surname, l_supervisors);
students_ids.add(st_id);
supervisor_ids.add(su_id);
} else{
// Saco los supervisores, añado uno más y grabo
l_supervisors = map_students.get(st_name + " " + st_surname);
l_supervisors.add(su_name + " " + su_surname);
map_students.put(st_name + " " + st_surname, l_supervisors);
supervisor_ids.add(su_id);
}
}
// Saco los estudiantes
s_students = map_students.keySet();
students = s_students.toArray(new String[s_students.size()]);
} else{
// TRATO EL ERROR. COMO ?????
}
CustomList adapter = new CustomList(getActivity(), students, imageStudents);
setListAdapter(adapter);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* When an student is selected it calls the supervisor fragment
* @param l
* @param v
* @param position
* @param id
*/
/*
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Guardo en device el id del estudiante
Device device = new Device(getActivity(), null, 1);
device.setStuId(students_ids.elementAt(position));
// Llamo al fragment de los supervisores para cargar sus datos
SupervisorFragment supervisores = (SupervisorFragment)getFragmentManager().findFragmentById(R.id.supervisores);
// Cojo el nombre y apellidos de ese estudiante
String name_surname_st = students[position];
supervisores.change(map_students, name_surname_st, map_supervisor_pictures, supervisor_ids);
getListView().setSelector(android.R.color.holo_blue_dark);
}
*/
}
\ No newline at end of file
package com.yottacode.pictogram.gui;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.dao.Device;
import com.yottacode.pictogram.tools.PCBcontext;
import java.util.List;
import java.util.Map;
import java.util.Vector;
/**
* SupervisorFragment show the list of the supervisors of the device when an student has been selected
* @author Miguel Ángel García Cumbreras
* @version 1.0
*/
public class SupervisorFragment extends ListFragment {
Vector<Integer> supervisor_ids;
PCBcontext pcb;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.list_fragment, container, false);
// Singleton getInstance
pcb = PCBcontext.getInstance();
return view;
}
/**
*
* @param map_students list of students
* @param name_surname_st name and surname of the student selected
* @param map_supervisor_pictures pictures of the supervisors of the student selected
* @param sup_ids ids of the supervisors
*/
public void change(Map<String, List<String>> map_students, String name_surname_st, Map<String, Bitmap> map_supervisor_pictures, Vector<Integer> sup_ids){
// Saco los supervisores de ese estudiante
List<String> l_supervisors = map_students.get(name_surname_st);
String[] supervisors = l_supervisors.toArray(new String[l_supervisors.size()]);
Vector<Bitmap> imageSupervisors = new Vector<Bitmap>();
supervisor_ids = sup_ids;
for (int i=0; i<supervisors.length; i++){
String supervisor = supervisors[i];
imageSupervisors.add(map_supervisor_pictures.get(supervisor));
}
CustomList adapter = new CustomList(getActivity(), supervisors, imageSupervisors);
setListAdapter(adapter);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Guardo en device el id del supervisor
pcb.getDevice().setLastSupId(supervisor_ids.elementAt(position));
Intent pictogramActivity = new Intent(getActivity(), PictogramActivity.class);
startActivity(pictogramActivity);
}
}
\ No newline at end of file
package com.yottacode.pictogram.gui;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.dao.User;
import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
/**
* SupervisorFragmentGrid implements the gridview with the supervisors
* @author Miguel Ángel García Cumbreras
* @version 1.0
*/
public class SupervisorFragmentGrid extends Fragment {
Vector<Integer> supervisor_ids;
PCBcontext pcb;
GridView gridView;
// String constant for logs
private final String LOG_TAG = this.getClass().getSimpleName(); // Or .getCanonicalName()
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
// Singleton getInstance
pcb = PCBcontext.getInstance();
}
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_new_student, container, false);
gridView = (GridView)view.findViewById(R.id.gridview);
return view;
}
/**
*
*/
public void change(Map<Integer, Vector<Integer>> ids_stu_sup, int pos){
// Saco el stu_id de esa posicion
Vector<Integer> students_ids = new Vector<Integer>();
for(Map.Entry<Integer,Vector<Integer>> entry : ids_stu_sup.entrySet()) {
Integer id_stu = entry.getKey();
students_ids.add(id_stu);
}
Integer id_stu_selected = students_ids.elementAt(pos);
// Saco los supervisores de ese estudiante
supervisor_ids = ids_stu_sup.get(id_stu_selected);
// De cada par id_stu, id_sup saco el nombre y la imagen
List<String> l_supervisors_name = new ArrayList<String>();
Vector<Bitmap> imageSupervisors = new Vector<Bitmap>();
Iterator itr = supervisor_ids.iterator();
while(itr.hasNext()) {
Integer id_sup = (Integer) itr.next();
try {
User currentUser = pcb.getDevice().findUser(id_stu_selected, id_sup);
String su_name = currentUser.get_name_sup();
Bitmap su_picture = currentUser.get_bitmap_sup(getActivity());
l_supervisors_name.add(su_name);
imageSupervisors.add(su_picture);
String[] supervisors_name = l_supervisors_name.toArray(new String[l_supervisors_name.size()]);
CustomList adapter = new CustomList(getActivity(), supervisors_name, imageSupervisors);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
pcb.getDevice().setLastSupId(supervisor_ids.elementAt(pos));
Intent pictogramActivity = new Intent(getActivity(), PictogramActivity.class);
startActivity(pictogramActivity);
}
});
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
......@@ -112,9 +112,9 @@ public class TapeAdapter extends BaseAdapter {
if(convertView == null){
view = new ImageView(PCBcontext.getContext());
// Ancho y alto de la imagen en la vista donde se va a colocar (en pixels)
view.setLayoutParams(new GridView.LayoutParams(getPx(80), getPx(60)));
view.setLayoutParams(new GridView.LayoutParams(80, 60));
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setPadding(5,10,5,5);
view.setPadding(5,5,5,5);
//view.setPadding(10,15,10,10);
}else{
view = (ImageView) convertView;
......
package com.yottacode.pictogram.gui;
/**
* Created by miguelangel on 16/3/15.
*/
public class UserBasicInfo {
private String FirstName;
private String Id;
private String ImageUrl;
public UserBasicInfo(String firstname, String id, String imageUrl) {
this.FirstName = firstname;
this.Id = id;
this.ImageUrl = imageUrl;
}
public String getFirstName() {
return this.FirstName;
}
public void setFirstName(String firstname) {
this.FirstName = firstname;
}
public String getUsertId() {
return this.Id;
}
public void setUserId(String Id) {
this.Id = Id;
}
public String getImageUrl() {
return this.ImageUrl;
}
public void setImageUrl(String imageUrl) {
this.ImageUrl = imageUrl;
}
}
\ No newline at end of file
......@@ -69,7 +69,6 @@ public class ImgDownloader extends AsyncTask<Vector<Img>, Void, Img> {
if (!img.exists_bitmap(this.context) || this.force_download) try {
this.activityManager.getMemoryInfo(mi);
Log.i(this.getClass().getCanonicalName(), "Picto Img "+img.get_url() + " to be downloaded");
if (this.source==source.remote) {
String surl = context.getResources().getString(R.string.server) + "/" + img.get_url();
URL url = new URL(surl);
......@@ -114,7 +113,6 @@ public class ImgDownloader extends AsyncTask<Vector<Img>, Void, Img> {
@Override
protected void onPostExecute(Img img) {
PCBcontext.getDevice().deleteDeprecatedImgs();
if (imgListener!=null)
if(img == null) imgListener.loadComplete();
else imgListener.loadImg(img);
......
package com.yottacode.pictogram.net;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.yottacode.net.RestapiWrapper;
import com.yottacode.net.iRestapiListener;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.dao.LoginException;
import com.yottacode.pictogram.dao.User;
import com.yottacode.pictogram.gui.PictogramActivity;
import com.yottacode.pictogram.gui.SerialActivity;
import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Hashtable;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
......@@ -28,39 +38,67 @@ import java.util.concurrent.TimeUnit;
public class NetService implements Runnable {
public static final String PREFS_NAME = "MyPrefsFile";
static final String ping_session="server/ping";
private boolean updated;
public NetService(int delay) {
this.updated=RestapiWrapper.ping(PCBcontext.getContext().getResources().getString(R.string.server), ping_session, new iRestapiListener() {
@Override
public void preExecute() {
}
@Override
public void result(JSONArray result) {
}
@Override
public void result(JSONObject result) {
updated=true;
}
@Override
public void error(Exception e) {
updated=false;
}
});
this.updated=RestapiWrapper.ping(PCBcontext.getContext().getResources().getString(R.string.server), ping_session);
Log.i(this.getClass().getName(), "Checking Pictogram server access...");
Log.i(this.getClass().getName(), this.updated ? "Pictogram server access ok" : "Pictogram server access failed, Internet connection available?");
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleWithFixedDelay(this, 0, delay, TimeUnit.SECONDS);
}
public void login() {
User user=PCBcontext.getPcbdb().getCurrentUser();
if (user.is_supervisor())
ServerLogin.login_supervisor(user.get_email_sup(), user.get_pwd_sup(), new iRestapiListener() {
@Override
public void preExecute() {
}
@Override
public void result(JSONArray result) {
PCBcontext.getPcbdb().user_online(true);
}
@Override
public void result(JSONObject result) {
}
@Override
public void error(Exception e) {
Log.e(this.getClass().getSimpleName(), "Error un when server login:" + e.getMessage());
if (e instanceof LoginException) PCBcontext.restart_app();
}
});
else ServerLogin.login_student(user.get_nickname_stu(), user.get_pwd_stu(), new iRestapiListener() {
@Override
public void preExecute() {
}
@Override
public void result(JSONArray result) {
PCBcontext.getPcbdb().user_online(true);
}
@Override
public void result(JSONObject result) {
}
@Override
public void error(Exception e) {
Log.e(this.getClass().getSimpleName(),"Error un when server login:"+e.getMessage());
if (e instanceof LoginException) PCBcontext.restart_app();;
}
});
}
public boolean online() {return updated;}
/**
......@@ -84,21 +122,52 @@ public class NetService implements Runnable {
if (result == null) {
updated = false;
} else if (!updated) {
Log.i(this.getClass().getName(), "PCB reconnect");
PCBcontext.getRoom().reconnect();
PCBcontext.getVocabulary().synchronize();
PCBcontext.getActionLog().batch();
updated = true;
// Comprobar si hay usuario offline, para hacer login transparente
if (PCBcontext.is_user_offline()){
login();
} else if (PCBcontext.is_user_online()){
Log.i(this.getClass().getName(), "PCB reconnect");
PCBcontext.getRoom().reconnect();
PCBcontext.getVocabulary().synchronize();
PCBcontext.getActionLog().batch();
updated = true;
}
}
Log.i(this.getClass().getName(), "PCB status checked. Updated? " + updated);
notifyStatus();
}
@Override
public void error(Exception e) {
updated = false;
Log.i(this.getClass().getName(), "PCB offline because exception happens: " + e.getMessage());
notifyStatus();
}
});
}
private void notifyStatus() {
NotificationCompat.Builder builder;
int notifyID = 1;
builder = new NotificationCompat.Builder(PCBcontext.getContext());
Intent resultIntent = new Intent(PCBcontext.getContext(), PictogramActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(PCBcontext.getContext());
stackBuilder.addParentStack(PictogramActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
if (updated)
builder.setSmallIcon(R.drawable.picton)
.setContentTitle("Pictogram online")
.setContentText(PCBcontext.getContext().getResources().getString(R.string.pictogram_online));
else
builder.setSmallIcon(R.drawable.pictoff)
.setContentTitle("Pictogram offline")
.setContentText(PCBcontext.getContext().getResources().getString(R.string.pictogram_offline));
NotificationManager mNotificationManager =
(NotificationManager) PCBcontext.getContext().getSystemService(PCBcontext.getContext().NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(notifyID, builder.build());
}
}
\ No newline at end of file
......@@ -157,7 +157,7 @@ public class PictoUploader {
* i) to upload the image,
* ii) to upload the attributes
* iii) to upload the expression
* iv) delete the old local picto since it will be recovered from the server
*
**/
public void upload() throws IOException {
int old_picto=this.picto.get_id();
......@@ -166,7 +166,7 @@ public class PictoUploader {
uploadAttributes(img_id);
uploadTranslation(img_id);
PCBcontext.getRoom().emit(new VocabularyAction(VocabularyAction.ADD, PictoUploader.this.picto));
PCBcontext.getPcbdb().deletePicto(old_picto);
}
}
......
package com.yottacode.pictogram.net;
import com.yottacode.net.iRestapiListener;
import com.yottacode.pictogram.dao.LoginException;
import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Hashtable;
/**
* Created by Fernando on 01/04/2016.
*/
public class ServerLogin {
private static void checkLogin(JSONObject result) throws LoginException {
String error;
try {
error=result.has("error")
? result.getString("error")
: null;
} catch (JSONException e) {
e.printStackTrace();
error=null;
}
if (error!=null){
if (error.contains("Invalid password") || error.contains("No credentials sent"))
throw new LoginException(error, LoginException.BAD_PASSWORD);
else if (error.contains("User not found"))
throw new LoginException(error, LoginException.UNKNOWN_USERNAME);
}
}
public static void login_student(String username, String password, iRestapiListener listener) {
login("stu/login", null, username, password, listener);
}
public static void login_supervisor(String email, String password, iRestapiListener listener) {
login("sup/login", email, null, password, listener);
}
private static void login(String operation, String email, String username, String password, final iRestapiListener listener){
Hashtable<String, String> postDataParams = new Hashtable<String, String>();
if (email!=null) postDataParams.put("email", email);
if (username!=null) postDataParams.put("username", username);
postDataParams.put("password", password);
PCBcontext.getRestapiWrapper().ask(operation, postDataParams, "post", new iRestapiListener() {
@Override
public void preExecute() {
listener.preExecute();
}
@Override
public void result(JSONArray result) {
listener.result(result);
}
@Override
public void result(JSONObject result) {
try {
checkLogin(result);
if (PCBcontext.is_user_offline()) {
final String TAG_TOKEN="token";
PCBcontext.getPcbdb().user_online(true);
PCBcontext.getRestapiWrapper().setToken(result.getString(TAG_TOKEN));
PCBcontext.getVocabulary().synchronize();
}
listener.result(result);
} catch (LoginException e) {
listener.error(e);
} catch (JSONException e) {
listener.error(e);
}
}
@Override
public void error(Exception e) {
listener.error(e);
}
});
}
}
......@@ -4,11 +4,9 @@ package com.yottacode.pictogram.tools;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.Color;
import android.util.Log;
import com.yottacode.tools.FileTools;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
......@@ -16,8 +14,9 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import com.yottacode.tools.FileTools;
import com.yottacode.tools.BitmapTools;
/**
* Img
......@@ -127,21 +126,27 @@ public class Img {
* @throws IOException
*/
public int save_bitmap(Context context, InputStream is) throws IOException {
final float MAX_WIDTH=100;
File file = file(context);
FileOutputStream os = new FileOutputStream(file);
try {
this.bitmap = BitmapFactory.decodeStream(is, new Rect(0,0,78,66),null);
this.bitmap=BitmapFactory.decodeStream(is);
if (this.bitmap.getWidth()>MAX_WIDTH) {
this.bitmap = new BitmapTools(this.bitmap).rescale(MAX_WIDTH / (float) this.bitmap.getWidth()).paintSquare(3, Color.DKGRAY).get();
}
}catch(java.lang.OutOfMemoryError err) {
Log.e(Img.class.getCanonicalName(), "Out of memory when decoding "+this.get_url());
}
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
this.bitmap.setHasAlpha(true);
Log.i(this.getClass().getCanonicalName(), "Img Uploading Picto img" + file_name() + " from " + get_type() + "size:" + get_bitmap(PCBcontext.getContext()).getWidth() + " " + get_bitmap(PCBcontext.getContext()).getHeight());
this.bitmap.compress(Bitmap.CompressFormat.PNG, 100, outstream);
this.bitmap.compress(Bitmap.CompressFormat.PNG, 50, outstream);
byte[] byteArray = outstream.toByteArray();
os.write(byteArray);
outstream.close();
os.close();
System.gc();
return byteArray.length;
}
......
package com.yottacode.pictogram.tools;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.yottacode.net.RestapiWrapper;
import com.yottacode.net.SSLDummyContext;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.action.ActionLog;
import com.yottacode.pictogram.dao.Device;
import com.yottacode.pictogram.dao.PCBDBHelper;
import com.yottacode.pictogram.dao.User;
import com.yottacode.pictogram.grammar.Vocabulary;
import com.yottacode.pictogram.gui.SerialActivity;
import com.yottacode.pictogram.net.NetService;
import com.yottacode.pictogram.action.Room;
import com.yottacode.pictogram.net.iImgDownloaderListener;
......@@ -54,9 +57,11 @@ public final class PCBcontext {
init=true;
context = c;
device = new Device(c, null, 1);
SSLDummyContext.init(context.getResources().getBoolean(R.bool.ssl_connect));
wrapper = new RestapiWrapper(context.getResources().getString(R.string.server), null);
service = new NetService(context.getResources().getInteger(R.integer.netservice_timing));
Log.i(PCBcontext.class.getCanonicalName(), "PCB context started. It's required to be invoked set_user method");
device.deleteDeprecatedImgs();
Log.i(PCBcontext.class.getCanonicalName(), "PCB context started. It's required set_user method call");
}
else Log.e(PCBcontext.class.getClass().getCanonicalName(), "Init method was previously invoked! Please, revise your code");
}
......@@ -73,12 +78,33 @@ public final class PCBcontext {
Log.i(PCBcontext.class.getCanonicalName(), "User set at student " + student.get_name_stu());
wrapper.setToken(token);
pcbdb = new PCBDBHelper(null, 1, student);
pcbdb.user_online(token!=null);
room = new Room();
actionLog = new ActionLog();
vocabulary = new Vocabulary(listener);
}
/**
* if the user becomes from offline to online and the login is failed, then the user relogin in the app
* The most frequent reason is a password change while the user have been logged offline
*/
public static void restart_app() {
SerialActivity.resetDefaultUser();
Intent serialActivity = new Intent(PCBcontext.getContext(), SerialActivity.class);
serialActivity.putExtra("resetPrevUser", true);
PCBcontext.getContext().startActivity(serialActivity);
}
/**
*
* @return true if the user is logged offline and it has not been online previously. False in other case (user not logged, user logged online, user offline but it was previously online logged
*/
public static boolean is_user_offline() {
return pcbdb == null ? false //no hay usuario aun
: !getPcbdb().isUser_online();
}
public static boolean is_user_online() {
return pcbdb != null && getPcbdb().isUser_online();
}
// Return the context
// modified by Fernando
public static Context getContext(){ if (context==null) throw new java.lang.NullPointerException("Context is null. PCBcontext.init must be invoked previously"); return context; }
......
package com.yottacode.tools;
import android.graphics.Bitmap;
import android.graphics.Matrix;
/**
* Created by Fernando on 15/03/2016.
*/
public class BitmapTools {
Bitmap bitmap;
public BitmapTools(Bitmap bitmap) { this.bitmap=bitmap;}
public Bitmap get() {return this.bitmap;}
public BitmapTools resize(int w, int h) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = w;
int newHeight = h;
// calculamos el escalado de la imagen destino
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// para poder manipular la imagen
// debemos crear una matriz
Matrix matrix = new Matrix();
// resize the Bitmap
matrix.postScale(scaleWidth, scaleHeight);
// volvemos a crear la imagen con los nuevos valores
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
width, height, matrix, true);
this.bitmap=resizedBitmap;
return this;
}
public BitmapTools rescale(float scale) {
int width = (int) (scale * (float) this.bitmap.getWidth());
int height = (int) (scale * (float) this.bitmap.getHeight());
return resize(width,height);
}
public BitmapTools paintSquare(int thickness, int color ) {
for (int i = 0; i < this.bitmap.getWidth(); i++)
for (int t = 1; t <= thickness; t++) {
this.bitmap.setPixel(i, 0 + t-1, color);
this.bitmap.setPixel(i, this.bitmap.getHeight() - t, color);
}
for (int i = 0; i < this.bitmap.getHeight(); i++)
for (int t = 1; t <= thickness; t++) {
this.bitmap.setPixel(0 + t-1, i, color);
this.bitmap.setPixel(this.bitmap.getWidth() - t, i, color);
}
return this;
}
}
package com.yottacode.tools;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;
/**
* Created by Fernando on 01/04/2016.
*/
public class GUITools {
public interface iOKListener {
public void ok();
}
public static void show_alert(Context context, int resource_msg, String additional_msg, final iOKListener oklistener) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
String msg = context.getString(resource_msg);
if (additional_msg != null) msg += ": " + additional_msg;
Log.i(GUITools.class.getName(), "Alert:" + msg);
builder.setMessage(msg)
.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (oklistener != null) oklistener.ok();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public static void show_alert(Context context, int resource_msg) {
show_alert(context, resource_msg, null);
}
public static void show_alert(Context context, int resource_msg, String additional_msg) {
show_alert(context, resource_msg, additional_msg,null);
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="7dp"
android:color="#de0707" />
</shape>
\ No newline at end of file
......@@ -53,8 +53,8 @@
android:layout_width="match_parent"
android:paddingTop="20dp"
android:columnWidth="100dp"
android:verticalSpacing="15dp"
android:horizontalSpacing="5dp"
android:verticalSpacing="1dp"
android:horizontalSpacing="15dp"
android:stretchMode="columnWidth"
android:layout_below="@+id/tape_grid_view">
</GridView>
......
......@@ -12,7 +12,7 @@
android:layout_height="120px"
android:contentDescription="@string/app_name"
android:orientation="vertical"
android:src="@drawable/yottalogo72p"
android:src="@drawable/logo"
android:scaleX="0.5"
android:scaleY="0.5"
android:id="@+id/imageView2"
......
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
\ No newline at end of file
android:layout_height="match_parent"
android:background="@drawable/image_border"/>
\ No newline at end of file
......@@ -19,6 +19,8 @@ translation VARCHAR(60) NOT NULL
CREATE TABLE student (
id INTEGER PRIMARY KEY,
nickname TEXT(40) NOT NULL,
pwd TEXT(40) NULL,
name TEXT(40) NOT NULL,
surname TEXT(60) NOT NULL,
url_img VARCHAR(250) NOT NULL,
......@@ -30,6 +32,8 @@ attributes TEXT(1024) NULL
CREATE TABLE supervisor (
id INTEGER PRIMARY KEY,
email TEXT(140) NOT NULL,
pwd TEXT(40) NOT NULL,
name TEXT(40) NOT NULL,
surname TEXT(60) NOT NULL,
url_img VARCHAR(250) NOT NULL,
......@@ -39,7 +43,7 @@ tts_engine TEXT(100) NULL
)
;--
insert into supervisor values(-1,"","","","M","es-es",NULL)
insert into supervisor values(-1,"","","","","","M","es-es",NULL)
;--
CREATE TABLE users (
......@@ -76,10 +80,29 @@ type TEXT(5) NOT NULL CHECK (type in ('stu','sup','pic'))
;--
CREATE VIEW users_detail AS
SELECT id_stu, a.name name_stu, a.surname surname_stu, a.url_img url_img_stu, a.gender gender_stu, a.lang lang_stu, a.attributes attributes_stu,
id_sup, b.name name_sup, b.surname surname_sup, b.url_img url_img_sup, b.gender gender_sup, b.lang lang_sup, b.tts_engine tts_engine_sup
FROM student a, supervisor b, users
WHERE a.id=users.id_stu AND b.id=users.id_sup
SELECT
id_stu,
a.nickname nickname_stu,
a.pwd pwd_stu,
a.name name_stu,
a.surname surname_stu,
a.url_img url_img_stu,
a.gender gender_stu,
a.lang lang_stu,
a.attributes attributes_stu,
id_sup,
b.email email_sup,
b.pwd pwd_sup,
b.name name_sup,
b.surname surname_sup,
b.url_img url_img_sup,
b.gender gender_sup,
b.lang lang_sup,
b.tts_engine tts_engine_sup
FROM
student a, supervisor b, users
WHERE
a.id=users.id_stu AND b.id=users.id_sup
;--
CREATE VIEW collection_detail AS
......@@ -173,10 +196,25 @@ END
CREATE TRIGGER trg_insert_users_detail
INSTEAD OF INSERT ON users_detail
FOR EACH ROW
WHEN NEW.pwd_stu IS NOT NULL
BEGIN
INSERT OR REPLACE INTO student VALUES (NEW.id_stu, NEW.name_stu, NEW.surname_stu, NEW.url_img_stu, NEW.gender_stu, NEW.lang_stu, NEW.attributes_stu);
INSERT OR REPLACE INTO supervisor VALUES (NEW.id_sup, NEW.name_sup, NEW.surname_sup, NEW.url_img_sup, NEW.gender_sup, NEW.lang_sup, NEW.tts_engine_sup);
INSERT INTO users VALUES (NEW.id_stu,NEW.id_sup);
INSERT OR REPLACE INTO student VALUES (NEW.id_stu, NEW.nickname_stu, NEW.pwd_stu, NEW.name_stu, NEW.surname_stu, NEW.url_img_stu, NEW.gender_stu, NEW.lang_stu, NEW.attributes_stu);
INSERT OR REPLACE INTO supervisor VALUES (NEW.id_sup, NEW.email_sup, NEW.pwd_sup, NEW.name_sup, NEW.surname_sup, NEW.url_img_sup, NEW.gender_sup, NEW.lang_sup, NEW.tts_engine_sup);
INSERT OR REPLACE INTO users VALUES (NEW.id_stu,NEW.id_sup);
END
;--
CREATE TRIGGER trg_insert_users_detail_nostudentpwd
INSTEAD OF INSERT ON users_detail
FOR EACH ROW
WHEN NEW.pwd_stu IS NULL
BEGIN
INSERT OR REPLACE INTO
student (id, nickname,name,surname,url_img,gender,lang,attributes)
VALUES (
NEW.id_stu, NEW.nickname_stu, NEW.name_stu, NEW.surname_stu, NEW.url_img_stu, NEW.gender_stu, NEW.lang_stu, NEW.attributes_stu);
INSERT OR REPLACE INTO supervisor VALUES (NEW.id_sup, NEW.email_sup, NEW.pwd_sup, NEW.name_sup, NEW.surname_sup, NEW.url_img_sup, NEW.gender_sup, NEW.lang_sup, NEW.tts_engine_sup);
INSERT OR REPLACE INTO users VALUES (NEW.id_stu,NEW.id_sup);
END
;--
......@@ -184,8 +222,8 @@ CREATE TRIGGER trg_update_users_detail
INSTEAD OF UPDATE ON users_detail
FOR EACH ROW
BEGIN
UPDATE student SET name=NEW.name_stu, surname=NEW.surname_stu, url_img=NEW.url_img_stu, gender=NEW.gender_stu, lang=NEW.lang_stu, attributes=NEW.attributes_stu WHERE id=NEW.id_stu;
UPDATE supervisor SET name=NEW.name_sup, surname=NEW.surname_sup, url_img=NEW.url_img_sup, gender=NEW.gender_sup, lang=NEW.lang_sup, tts_engine=NEW.tts_engine_sup WHERE id=NEW.id_sup;
UPDATE student SET nickname=NEW.nickname_stu, pwd=NEW.pwd_stu,name=NEW.name_stu, surname=NEW.surname_stu, url_img=NEW.url_img_stu, gender=NEW.gender_stu, lang=NEW.lang_stu, attributes=NEW.attributes_stu WHERE id=NEW.id_stu;
UPDATE supervisor SET email=NEW.email_sup, pwd=NEW.pwd_sup, name=NEW.name_sup, surname=NEW.surname_sup, url_img=NEW.url_img_sup, gender=NEW.gender_sup, lang=NEW.lang_sup, tts_engine=NEW.tts_engine_sup WHERE id=NEW.id_sup;
END
;--
......
......@@ -16,11 +16,14 @@
<string name="title_activity_pictogram">PictogramActivity</string>
<string name="title_activity_splash_screen">SplashScreenActivity</string>
<string name="loginTitle">Who are you?</string>
<string name="passErrorTxt">Invalid password</string>
<string name="LoginError">Login</string>
<string name="passErrorMsg">This password is not correct. Try again.</string>
<string name="userErrorTxt">User not found</string>
<string name="userErrorMsg">The user is not correct. Inténtelo de nuevo.</string>
<string name="userErrorMsg">Unknown user name</string>
<string name="userLoadingTxt">Loading</string>
<string name="userLoadingMsg">Loading students. Please wait.</string>
<string name="imguserLoadingMsg">Loading images students. Please wait.</string>
<string name="noStudentsError">User without any student available</string>
<!-- Alert dialogs -->
<string name="exitPictogram">Exit Pictogram</string>
<string name="enterEscapeCode">Type escape code</string>
......@@ -33,8 +36,6 @@
<string name="codesNotEqual">The codes entered are not equal</string>
<string name="ok">Ok</string>
<string name="cancel">Cancel</string>
<string name="tabletNoYotta">Important: writes this ID number for your cabinet</string>
<string name="loginNoUsers">There are no students assigned with your tablet. Please, ask your cabinet</string>
<!-- Login -->
<string name="systemMessage">System message</string>
......@@ -51,5 +52,7 @@
<!--Upload local img -->
<string name="enterImgLabel">Enter img label</string>
<string name="notNewCats">Including new categories is not allowed</string>
<!--online/offline status-->
<string name="pictogram_offline">Please check your internet connection. </string>
<string name="pictogram_online">Server connection established. </string>
</resources>
......@@ -17,10 +17,14 @@
<string name="prompt_serial_pass">Contraseña</string>
<string name="action_entrar">Entrar</string>
<string name="loginTitle">¿Quién eres?</string>
<string name="passErrorTxt">Invalid password</string>
<string name="LoginError">Login</string>
<string name="passErrorMsg">La contraseña indicada no es correcta. Inténtelo de nuevo.</string>
<string name="userErrorTxt">User not found</string>
<string name="userErrorMsg">El usuario indicado no es correcto. Inténtelo de nuevo.</string>
<string name="userErrorMsg">Nombre de usuario desconocido</string>
<string name="userLoadingTxt">Cargando</string>
<string name="userLoadingMsg">Cargando alumnos. Por favor espere.</string>
<string name="imguserLoadingMsg">Cargando imágenes de los alumnos. Por favor espere.</string>
<string name="noStudentsError">El usuario indicado no tiene alumnos asignados. Asigne estudiantes desde el panel de control</string>
<!-- Alert dialogs -->
<string name="exitPictogram">Salir de Pictogram</string>
......@@ -34,8 +38,6 @@
<string name="codesNotEqual">Los codigos introducidos no coinciden</string>
<string name="ok">Aceptar</string>
<string name="cancel">Cancelar</string>
<string name="tabletNoYotta">Importante: anote este nº de dispositivo para indicárselo al responsable de su asociación o gabinete</string>
<string name="loginNoUsers">No está asignado ningún alumno con tu tablet. Consulte con el responsable de su asociación o gabinete</string>
<!-- Login -->
<string name="systemMessage">Mensaje del sistema</string>
......@@ -55,5 +57,8 @@
<!--Upload local img -->
<string name="enterImgLabel">Introduzca etiqueta de la imagen</string>
<string name="notNewCats">No puede añadir nuevas categorias</string>
<!--online/offline status-->
<string name="pictogram_offline">Compruebe si tiene conexión a Internet. </string>
<string name="pictogram_online">Conexón con el servidor establecida. </string>
</resources>
......@@ -11,16 +11,20 @@
<string name="title_activity_splash_screen">SplashScreenActivity</string>
<!-- Strings de serial -->
<!-- Strings de serial y login activity-->
<string name="title_activity_serial">Indique los datos de acceso</string>
<string name="prompt_serial_mail">Usuario</string>
<string name="prompt_serial_pass">Contraseña</string>
<string name="action_entrar">Entrar</string>
<string name="loginTitle">¿Quién eres?</string>
<string name="passErrorTxt">Invalid password</string>
<string name="LoginError">Login</string>
<string name="passErrorMsg">La contraseña indicada no es correcta. Inténtelo de nuevo.</string>
<string name="userErrorTxt">User not found</string>
<string name="userErrorMsg">El usuario indicado no es correcto. Inténtelo de nuevo.</string>
<string name="userErrorTxt">Usuario no encontrado</string>
<string name="userErrorMsg">Nombre de usuario desconocido</string>
<string name="userLoadingTxt">Cargando</string>
<string name="userLoadingMsg">Cargando alumnos. Por favor espere.</string>
<string name="imguserLoadingMsg">Cargando imágenes de los alumnos. Por favor espere.</string>
<string name="noStudentsError">El usuario indicado no tiene alumnos asignados. Asigne estudiantes desde el panel de control</string>
<!-- Alert dialogs -->
<string name="exitPictogram">Salir de Pictogram</string>
......@@ -34,8 +38,6 @@
<string name="codesNotEqual">Los codigos introducidos no coinciden</string>
<string name="ok">Aceptar</string>
<string name="cancel">Cancelar</string>
<string name="tabletNoYotta">Importante: anote este nº de dispositivo para indicárselo al responsable de su asociación o gabinete</string>
<string name="loginNoUsers">No está asignado ningún alumno con tu tablet. Consulte con el responsable de su asociación o gabinete</string>
<!-- Login -->
<string name="systemMessage">Mensaje del sistema</string>
......@@ -68,5 +70,8 @@
<string name="error_field_required">This field is required</string>
<string name="permission_rationale">"Contacts permissions are needed for providing email
completions."
<!--online/offline status-->
<string name="pictogram_offline">Compruebe si tiene conexión a Internet. </string>
<string name="pictogram_online">Conexón con el servidor establecida. </string>
</string>
</resources>
\ No newline at end of file
No preview for this file type
No preview for this file type
info: Starting app...
warn: Cannot read package.json in the current directory (/home/dofer/pictogram)
warn: Are you sure this is a Sails app?
warn: 
warn: The package.json in the current directory does not list Sails as a dependency...
warn: Are you sure `/home/dofer/pictogram` is a Sails app?
warn: 
info: 
info:  .-..-.
info: 
info:  Sails <| .-..-.
info:  v0.11.3 |\
info:  /|.\
info:  / || \
info:  ,' |' \
info:  .-'.-==|/_--'
info:  `--'-------'
info:  __---___--___---___--___---___--___
info:  ____---___--___---___--___---___--___-__
info: 
info: Server lifted in `/home/dofer/pictogram`
info: To see your app, visit http://localhost:1337
info: To shut down Sails, press <CTRL> + C at any time.

debug: --------------------------------------------------------
debug: :: Tue Dec 22 2015 21:34:51 GMT+0100 (CET)

debug: Environment : development
debug: Port : 1337
debug: --------------------------------------------------------
error: 
------------------------------------------------------------------------
grunt-cli: The grunt command line interface. (v0.1.13)
Fatal error: Unable to find local grunt.
If you're seeing this message, either a Gruntfile wasn't found or grunt
hasn't been installed locally to your project. For more information about
installing and configuring grunt, please see the Getting Started guide:
http://gruntjs.com/getting-started
------------------------------------------------------------------------

error: Looks like a Grunt error occurred--
error: Please fix it, then **restart Sails** to continue running tasks (e.g. watching for changes in assets)
error: Or if you're stuck, check out the troubleshooting tips below.

error: Troubleshooting tips:
error: 
error:  *-> Are "grunt" and related grunt task modules installed locally? Run `npm install` if you're not sure.
error: 
error:  *-> You might have a malformed LESS, SASS, CoffeeScript file, etc.
error: 
error:  *-> Or maybe you don't have permissions to access the `.tmp` directory?
error:  e.g., `/home/dofer/pictogram/.tmp` ?
error: 
error:  If you think this might be the case, try running:
error:  sudo chown -R 1001 /home/dofer/pictogram/.tmp

# INSTALL
---
## Instalación previa
Instalar nodejs
```
sudo apt-get install python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
```
(Sólo en Debian) Crear link simbólico por conflicto de nombre con el paquete para utilizar nodejs en lugar de node
```
sudo ln -s /usr/bin/nodejs /usr/bin/node
```
Instalar sails
```
sudo npm -g install sails
```
Fuente: http://sailsjs.org/#/getStarted
## Descarga y configuración del proyecto
Descarga del proyecto
```
git clone http://scm.ujaen.es/softuno/pictogram.git
```
Acceder a la carpeta `src` del proyecto e instalar las dependencias definidas en `package.json`
```
npm install
```
Descomprimir el archivo de pictogramas /pictogram/sails/conf/symbolstx.rar en /pictogram/sails
```
rar x symbolstx.rar
```
En carpeta `src` del proyecto levantar sails (comprobar en localhost:1337)
```
sails lift
```
O bien en modo consola para hacer pruebas (engloba a sails lift)
```
sails console
```
De las opciones que aparecen a continuación, seleccionar en producción `1. safe` o en desarrollo `2. alter`. Esta última reconstruye la BDD según los modelos definidos en sails sin eliminar la información que tuviera previamente.
```
1. safe - never auto-migrate my database(s). I will do it myself (by hand)
2. alter - auto-migrate, but attempt to keep my existing data (experimental)
3. drop - wipe/drop ALL my data and rebuild models every time I lift Sails
```
# Servidor de Pictogram e instalación del cliente web
En este directorio se encuentra el servidor web ([src](./src)) y la aplicación
web ([src/assets/app](./src/assets/app)). Los distintos ficheros de configuración
utilizados para la inicialización y el testeo de la aplicación se encuentran
en el directorio [conf](./conf).
## Dependencias
- Ubuntu >= 14.04
- Nodejs >= 0.10.37
- Npm >= 3.8.5
- Bower >= 1.4.1
## Instalación del servidor y el cliente web
- Configurar el cliente ssh para poder conectarse a los servidores de
pre.yottacode.com (se intentará conectar como el usuario ec2-user).
- Ejecutar el script [install.sh](./install.sh) para instalar todas las
dependencias del servidor y el cliente web.
- Acceder al directorio [conf](./conf) para la instalación de la base de datos.
> **Importante**: el script utilizado creará un entorno para el servidor desde
> cero, por lo que **pueden perderse los datos** almacenados por usuarios.
## Desarrollo y pruebas
Para ejecutar el servidor como desarrollo se debe acceder al directorio
[conf](./conf) e instalar los datos de la base de datos necesarios.
## Ejecución
Para lanzar el servidor hay que acceder al directorio [src](./src) y ejecutar
uno de esos comandos:
- `sails lift`: para un servidor corriente
- `sails console`: para un servidor con un intérprete de nodejs con las
variables de sails expuestas
> El servidor se ejecutará en [localhost:1337/app](http://localhost:1337/app)
# Order of imports
# Configuración de la base de datos
* `pictodb.sql` contains the SQL statements to create the schema of the database
* `pictodb-data.sql` contains first data load with basic information for the application to work
* `pictodb-test.sql` contains test data to be loaded in order to test the application in development
## Scripts
A script called `installdb.sh` will empty existing database and generate the new one and import the data, leaving you with a fresh database for development.
- [installdb.sh](./installdb.sh) elimina la base de datos existente y realiza
una instalación limpia para producción.
- [installdb-tests.sh](./installdb-test.sh) realiza el mismo proceso
que [installdb.sh](./installdb.sh) pero añadiendo los datos de tests.
- [installdb-autismojaen.sh](./installdb-autismojaen.sh) realiza el mismo
proceso que [installdb.sh](./installdb.sh), pero añadiendo los datos de
autismojaen.
# Notes
> **Importante**: para no añadir la biblioteca de symbolstix de nuevo
> y conservarla en el caso de que ya esté en la base de datos se puede
> añadir la opción `--ignore-symbolstix` a todos los scripts (por ejemplo
> `installdb.sh --ignore-symbolstix` no importará estos datos).
## Importing data
To import `pictodb-data.sql` into MySQL without foreign key constraints, ensure that the imported file starts with `SET foreign_key_checks=0;` and then you turn on it again with `SET foreign_key_checks=1;`
## Orden de la importación
### Datos necesarios
- [init.sql](./pictodb-init.sql) inicializa el usuario y permisos de la base de
datos.
- _[init-ignoresymbolstix.sql](./sql/init-ignoresymbolstix.sql) realiza el mismo
proceso que [init.sql](./sql/init.sql), pero ignorando a symbolstix._
- [pictodb-schema.sql](./sql/pictodb-schema.sql) contiene el esquema de la base de
datos.
- _[symbolstix-categories.sql](./sql/symbolstix-categories.sql) añade las
categorías de symbolstix._
- _[symbolstix-metadata.sql](./sql/symbolstix-metadata.sql) añade los
metadatos de symbolstix._
- [pictodb-data.sql](./sql/pictodb-data.sql) contiene la información básica que
la aplicación necesita para funcionar.
- [triggers-enrolments-integrity-constraints.sql](./pictodb-triggers-enrolments-integrity-constraints.sql)
añade disparadores para el control de integridad de inscripciones.
- [triggers-sessions-integrity-constraints.sql](./pictodb-triggers-enrolments-integrity-constraints.sql)
añade disparadores para el control de integridad de sesiones.
### Añadido de datos de desarrollo y pruebas
- [test.sql](./sql/test-autismojaen.sql) contiene datos para el desarrollo y
pruebas de la aplicación.
- [test-autismojaen.sql](./sql/test-autismojaen.sql) añade los datos de
autismojaen.
## Notes
### Importación de datos
To import `pictodb-data.sql` into MySQL without foreign key constraints, ensure
that the imported file starts with `SET foreign_key_checks=0;` and then you turn
on it again with `SET foreign_key_checks=1;`
### Eliminando la base de datos completa
## Droping all tables
```sql
SET foreign_key_checks=0;
DROP TABLE `action`, `device`, `enrolment`, `instruction`, `license`, `license_activation`, `meta_picto`, `meta_stu`, `method`, `office`, `official_dev`, `picto`, `picto_acl`, `picto_core`, `picto_core_cat`, `picto_exp`, `picto_tag`, `picto_tag_sup`, `source`, `student`, `stu_picto`, `stu_sup`, `stu_sup_dev`, `supervisor`, `try`, `working_session`;
DROP TABLE `action`, `device`, `enrolment`, `instruction`, `license`,
`license_activation`, `meta_picto`, `meta_stu`, `method`, `office`,
`official_dev`, `picto`, `picto_acl`, `picto_core`, `picto_core_cat`,
`picto_exp`, `picto_tag`, `picto_tag_sup`, `source`, `student`, `stu_picto`,
`stu_sup`, `stu_sup_dev`, `supervisor`, `try`, `working_session`;
SET foreign_key_checks=1;
```
\ No newline at end of file
```
#!/bin/bash
echo "SET foreign_key_checks=0;
TRUNCATE TABLE action;
TRUNCATE TABLE device;
TRUNCATE TABLE instruction;
TRUNCATE TABLE method;
TRUNCATE TABLE office;
TRUNCATE TABLE official_dev;
TRUNCATE TABLE picto_acl;
TRUNCATE TABLE picto_tag_sup;
TRUNCATE TABLE student;
TRUNCATE TABLE stu_dev;
TRUNCATE TABLE stu_picto;
TRUNCATE TABLE stu_sup;
TRUNCATE TABLE supervisor;
TRUNCATE TABLE try;
TRUNCATE TABLE working_session;
TRUNCATE TABLE meta_method;
TRUNCATE TABLE meta_picto;
TRUNCATE TABLE meta_stu;
TRUNCATE TABLE meta_instruction;
TRUNCATE TABLE source;
TRUNCATE picto_core_cat;
SET foreign_key_checks=1;" | mysql -u pictodbuser -pp1KT015 pictodb
#!/bin/bash
ROOT_PASSWD=passwd
IGNORE_SYMBOLSTIX=false
USAGE="Usage: ${0##*/} <mysql root pwd> [--ignore-symbolstix]"
DBUSER=pictodbuser
DBNAME=pictodb
function do_exit {
echo $USAGE
exit 1
}
function execute_db {
echo $1
mysql -u $DBUSER -pp1KT015 $DBNAME < $1
}
function main {
if [ $# -eq 0 ]; then do_exit; fi
if [ $# -gt 2 ]; then do_exit; fi
if [ $# -eq 1 ]; then ROOT_PASSWD=$1; fi
if [ $# -eq 2 ]; then
if [ $2 != '--ignore-symbolstix' ]; then do_exit; fi
ROOT_PASSWD=$1
IGNORE_SYMBOLSTIX=true
fi
if [ $IGNORE_SYMBOLSTIX == true ]; then
echo Init ignoring symbolstix
mysql -u root -p$ROOT_PASSWD < ./sql/init-ignoresymbolstix.sql
else
echo Init with symbolstix
mysql -u root -p$ROOT_PASSWD < ./sql/init.sql
fi
execute_db ./sql/pictodb-schema.sql
execute_db ./sql/pictodb-data.sql
execute_db ./sql/test-autismojaen.sql
if [ $IGNORE_SYMBOLSTIX == false ]; then
execute_db ./sql/symbolstix-categories.sql
execute_db ./sql/symbolstix-metadata.sql
fi
execute_db ./sql/triggers-enrolments-integrity-constraints.sql
execute_db ./sql/triggers-sessions-integrity-constraints.sql
}
main "$@"
#!/bin/bash
ROOT_PASSWD=passwdd
IGNORE_SYMBOLSTIX=false
USAGE="Usage: ${0##*/} <mysql root pwd> [--ignore-symbolstix]"
DBUSER=pictodbuser
DBNAME=pictodb
function do_exit {
echo $USAGE
exit 1
}
function execute_db {
echo $1
mysql -u $DBUSER -pp1KT015 $DBNAME < $1
}
function main {
if [ $# -eq 0 ]; then do_exit; fi
if [ $# -gt 2 ]; then do_exit; fi
if [ $# -eq 1 ]; then ROOT_PASSWD=$1; fi
if [ $# -eq 2 ]; then
if [ $2 != '--ignore-symbolstix' ]; then do_exit; fi
ROOT_PASSWD=$1
IGNORE_SYMBOLSTIX=true
fi
if [ $IGNORE_SYMBOLSTIX == true ]; then
echo Init ignoring symbolstix
mysql -u root -p$ROOT_PASSWD < ./sql/init-ignoresymbolstix.sql
else
echo Init with symbolstix
mysql -u root -p$ROOT_PASSWD < ./sql/init.sql
fi
execute_db ./sql/pictodb-schema.sql
execute_db ./sql/pictodb-data.sql
execute_db ./sql/test.sql
if [ $IGNORE_SYMBOLSTIX == false ]; then
execute_db ./sql/symbolstix-categories.sql
execute_db ./sql/symbolstix-metadata.sql
fi
execute_db ./sql/triggers-enrolments-integrity-constraints.sql
execute_db ./sql/triggers-sessions-integrity-constraints.sql
}
main "$@"
#!/bin/bash
echo "SET foreign_key_checks=0;
DROP TABLE action, catexp, device, instruction, meta_instruction, meta_method,
meta_picto, meta_stu, method, office, official_dev, picto, pictocat, picto_acl, picto_core,
picto_core_cat, picto_exp, picto_tag, picto_tag_sup, source, student, stu_dev, stu_picto,
stu_sup, supervisor, try, working_session;
SET foreign_key_checks=1;" | mysql -u pictodbuser -pp1KT015 pictodb
mysql -u pictodbuser -pp1KT015 pictodb < pictodb.sql
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-data.sql
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-test.sql
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-autismojaen.sql
# picto, picto_exp and picto_tag
mysql -u pictodbuser -pp1KT015 pictodb < symbolmetadata.sql
# pictocat and catexp
mysql -u pictodbuser -pp1KT015 pictodb < symbolcat.sql
# Triggers for enrolments (office licenses)
mysql -u pictodbuser -pp1KT015 pictodb < pictodb_enrolments_integrity_constraints.sql
# Triggers and procedures for sessions
mysql -u pictodbuser -pp1KT015 pictodb < pictodb_sessions_integrity_constraints.sql
\ No newline at end of file
ROOT_PASSWD=passwd
IGNORE_SYMBOLSTIX=false
USAGE="Usage: ${0##*/} <mysql root pwd> [--ignore-symbolstix]"
DBUSER=pictodbuser
DBNAME=pictodb
function do_exit {
echo $USAGE
exit 1
}
function execute_db {
echo $1
mysql -u $DBUSER -pp1KT015 $DBNAME < $1
}
function main {
if [ $# -eq 0 ]; then do_exit; fi
if [ $# -gt 2 ]; then do_exit; fi
if [ $# -eq 1 ]; then ROOT_PASSWD=$1; fi
if [ $# -eq 2 ]; then
if [ $2 != '--ignore-symbolstix' ]; then do_exit; fi
ROOT_PASSWD=$1
IGNORE_SYMBOLSTIX=true
fi
if [ $IGNORE_SYMBOLSTIX == true ]; then
echo Init ignoring symbolstix
mysql -u root -p$ROOT_PASSWD < ./sql/init-ignoresymbolstix.sql
else
echo Init with symbolstix
mysql -u root -p$ROOT_PASSWD < ./sql/init.sql
fi
execute_db ./sql/pictodb-schema.sql
execute_db ./sql/pictodb-data.sql
if [ $IGNORE_SYMBOLSTIX == false ]; then
execute_db ./sql/symbolstix-categories.sql
execute_db ./sql/symbolstix-metadata.sql
fi
execute_db ./sql/triggers-enrolments-integrity-constraints.sql
execute_db ./sql/triggers-sessions-integrity-constraints.sql
}
main "$@"
set MYSQL=C:\wamp\bin\mysql\mysql5.6.17\bin\mysql.exe
echo Drop previous database
%MYSQL% -u root < pictodb_init.sql
echo Create schema
%MYSQL% -u pictodbuser -pp1KT015 pictodb < pictodb.sql
echo Insert data
%MYSQL% -u pictodbuser -pp1KT015 pictodb < pictodb-data.sql
%MYSQL% -u pictodbuser -pp1KT015 pictodb < pictodb-test-caja.sql
echo Insert symbols
%MYSQL% -u pictodbuser -pp1KT015 pictodb < symbolmetadata.sql
echo Insert cats
%MYSQL% -u pictodbuser -pp1KT015 pictodb < symbolcat.sql
echo Create constraints
%MYSQL% -u pictodbuser -pp1KT015 pictodb < pictodb_enrolments_integrity_constraints.sql
%MYSQL% -u pictodbuser -pp1KT015 pictodb < pictodb_sessions_integrity_constraints.sql
echo End
#!/bin/bash
if [ $# -eq 0 ]
then
echo "Usage: ${0##*/} <mysql root pwd>"
exit 1
fi
echo Drop previous database
mysql -u root -p$1 < pictodb_init.sql
echo Create schema
mysql -u pictodbuser -pp1KT015 pictodb < pictodb.sql
# picto, picto_exp and picto_tag
echo Insert symbols
mysql -u pictodbuser -pp1KT015 pictodb < symbolmetadata.sql
# pictocat and catexp
echo Insert cats
mysql -u pictodbuser -pp1KT015 pictodb < symbolcat.sql
echo Insert data
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-data.sql
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-test-caja.sql
echo Create constraints
# Triggers for enrolments (office licenses)
mysql -u pictodbuser -pp1KT015 pictodb < pictodb_enrolments_integrity_constraints.sql
# Triggers and procedures for sessions
mysql -u pictodbuser -pp1KT015 pictodb < pictodb_sessions_integrity_constraints.sql
echo End
#!/bin/bash
if [ $# -eq 0 ]
then
echo "Usage: ${0##*/} <mysql root pwd>"
exit 1
fi
echo Drop previous database
mysql -u root -p$1 < pictodb_init_keepsymbolstix.sql
echo Create schema
mysql -u pictodbuser -pp1KT015 pictodb < pictodb.sql
echo Insert data
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-data.sql
mysql -u pictodbuser -pp1KT015 pictodb < pictodb-test-caja.sql
echo Create constraints
# Triggers for enrolments (office licenses)
mysql -u pictodbuser -pp1KT015 pictodb < pictodb_enrolments_integrity_constraints.sql
# Triggers and procedures for sessions
mysql -u pictodbuser -pp1KT015 pictodb < pictodb_sessions_integrity_constraints.sql
echo End
......@@ -566,12 +566,12 @@ UPDATE picto_exp SET text='papá' WHERE id_pic=49287 and lang='es-es';
UPDATE picto_exp SET text='mom' WHERE id_pic=7476 and lang='en-us';
UPDATE picto_exp SET text='mom' WHERE id_pic=7476 and lang='en-gb';
UPDATE picto_exp SET text='mamá' WHERE id_pic=7476 and lang='es-es';
UPDATE picto_exp SET text='grandma' WHERE id_pic=7348 and lang='en-us';
UPDATE picto_exp SET text='grandma' WHERE id_pic=7348 and lang='en-gb';
UPDATE picto_exp SET text='abuela' WHERE id_pic=7348 and lang='es-es';
UPDATE picto_exp SET text='grandpa' WHERE id_pic=7350 and lang='en-us';
UPDATE picto_exp SET text='grandpa' WHERE id_pic=7350 and lang='en-gb';
UPDATE picto_exp SET text='abuelo' WHERE id_pic=7350 and lang='es-es';
UPDATE picto_exp SET text='grandpa' WHERE id_pic=7348 and lang='en-us';
UPDATE picto_exp SET text='grandpa' WHERE id_pic=7348 and lang='en-gb';
UPDATE picto_exp SET text='abuelo' WHERE id_pic=7348 and lang='es-es';
UPDATE picto_exp SET text='grandma' WHERE id_pic=7350 and lang='en-us';
UPDATE picto_exp SET text='grandma' WHERE id_pic=7350 and lang='en-gb';
UPDATE picto_exp SET text='abuela' WHERE id_pic=7350 and lang='es-es';
UPDATE picto_exp SET text='girl' WHERE id_pic=7329 and lang='en-us';
UPDATE picto_exp SET text='girl' WHERE id_pic=7329 and lang='en-gb';
UPDATE picto_exp SET text='chica' WHERE id_pic=7329 and lang='es-es';
......
DROP TABLE stu_opentry;
DROP PROCEDURE newTry;
DROP TRIGGER TRG_TRY_EVALUATED;
DROP TRIGGER TRG_NEW_EVENT;
DROP TRIGGER TRG_SESSION_NEW;
DELIMITER ;;
CREATE TABLE stu_opentry (
id int NOT NULL AUTO_INCREMENT,
id_stu int NOT NULL,
id_sup int NOT NULL,
id_ws int NOT NULL,
id_opentry int ,
total_tries int DEFAULT 0,
begin timestamp NULL,
end timestamp NULL,
PRIMARY KEY(id),
UNIQUE(id_stu),
UNIQUE(id_sup),
UNIQUE(id_ws),
FOREIGN KEY (id_stu) REFERENCES student,
FOREIGN KEY (id_opentry) REFERENCES try,
INDEX USING HASH (id_stu),
INDEX USING HASH (id_ws)
) ENGINE=MEMORY;;
CREATE PROCEDURE newTry(idstu INT, idsup INT, idws INT)
MODIFIES SQL DATA
BEGIN
DECLARE idopentry int;
INSERT INTO try(`id_ws`)
VALUES (idws);
SET idopentry=LAST_INSERT_ID();
INSERT INTO stu_opentry(id_stu,id_sup,id_ws,id_opentry, total_tries,begin)
VALUES (
idstu,
idsup,
idws,
idopentry,
0,
NOW()
)
ON DUPLICATE KEY UPDATE id_stu=idstu, id_sup=idsup, id_ws=idws, id_opentry=idopentry;
END;;
CREATE TRIGGER TRG_TRY_EVALUATED
AFTER UPDATE ON try
FOR EACH ROW
BEGIN
DECLARE idopentry INT;
DECLARE idws INT;
DECLARE ws_end DATE;
IF ( (old.result IS NULL) and (new.result IS NOT NULL) and (new.end>ws_end)) THEN
SELECT id_ws, id_opentry,end INTO idws, idopentry, ws_end
FROM
stu_opentry
WHERE
id_ws = NEW.id_ws;
UPDATE stu_opentry
SET end=new.end, total_tries=total_tries+1
WHERE id_ws=idws;
END IF;
END;;
CREATE TRIGGER TRG_NEW_EVENT
AFTER INSERT ON action
FOR EACH ROW
BEGIN
DECLARE idopentry INT;
DECLARE idsup_ws INT;
DECLARE idws INT;
CASE NEW.type
WHEN 'Show' THEN
SELECT id_ws, id_sup, id_opentry INTO idws, idsup_ws, idopentry
FROM
stu_opentry
WHERE
id_stu = NEW.id_stu;
IF (idopentry IS NOT NULL and NEW.id_sup IS NULL) THEN
UPDATE `try`
SET end=NOW()
WHERE id=idopentry;
call newTry(new.id_stu, idsup_ws, idws);
END IF;
WHEN 'Pause' THEN
SELECT id_ws, id_opentry INTO idws, idopentry
FROM
stu_opentry
WHERE
id_stu = NEW.id_stu;
IF (idopentry IS NULL) THEN
call newTry(new.id_stu, new.id_sup,idws);
ELSE
call deleteOpenTry(idws);
END IF;
ELSE BEGIN END;
END CASE;
END;;
CREATE TRIGGER TRG_SESSION_NEW
AFTER INSERT ON working_session
FOR EACH ROW
BEGIN
DECLARE idstu INT;
SELECT DISTINCT M.id_stu INTO idstu
FROM
instruction I,
method M
WHERE
I.id=new.id_ins AND
I.id_met=M.id;
UPDATE instruction
SET status='started'
WHERE id=new.id_ins;
CALL newTry(idstu, new.id_sup, new.id);
END;;
DELIMITER ;

87.8 KB | W: | H:

87.8 KB | W: | H:

sails/conf/EC.png
sails/doc/EC.png
sails/conf/EC.png
sails/doc/EC.png
  • 2-up
  • Swipe
  • Onion skin
#!/bin/bash
# Nodejs install
sudo apt-get update
sudo apt-get install -y python-software-properties python g++ make
sudo add-apt-repository -y ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install -y nodejs
sudo npm install -g npm
# Sails install
sudo npm install -g sails
# Sails log file
mkdir -p ./src/logs
touch ./src/logs/my_log_file.log
# Sails upload folder
mkdir -p ./upload
# Server dependencies installation
pushd ./src
npm install
popd
# Copy sails.io.js
pushd /tmp
rm -rf sailstempapp
sails new sailstempapp
popd
mkdir -p ./src/assets/app/js/lib/
cp /tmp/sailstempapp/assets/js/dependencies/sails.io.js ./src/assets/app/js/lib/
rm -rf /tmp/sailstempapp
# Link configuration file
ln ./conf/js/config.js ./src/assets/app/js/config.js
ln ./conf/js/local.js ./src/assets/app/js/local.js
# Download project assets
scp ec2-user@pre.yottacode.com:~/symbolstx.zip .
scp ec2-user@pre.yottacode.com:~/upload.zip .
unzip symbolstx
unzip upload
rm symbolstx.zip
rm upload.zip
# Client dependencies installation
sudo npm install -g bower
pushd ./src/assets/app
bower install
popd
/**
* Gruntfile
*
* This Node script is executed when you run `grunt` or `sails lift`.
* It's purpose is to load the Grunt tasks in your project's `tasks`
* folder, and allow you to add and remove tasks as you see fit.
* For more information on how this works, check out the `README.md`
* file that was generated in your `tasks` folder.
*
* WARNING:
* Unless you know what you're doing, you shouldn't change this file.
* Check out the `tasks` directory instead.
*/
module.exports = function(grunt) {
// Load the include-all library in order to require all of our grunt
// configurations and task registrations dynamically.
var includeAll;
try {
includeAll = require('include-all');
} catch (e0) {
try {
includeAll = require('sails/node_modules/include-all');
}
catch(e1) {
console.error('Could not find `include-all` module.');
console.error('Skipping grunt tasks...');
console.error('To fix this, please run:');
console.error('npm install include-all --save`');
console.error();
grunt.registerTask('default', []);
return;
}
}
/**
* Loads Grunt configuration modules from the specified
* relative path. These modules should export a function
* that, when run, should either load/configure or register
* a Grunt task.
*/
function loadTasks(relPath) {
return includeAll({
dirname: require('path').resolve(__dirname, relPath),
filter: /(.+)\.js$/
}) || {};
}
/**
* Invokes the function from a Grunt configuration module with
* a single argument - the `grunt` object.
*/
function invokeConfigFn(tasks) {
for (var taskName in tasks) {
if (tasks.hasOwnProperty(taskName)) {
tasks[taskName](grunt);
}
}
}
// Load task functions
var taskConfigurations = loadTasks('./tasks/config'),
registerDefinitions = loadTasks('./tasks/register');
// (ensure that a default task exists)
if (!registerDefinitions.default) {
registerDefinitions.default = function (grunt) { grunt.registerTask('default', []); };
}
// Run task functions to configure Grunt.
invokeConfigFn(taskConfigurations);
invokeConfigFn(registerDefinitions);
};
# INSTALL
---
## Instalación previa
Instalar nodejs
```
sudo apt-get install python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
```
(Sólo en Debian) Crear link simbólico por conflicto de nombre con el paquete para utilizar nodejs en lugar de node
```
sudo ln -s /usr/bin/nodejs /usr/bin/node
```
Instalar sails
```
npm -g install sails
```
Fuente: http://sailsjs.org/#/getStarted
## Descarga y configuración del proyecto
Descarga del proyecto
```
git clone http://scm.ujaen.es/softuno/pictogram.git
```
Acceder a la carpeta `src` del proyecto e instalar las dependencias definidas en `package.json`
```
npm install
```
En carpeta `src` del proyecto levantar sails (comprobar en localhost:1337)
```
sails lift
```
O bien en modo consola para hacer pruebas (engloba a sails lift)
```
sails console
```
# sails_demo
# Cliente web
a [Sails](http://sailsjs.org) application
# Run test
sais/src/$ mocha test/unit/**/*.js --timeout 30000
\ No newline at end of file
Este es el cliente web servido por Sails como aplicación por defecto. Para
instalar todas las dependencias sólo hay que ejecutar el script
[install.sh](../install.sh) que se encuentra en el directorio del servidor.
module.exports = function(req, res, next) {
var token;
//
// Token comes in the header
//
if (req.headers && req.headers.authorization) {
var parts = req.headers.authorization.split(' ');
if (parts.length == 2) {
var scheme = parts[0],
credentials = parts[1];
if (/^Bearer$/i.test(scheme)) {
token = credentials;
}
} else {
return res.json(401, {err: 'Format is Authorization: Bearer [token]'});
}
//
// Token comes as a parameter
//
} else if (req.param('token')) {
token = req.param('token');
// We delete the token from param to not mess with blueprints
delete req.query.token;
: } else {
return res.json(401, {err: 'No Authorization header was found'});
}
//
// We have a token, let's verify it
//
sailsTokenAuth.verifyToken(token, function(err, token) {
if (err) return res.json(401, {err: 'Invalid token'});
req.token = token;
next();
});
};
\ No newline at end of file
......@@ -29,5 +29,10 @@
"angular-sanitize": "~1.4.1",
"angular-chart.js": "~0.7.2",
"ng-lodash": "~0.3.0"
},
"resolutions": {
"angular": ">=1 <1.3.0",
"humanize-duration": "~3.0.0",
"momentjs": "~2.10.3"
}
}
......@@ -33,5 +33,8 @@
"url": "http://scm.ujaen.es/softuno/pictogram.git"
},
"author": "emblanco, amontejo",
"license": ""
"license": "",
"devDependencies": {
"node-inspector": "^0.12.8"
}
}
{
"name": "sails_demo",
"private": true,
"version": "0.0.0",
"description": "a Sails application",
"keywords": [],
"dependencies": {
"sails": "~0.10.5",
"sails-disk": "~0.10.0",
"rc": "~0.5.0",
"include-all": "~0.1.3",
"ejs": "~0.8.4",
"grunt": "0.4.2",
"grunt-sync": "~0.0.4",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-sails-linker": "~0.9.5",
"grunt-contrib-jst": "~0.6.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-uglify": "~0.4.0",
"grunt-contrib-cssmin": "~0.9.0",
"grunt-contrib-less": "0.11.1",
"grunt-contrib-coffee": "~0.10.1",
"jsonwebtoken": "~0.4.0",
"bcrypt": "~0.7.8"
},
"scripts": {
"start": "node app.js",
"debug": "node debug app.js"
},
"main": "app.js",
"repository": {
"type": "git",
"url": "git://github.com/emblanco/sails_demo.git"
},
"author": "emblanco",
"license": ""
}
\ No newline at end of file
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