Arxius

Archive for the ‘Uncategorized’ Category

Number base conversion from 64 to 58

If you are only looking for an example, you can find one here in my GitHub.

It would seem that a number base conversion is easy. And it is unless you deal with very large numbers. In this case, the problem gets worse. Here I explain how I developed an efficient base change algorithm that will take simple execution requisites for large number conversions.

As this nice page explains, the simplest way to convert base number is this algorithm:

// M = input number, N = output base,
result = “”
if M < N, result = ‘M’ + result. Stop.
S = M mod N, result = ‘S’ + result
M = M/N
goto 2

For example, if we try to convert 100 from base 10 to base 16, we should follow these steps:

M = 100, N = 16
100 < 16 ?
S = 4, result = ‘4’
M = 100/16 = 6
6 < 16 ?
result = ’64’

And therefore, we’ll get that 100 is equal 64 in base 16.

However, this algorithm involves working with the whole input number in math operations (such as division and modulus). If you tried to convert a long number (let’s suppose a long number has more than 30 digits), it would be needed a very long numeric data type for this operations. For instance, to allow a 60 hexadecimal digit number, we would need a 240-bit (30 bytes) data type number, which does not exist in most languages (usually the largest types are long and double-precision, with 64 bit).

So, I tried to find out a different way to manage a base conversion, where it would be possible to slice the number and work with their parts independently. It came to me that there must be an easier way to shift a number by only 1 base. And actually there is.

Let’s try to explain it with a simple example. Imagine you want to convert a 2 digit number from base 16 to base 15, for instance, the number “43 hex”. The second digit of this number (4) means that in fact, we have added 4*16 times the 1 value. If we try to allocate the same value in a 15 base number, we could find easily that: (4*16) = 4 * (4*15), so the second digit remains as “4”, but we must add the same second digit value to the first digit value (4+3). Finally, we get that “43” base 16 = “47” base 15. Notice that we did this conversion only with a simple and independent digit sum.

Well, to be fair let’s see the worst case in this conversion example. Let’s try to convert in the same way the number “FF hex” to 15 base. If we apply the same rule, by decoding the number as “FF = (F * 16) + F = (F * 15) + F + F”, we’ll have an overflow at the first digit (F + F = 1E), so we must add (carry) this “1” spent value to the second digit. And then, the second digit “F + 1” will also have another overflow, and will also take another carry value to the next digit. So finally we’ll get that “FF hex” equals to “1FE” in base 15. In fact, the method is the same, though we must pay attention to the carry values.

Now let’s try to convert a 4 digit number “5A78 hex”. In order to introduce yourself to my algorithm’s notation, I’m going to write this number as an integer array: “5A78 hex” = [5,10,7,8]. If we try to apply the same method, we’ll find that “[5,10,7,8] = (5 * 16³) + (10 * 16²) + (7 * 16) + 8”. By decoding every part independently, we’ll get:

(8 * 16⁰) = (8 * 15⁰) = [0,0,0,8]
(7 * 16¹) = (7 * 15) + 7 = [0,0,7,7]
(10 * 16²) = (10 * 15²) + (10 * 2 * 15) + 10 = [0,10,(10*2),10]
(5 * 16³) = (5 * 15³) + (5 * 3 * 15²) + (5 * 3 * 15) + 5 = [5,(5*3),(5*3),5]

It means that, for shifting each digit, we must add the following values:

5 10 7 8  
      8 the first digit needn’t be shifted
    7 7 to shift the second digit
  10 20 10 to shift the third digit
5 15 15 5 to shift the fourth digit
5 25 42 30 without carrying the overflows
6 12 14 0  

And thereafter, without missing the overflow carries, we’ll get the result = [6,12,14,0].
Notice that the same matrix would work for any other 4 digit conversion since we express the accumulators (the numbers we must add to shift the digits) as a multipliers of the original digits:

d c b a
      a
    b b
  c 2c c
d 3d 3d d

So, by following this method we can increase this matrix in size to the needed digits, and then apply simple sums for each digit. For instance, the 8 digit conversion matrix  is equal to:

h g f e d c b a
              a
            b b
          c 2c c
        d 3d 3d d
      e 4e 6e 4e e
    f 5f 10f 10f 5f f
  g 6g 15g 20g 15g 6g g
h 7h 21h 35h 35h 21h 7h h

We can also apply this to convert, for example, the number “39485A78 hex”. We only must apply this fix multiplier matrix:

              1
            1 1
          1 2 1
        1 3 3 1
      1 4 6 4 1
    1 5 10 10 5 1
  1 6 15 20 15 6 1
1 7 21 35 35 21 7 1

To the specific values:

  3 9 4 8 5 10 7 8
8               8
7             7 7
10           10 20 10
5         5 15 15 5
8       8 32 48 32 8
4     4 20 40 40 20 4
9   9 54 135 180 135 54 9
3 3 21 63 105 105 63 21 3
  3 30 121 268 362 311 169 54
  5 9 5 8 8 7 7 9

Once here, you should have noticed that the next goal should be to set a method for building any size multipliers matrix. Indeed, as you may have graphically seen, there’s an easier way to build the matrix without decoding each digit into a mathematical expression. Instead, we can iterate each digit and get the next multiplier value by adding the multiplier value at its previous position (at its right position in the grid). It would be something like:

 

gapi

We could easily get this with the following double loop:

var buffer_mult = [1,0,0,0,0,.....]; // First multiplier must be set as 1
for (var cdig = 0; cdig < buffer_mult.length; cdig++) {
    for (var t = cdig; t > 0; t--) buffer_mult[t] += (buffer_mult[t - 1] || 0);
}

This method always works for every number.

However, in the same way as the matrix grows, we’ll get higher multiplier values. We can reach several millions at a 30 digit conversion though there’s an optimization to avoid this lack. Shifting the multiplier values up, with a modulus and carry values at the conversion base, we could manage to avoid big numbers getting the same result.

For instance, in the last example we can optimize the seventh interation by shifting up the values over 15:

  1 6 15 20 15 6 1
    +1 +1 +1      
  1 7 1 6 0 6 1
1 8 8 7 6 6 7 1

and get the same result with fewer multiplier values.

.

Practical case: Convert from hexadecimal to 58 base

.

A practical case of this method could be used to convert from base 64 to base 58. It is usual to need number conversion to base 58 when you’re dealing with bitcoin addresses, URL shorteners and others. Therefore, it is nice to have a good way to do it.

I did it by applying this method with good results. I applied 6 times the algorithm, shifting from base 64 to base 58. I had good results with some 80 digit hexadecimal numbers. Fast executions, with less than 50.000 iterations, and maximum variable’s values under 200.000.

If you’d like to check it out, you can find this example developed in a simple html/javascript page just here in my GitHub repository, or try it working here.

gapi.png

Or if you are not still satisfied, here’s another page where you can find another ways to get the same.

 

 

 

 

Anuncis

Working with google APIs

We’ve already seen how to develop a whole web app using the «Web App Scripts». However, many times we would like to keep our web app into another place/server, so in this case we must use the google APIs to interact with the google services. Let’s see how to do it.

Grant access to the APIs

Before coding anything, we must grant the access to the APIs we’re going to use into our google account.

So go to : https://console.developers.google.com/ and create a new project (for instance, project2):

gapi

Then, go to «APIs & auth», «APIs» option of the new Project, and there select the API you want to enable for the project. In our example it will be the «Drive API» :

gapi

And set “enable” the API for the project :

gapi

You may add more information about why your app needs to be connected into the Google Drive Service :gapi

Now go to the «APIs & auth», «Credentials» option, and add a new credential of «OAuth 2.0 client ID» :

gapi

There are 2 authentication methods depending on which sort of use it will be needed:

  1. We could launch requests to APIs which doesn’t need to access private data in the google account, and therefore it doesn’t need authorization, so we can use a simple access with gapi.client.setApiKey(API KEY);
  2. If we have to access private data with the APIs, we have to use the OAuth 2.0.

In the example, we’ll use the OAuth 2.0 method, so we’ll work with private data.

However, before creating it, you must setup the «Consent Screen». This is the screen that will be shown to get the authorization when the app tries to access google API for first time. So go to set it up :

gapi

type a «Product Name» and save it.

gapi

Afterwards, choose the «Web application» type and – for more safety – I advise to filter the origin domains where the app will access (in the example, we’ll use a local server, so we’ll access from local http://localhost) :

gapi

Then, you will get the «Client ID» and «Client Secret» keys. Keep your «Client ID», because we’ll need it later.

gapi

So we’ve already got it. Now we can access the services using the API.

The first time you try to access to the API, if the request parameter «immediate» is false (we’ll see it later), a window screen pop up will ask you for login into google account (if you’re not yet):

gapi

and also to allow the access to the google service:

gapi

Access the API

Now that we have the access available, let’s going to see how to use it.
We’ve built this simple html page to show an easy example :

<!DOCTYPE html>

<html>

<head>

https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js

https://apis.google.com/js/client.js

var clientId = ’10…………….apps.googleusercontent.com’;

var scopes = ‘https://www.googleapis.com/auth/drive.metadata.readonly&#8217;;

function checkAuth() {

$(‘body’).append(‘

The authorization request has been launched

‘);

gapi.auth.authorize({

‘client_id’: clientId,

‘scope’ : scopes,

‘immediate’: true

},

handleAuthResult);

}

function handleAuthResult(authResult) {

if (authResult && !authResult.error) {

$(‘body’).append(‘

The authorization request has been succesful

‘);

$(‘.send_request’).removeAttr(‘disabled’);

} else {

$(‘body’).append(‘

There was an ERROR!

‘);

}

}

</head>

<body style=”width: 100%; height: 100%; overflow: hidden;”>

<h1> Google API access example </h1>

<button id=”authorize-button1″ onclick=”checkAuth();”> check Authorization </button>

<button class=”send_request” onclick=”method_1_request();” disabled=”true”> Request method 1 (request) </button>

<button class=”send_request” onclick=”method_2_request();” disabled=”true”> Request method 2 (load) </button>

<button class=”send_request” onclick=”method_3_request();” > Request method 3 (CORS) </button>

</body>

</html>

The first we need is include the google API’s JS library into our page (https://apis.google.com/js/client.js). We’re going to launch the request with a javascript code, although there’re many other ways to do it. You can also use PHP, Java, Python, etc.. (https://developers.google.com/api-client-library/).

As you can guess, before anything the app has to authenticate the client access to the API services. In the example, as we’ve set it up before, we’ll use the OAuth 2.0. As you can see in the code, we put a button that calls a javascript function «checkAuth», where we use the gapi.auth.authorize() function. This uses 2 parameters. The first parameter is an object with the following values:

  1. client_id: This is the ID you’ve got after setting up the google API service access. Just put the code there, or use an input parameter to set it.
  2. scope: Here we have to specify which scope (part of the service) we will use. Each API has many scopes, and depending on what our app wants to do, we must choose the most suitable. In the example, we’re using the «drive.metadata.readonly» scope of the Google Drive API. However we could use many others.
  3. immediate: This (true/false) value – as we’ve seen before – sets the app to show the authorization popup window, or not. (true = it doesn’t show the popup / false = it does show the popup).

And the second parameter, is a handler function (handleAuthResult), to be called after the request finishes, in order to handle the answer. The most common we should do here is to test the result of the request with the parameter (authRestful), and then proceed as the app needs.

If you try to execute the example, you’ll see that there’s an authorization request to the API:

gapi

gapi

As you may know, the google API works as a RESTful method. It means that the client (javascript, or any else we’re using) and the server (google) uses a http URL structured interface to compose the messages for sending requests and responses. You can learn more about this process there.

So, let’s see how to build and send a request. Here we have 3 different options. We can either use a simple request call (with gapi.client.request), or a faster technique, that loads previously the API interface. Even more, we also could build manualy an XHR request (with CORS).

Method 1: gapi.client.request

The easier one. We can quickly compose a http request using the gapi.client.request function. This uses an object parameter where we must set the required values to build the request, as the «path» (in the example, we’re using the drive file list request), the «method» (GET by default for reading, although it could be POST / PUT / DELETE), «params» for specific parameters of the request, and «headers» and «body», which we’re not going to use for now.

function method_1_request() {
    $(‘body’).append(‘<p>Drive API direct request has been launched</p>’);
    var restRequest = gapi.client.request({
       ‘path’ : ‘https://www.googleapis.com/drive/v2/files&#8217;,
        ‘method’ : ‘GET’,
        ‘params’ : { ‘maxResults’: 10, ‘q’ : ‘trashed=false’ }
        });
    restRequest.then(
       function(resp) { load_result(resp.result); }, // Success function
       function(reason) { $(‘body’).append(‘<p>There was an ERROR!</p>’); }); // Error function
}

After the request, as we have previously set with the «restRequest.then», it will launches the response handled function (load_result if it goes ok).

The request we’ve used for the example (drive/v2/files), as you may have already read in the documentation, asks google Drive for a metadata list of our stored files, and returns it in a JSON structure:

{
“kind” : “drive#fileList”,
“etag” : etag,
“selfLink” : string,
“nextPageToken” : string,
“nextLink” : string,
“items” : [ files Resource ]
}

As an example, we could print it into the page with and easy dynamic script :

function load_result(resp) {
    $(‘body’).append(‘<p>Drive API direct request has been successful</p>’);
    var files = resp.items;
    if (files && files.length > 0) {
        $(‘body’).append(‘<ul>’);
        for (var i = 0; i < files.length; i++) {
           $(‘body’).append(‘<li>’ + files[i].title + ‘ – ‘ + files[i].id + ‘</li>’);
        }
        $(‘body’).append(‘</ul>’);
    } else {
        $(‘body’).append(‘<p>No files found.</p>’);
    }
}

And get the following result :

gapi

As you’ve seen, after pushing the button, the page launched a XHR request to talk with the API, with the URL and defined parameters:

gapi

Method 2: gapi.client.load

There’s another way to do exactly the same, though with a better performance. We could load the full client API’s interface, with the gapi.client.load() function, and henceforth use it to launch many requests. As you can imagine, it should be faster in a many requests scenario.

After loading the API interface, we can call all its available requests (for instance, those of the Drive API) through each of its functions (like gapi.client.drive.files.list). So we can manage to the same result as in the last method with the following code:

function method_2_request() {
    gapi.client.load(‘drive’, ‘v2’,
function() {
$(‘body’).append(‘<p>Drive API interface loaded</p>’);
var request = gapi.client.drive.files.list({ ‘maxResults’: 10, ‘q’ : ‘trashed=false’ });
request.execute(load_result);
}
);
}

As you can see, the result is the same, and the XHR request has the same structure and parameters :

gapi

Method 3: Direct request with CORS

We have also another method to send a request to a google API: with a direct CORS request.

To take it lighter, we may just load the auth.js library instead of the whole client.js :

https://apis.google.com/js/auth.js <!– use this for only CORS auth –>
https://apis.google.com/js/client.js <!– use this for full client API –>

and then, after getting permission from the gapi.auth.authorize function, built the XHR request directly:

function method_3_request() {
$(‘body’).append(‘<p>Launching a manual request with CORS</p>’);
gapi.auth.authorize({
client_id : clientId,
scope : scopes,
immediate : true},
function() {
var oauthToken = gapi.auth.getToken();
var xhr = new XMLHttpRequest();
var url_request = ‘https://www.googleapis.com/drive/v2/files?maxResults=10‘; // + ‘&access_token=’ + encodeURIComponent(oauthToken.access_token);
$(‘body’).append(‘<p>xhr: ‘ + url_request + ‘</p>’);
xhr.open(‘GET’, url_request);
xhr.setRequestHeader(‘Authorization’, ‘Bearer ‘ + oauthToken.access_token);
xhr.onload = function() {
var obj_res = JSON.parse(xhr.responseText);
load_result(obj_res);
};
xhr.send();
});
}

This is the same way as if we would have buit a simple XMLHttpRequest.

Nevertheless, we shouldn’t forget adding the authorization token to the request. We have 2 ways to do it:

  1. Add the access_token parameter to the URL:
    var oauthToken = gapi.auth.getToken();
    var url_request = ‘https://www.googleapis.com/drive/v2/files?maxResults=10‘ + ‘&access_token=’ + encodeURIComponent(oauthToken.access_token);
  2. Or add it to the request’s header (with the setRequestHeader function):
    var oauthToken = gapi.auth.getToken();
    xhr.setRequestHeader(‘Authorization’, ‘Bearer ‘ + oauthToken.access_token);

There’s more info about this method right here.

Categories:Uncategorized

How to use Google App Scripts

Google has a huge collection of tools which allow developers interact with its services.

gapi1

One of my favourites is the Google App Scripts. This a great tool that allow us to develop software that can work together with the most Google common services, as Gmail, Calendar, Drive, Maps, Translator, etc. Actually, this is very similar to an API, but in my opinion, what Google people are offering here is something more powerful, and easier to use, than the Google APIs.

However, we can always use the Google APIs with the same aim, but for non complex aplications I think it is better to use “Google App Scripts”.

gapi2

To work with “Google App Scripts” we need a Google account. So all the references to the Google Services we are going to use, are going to point to the ones of the logged session in the browser.

“Google App Script” can be used in several ways. We are not going to talk about scripts integrated into the Google services. Rather we are going to suppose that we have a personal Web App, and we want to link it to one of our Google services.

At this point, we have 2 choices:

  • We can create our Web App completely as a “Google App Script”.
  • Or we can create a Script, and use it as an API, requested from another Web App.

We’re going to start with the first case.

Create a Web App Script

Beyond the “App Scripts”, we can also write an host a whole html dynamic page. The only thing we need to start, is a google account with a Google Drive service. The project will be stored as a file into your Google Drive unit. So you can create one directly with the Drive New File button:

gapi1

or going directly to this URL: https://script.google.com

Both cases, we’ll get the start wizard, where there are many options, but what we are looking for is the last of the left column «Web App»

gapi1

After choosing, we’ll get that framework with an implemented example :

Apps Script Framework

As you can see, the project has 4 files :

  1. Code.gs : Here we must write our Google App Scripts. With this functions we can bind our javascript code with Google Services.
  2. Index.html : This is the main html file of our web page.
  3. Javascript.html : Here we can write the javascript code for our web app.
  4. Stylesheet.html :  Here we can write the CSS styles for our web app.

Let’s try to execute the project:

  1. Go to the menu -> Publish -> Deploy as a web app
    gapi1
  2. Choose a name for the project (f.e. project_1).
    gapi1
  3. Select the Project options and access permissions.
    gapi1
  4. And then we’ll get an URL, ended with “/exec“, like this «https://script.google.com/macros/s/[…ID…]/exec».
    gapi1

This URL contains de ID of the Web App. You can change the last part of it in order to work with it. The possible endings are:

  • /exec     With this URL, you will send the request for the published version of the Web App, and get the HTML main page.
  • /dev       With this one, you will also send the request, but rather than the last published version, you’ll get the currently developed version of the Web App.
  • /edit      With this one, you will be redirected to the “web framework” where Google allows to develop the Web App.

If we try to go to the /exec url (in a new browser window), the first time we try to launch the app, Google will ask for grant for it. So give it permission.

gapi1

And finally we will get the result page. The example Web App shows a list with the name of our 20 first files in our Google Drive main folder.

gapi1

Let’s going to see how does it work.

Initial funcion doGet()

When we launch the a GET request URL (ended with /exec), the first what Google executes is the «doGet(e)» function, stored in the Code.gs file

gapi1

We can pass “GET parameters” to this function, collected in the “e” main parameter. For example, if I called the URL with “https://script.google.com/macros/s/%5B……%5D/exec?folderId=id001“, we could read (in the doGet function) the folderId value as e.parameter.folderId.

After recieving the GET request, it constructs a template object, taking the “Index.html” template file with the HtmlService.createTemplateFromFile() function.

If there’s a “folderId” parameter into the URL, it passes this value to the template variable, or ‘root’ value if not. It means that everywhere where there’s a <?=folderId?> in the template code, will be translated by the same value we’ve given to it.

And then, the template object launches 3 methods and returns the result.

  1. With the setSandboxMode(), the result web page is served into an iFrame structure, as a sandbox, in order to protect the client browser to execute malicious javascript code.
  2. With setTitle(), we can set a Window title.
  3. With evaluate(), the template code is evaluated, converted and returned as a final HTML code.

As you must have realized, this doGet() function only return an HTML code for our main page. We could write a simpler function like that :

function doGet(e) {
return HtmlService.createHtmlOutput(‘<html> <body> <p> Hello World </p> </body> </html’);
}

and after the URL request we would get this simple html page.

Template file Index.html

Now, let’s take a glance to the Index.html template file :

gapi1

As you can see, there are some <?=folderId?> template tabs, which as we know they will be overwritten with the URL parameter value.

However, there are also another <?!= HtmlService.createHtmlOutputFromFile(‘[file name]’).getContent(); ?> template tabs.

When the template is evaluated, the createHtmlOutputFromFile(”) function creates a new HtmlOutput object, and loads all the html content of the file into the final html page result. So, in this case, it takes the ‘Stylesheet.html‘ and ‘Javascript.html‘ files, and loads all their content into the final served page

<!DOCTYPE html>
<html>
<head>
<base target=”_top”>

[All the Stylesheet.html content]
var folderId = ‘root’;

[All the JavaScript.html content]

</head>


</html>

If you wish, you can add more files, to make your application more modular. For instance, if you have to add a jQuery-UI custom library, you can add the file to the project :

gapi1

and then, insert this code into the header of the main page :

<?!= HtmlService.createHtmlOutputFromFile(‘jquery_ui’).getContent(); ?>

Bind Google Scripts with Javascript.

Now that we have the static page, let’s see the dinamic part.
Opening the «JavaScript.html» file, we can find this:

gapi2

First of all, we can realize that we’re going to work with a jQuery framework, therefore there is a library link at the top.

Then, we can see the $(function() {}) declaration. As you may know, this is the way (or one of them) to implement the short document onready function in jQuery. That means that it will be executed when the page is loaded in the browser.

So, when our page is loaded in the browser, this javascript will call automaticaly the “google.script.run” method, that binds the javascript client side code with de Google Script in the server.

In order to use this method, we must to declare :

  • getFolderContents: The “Script” function to be called (into the Code.gs file). In this case, we’re going to call the getFolderContents() script function.
  • withSuccesHandler: This is the handler function that will be called after the script function, if all goes ok.
  • withFailureHandler: This is the handler function that will be called after the macro function, if anything goes wrong.

As you can see, if the macro function goes wrong, we’ll load and show the error message into the “error-message” div, giving the apropiate style to it.

Before understanding the succes handler, we must to see how the Google Script.

So, let’s open the Code.gs file again, and look to the getFolderContents() function :

gapi2

This is an easy example about how can we deal with Google Services there. In this case, it is using the Drive App Service, that allows us to work with the Google Drive.

The script gets an initial folder. If we have passed the ID parameter, it uses getFolderById() function, else the getRootFolder() function. Then, it gets the folder file list (with getFiles) and loops its 20 first files, and gets the name of each one (with getName). It loads the list into an array object (contents.children), and returns the object.

Now, into the Javascript client side, if the macro ended ok, the updateDisplay function will be executed.

gapi2

This function collect the result array into the contents parameter, and loads the list into the page with a simple loop and some dynamic html construction.

Developing a new version

Now that we have seen how the script works, we’re going to add some new code to the example, in order to understand it a little bit better.

For example, we will add a button to create a new folder. This is not complicated.

First, we add a submit input into the HTML main page :

<input type=”submit” id=”id_add_folder_button” value=”ADD NEW FOLDER”/>

and in our init javascript function, we link a function to call when it’s clicked:

$(function() {
    $(‘#id_add_folder_button’).click(fun_add_folder);
    …
}

In the fun_add_folder javascript function, we have to call a new Google Script (addFolder) :

function fun_add_folder() {
    var fname = prompt(“Folder name:”, “New folder”);
    if ((fname != null) && (fname != ”)) {
       $(‘#id_add_folder_button’).attr(‘disabled’, ‘true’);
       google.script.run
          .withSuccessHandler(function() {
             $(‘#id_add_folder_button’).removeAttr(‘disabled’)
          })
          .withFailureHandler(function(msg) {
             $(‘#error-message’).text(msg).addClass(“error”).show();
$(‘#id_add_folder_button’).removeAttr(‘disabled’)
          })
          .addFolder(folderId, fname);
    }
}

In order to avoid parallel requests, note that just after calling the function, the button turns disabled, and after executing the Google Script it turns on again. This is not the best way to prevent multiple calls at the same time, but it is helpful show the user that he shouldn’t click again the button until the answer.

In the Code.gs file, we must code the addFolder function as :

function addFolder(folderId, folder_name) {
    if (folderId == ‘root’) Current_Folder = DriveApp.getRootFolder();
    else                    Current_Folder = DriveApp.getFolderById(folderId);
    Current_Folder.createFolder(folder_name);
}

In this case, we have 2 input parameters (the folder parent ID, and the new folder name), and none for return.

We can create a new folder as easily as with calling the createFolder() function.

Now, we can try our new version with launching the /dev URL. However, this must be a provisional URL, to try the App while we’re developing. If we try to use the /exec URL, we will not see the changes, because before that, we must publish the new version of the Web App.

To get it, we must go to “Publish” – “Deploy as web app…”, and then choose a “New” Project version. It is advised to write a comment about the changes.

gapi2

And finally, updating the project version we can use the /exec URL as well.

Categories:Uncategorized

How to set up ASUS BIOS to boot from USB

Sometimes things that must be easy, are not.

When I bought my ASUS laptop, the first I did was install my GNU Linux OS. However, my first deal was find out how to boot my new computer from a USB drive, in order to launch the instalator. But, making my life worst, I realized that ASUS’ BIOS is not so easy to understand. But finally, after following this steps below I managed to boot my laptop from an USB key.

First of all, we have a very simple way to select the boot device: Pressing the “ESC” key immediately when the computer turns on. In this case, the system shows us a little list, with the different choices of the devices and options you can boot. If your USB is in the list, that’s perfect. You only have to choose it, and that’s all.

2015-09-23 12.43.13

 

However, in my case the USB was not in this list (may the easy way be the most frequent!).

To solve it I had to enter in the BIOS setup, by pressing the “F2” key immediately when the computer turns on. For my surprise, the USB boot option did not appear in the boot list either. After several investigations, I learnt that, to enable the option, we must :

  1. Keep a valid USB key connected to the computer (this may seem fool, but it is very important, because if not, you will never see the option in the BIOS).
    BIOS1

  2. In the “Security” tab, select the “Secure Boot Menu”, and mark the “Secure Boot Control” option as [Disabled].
    BIOS2

  3. In the “Boot” tab, mark the “Fast Boot” option as [Disabled], and “Launch CSM” option to [Enable].
    BIOS3

  4. Save the changes, exit BIOS, and enter again.

When you enter again into the BIOS, in the “Boot” tab you should see the USB option in the “Boot Option Priorities” list. Even, you should also see the “Hard Drive BBS Priorities” option, below the “Boot Option Priorities” list :

BIOS4

If the USB drive is not which you need, you can change the origin with the “Hard Drive BBS Priorities” option.

Further more, if you want to set the exactly file from the boot device that have to run, you could use the “Add New Boot Option”. Here there is a menu where you can select the .EFI file (into each device) that you wish select as the initialization file.

BIOS5

 

 

Categories:Uncategorized

How to add dictionaries into an eBook reader

One of the most important ways to learn languages is by book readings. Making this work easier, there’s a powerful tool to help us: the eBook readers with inlaid dictionaries. So I’m going to explain how I did it.

First of all, you have to install Moon+ Reader (the most popular eBooks reader app) on your device. There’s a free version (with some advertisement), or if you want, you can buy the pro version (it is a little bit expensive, more than 5€ :-/ too much for me). Twice works, it doesn’t matter.
Then, open the app, and import a eBook. For example, I’m going to use one of my favourites: Robinson Crusoe :
2015-04-28 21.33.02
Open the eBook, and tap (with a long press, about 1 or 2 seconds) any word of the text. This would open the dictionary with the information of the word, but so far (in the first time) it will show you that message, because there’s no dictionary app installed :
2015-04-28 21.08.21
At this point, you have to install one Dictionary App. We’re going to install “ColorDict” app.
Press ok in the message, and it will redirect automatically to the app market to install the “ColorDict” dictionary app. Accept it, and wait the installation.
2015-04-28 21.09.47
When the installation finished, open ColorDict App.
In this app, you can add as many dictionaries as you want. For example, the wikipedia reference, the english/spanish translation, english irregular forms, and others. You can show a list of available dictionaries in the app Market by click on “Download Dictionaries” :
2015-04-28 21.11.52
Every dictionary is embedded in an another app in the Market.
In my case, I’ve installed the “English Irregular Forms Dict” (for irregular forms), “English Dictionary Wordnet” (for general word information), “Spanish English Dictionary” (for spanish translations) and “English Thesaurus Dictionary” (for synonyms).
To install them, you have to install each of those apps. Open it (each app you have installed), and this will automatically add the data dictionary into the ColorDict app. Then, you can uninstall every Data dictionary apps, because the data were included yet, and you don’t need the app anymore :
2015-04-28 22.01.03b
Now, if you open the ColorDict app again, you will see the list of installed dictionaries. Here you can disable the dictionaries you don’t want to use, and order the available dictionaries in the way you want to show the information. For example, I prefer to see the irregular forms info at top, continued by the Wordnet info, and then the Spanish translation info. So I’m going to order my list in that way :
2015-04-28 22.29.46
You can use the ColorDict app directly, by typing the searching word there. But the powerful way to use that is in the eBook reader.
Now, by tapping (with a long press) a word you don’t understand, directly into the eBook reader, the dictionaries entries will be shown over the text to help you read easier, faster, and better :
 2015-04-28 22.32.43
Enjoy it!
Categories:Uncategorized

Sobre la legitimitat de la sobirania

Qui decideix qui és sobirà?

cropped-iStock_000017452286XSmall

En primer lloc, m’agradaria deixar clara la meva opinió sobre la clau d’aquesta qüestió: la democràcia. Aquest estendard que amb tanta freqüència s’enarbora com a únic i irrevocable principi universal. M’agradaria començar matisant-lo per no caure en la trampa de la demagògia. Una llei democràtica, és a dir, escollida per la majoria d’aquells a qui afecta, no ha de ser necessàriament justa. Vull deixar clar que tot i semblar propaganda del 3er Reich, en la meva opinió l’autoritarisme tampoc ha de ser necessàriament just, al contrari, estic convençut de que una llei imposada per una minoria té encara menys probabilitats de ser justa. És normal que quan s’escull la norma entre una majoria, correspongui més adequadament al benefici comú, cosa que converteix la democràcia en el sistema probablement més just. Però tot i això, no és garantia de justícia.

Com va dir Benjamin Franklin : “La democràcia consisteix en 2 llops i un xai votant què menjar per sopar”. O per entendre’ns millor, si els típics 4 “abusons” del col·legi que s’aprofiten contínuament de l’esquifit de la classe decideixen resoldre el seu conflicte democràticament, segurament el pobre repudiat acabarà novament sense esmorzar, amb els calçotets per fora, i amb 3 puntades de peu gratuïtes. És justa aquesta decisió democràtica?

Així doncs, si la democràcia és el millor sistema per escollir una norma justa, però sense garantia de que realment ho sigui, pot realment la democràcia legitimar la sobirania dels pobles?

Tot i que la majoria d’estats han estat forjats amb la sang i el ferro dels conflictes bèl·lics, i les fronteres han estat traçades amb el dret d’invasió dels vencedors, no podem oblidar que els pobles, països i regions segueixen essent petites peces d’una gran obra arquitectònica que conforma la humanitat. I les persones, per sobre de tot, han estat sempre l’element fonamental, el maó bàsic d’aquesta construcció. En aquest gran edifici podem marcar línies per dividir portes, parets, finestres o habitacions, però en cap moment hem d’oblidar que som persones que, cooperant entre nosaltres d’una o altre manera aconseguim aixecar aquest fabulós pilar.

El que vull dir amb això, és que la idea de sobirania legítima dels pobles és un concepte irracional, que no té sentit quan s’intenta justificar la necessària cooperació a què tots estem subjectes, i que per tant no existeix cap mètode just per designar a un poble amo i senyor sobre ell mateix. La justícia és universal, igual per tothom, no existeixen lleis aplicables per uns i per altres no. De fet, la paraula justícia perd el seu sentit quan no s’aplica de forma transversal. Per aquest motiu no comparteixo l’existència de diferents nacions, ni diferents legalitats. Tots hauríem de ser mesurats amb la mateixa regla.

No obstant, davant d’una mala situació, sí que reconec que, a vegades, quan dues peces no encaixen, potser cal provar de col·locar-les d’una altre manera.

Sóc conscient de que el món real dista moltíssim de la meva utopia, i que costa encaixar-hi les meves percepcions. Per això intentaré explicar una mica millor el perquè la sobirania no pot ser mai legítima, apuntant justament a les fal·làcies sobre les que s’argumenta cada cas.

Segons la teoria d’estats de Montesquieu, és necessària la sobirania per a constituir un estat propi. Per tant, a banda de la llengua, cultura i el territori, també és necessari ser sobirà, i que la resta d’estats sobirans t’hi reconeguin com a tal. Les fórmules per les quals es pot obtenir l’estat, i per tant la sobirania, són o bé per la força militar, o bé la proclamació popular d’una majoria democràtica. En el primer cas, és evident que imposar per mitjà de la violenta és una forma injusta i il·legítima. En el segon cas però, la qüestió és, a qui li pertany decidir democràticament? Quina és la fórmula democràtica més justa per legitimar la sobirania?

És just que si la majoria de catalans escull democràticament la secessió, se’ls hi reconegui la seva pròpia sobirania? O és just que si el conjunt de l’estat espanyol escull democràticament que Catalunya no pot ser sobirana, aquesta no ho pugui ser, per damunt de la seva pròpia voluntat democràtica a ser-ho?

Evidentment en una qüestió tant complicada com aquesta cada prisma polític té la seva pròpia interpretació de justícia. Però si retirem els prismes, què és realment més just?

Si l’elecció democràtica de la major majoria és la forma més justa per definir la sobirania d’un poble (tal com sosté el govern de l’estat espanyol), llavors qualsevol altre majoria superior, com per exemple el poble d’Etiòpia, podria decidir que la sobirania del poble espanyol ja no recau en els espanyols, sinó en els etíops, i per tant els legitima a convertir Espanya en una regió de Etiòpia, encara que la majoria d’espanyols expressessin democràticament la seva voluntat en contra. Segurament el reconeixement internacional, i els interessos econòmics, converteixen aquesta hipòtesis en quelcom bastant improbable, però els que recolzen aquesta norma per Catalunya, haurien de ser conscients que si és aplicable per Espanya, també ho és per un altre poble. És just que Pakistan envaeixi Espanya i voti que aquesta no pot seguir essent sobirana? És just que els 2 llops escullin el xai per sopar?

Per altre banda, si la forma més justa defineix que la sobirania recau únicament en l’elecció d’aquells a qui afecta (com defensa el govern de Catalunya), jo mateix em podria declarar sobirà de mi mateix, de forma democràtica i sense necessitat de que ningú em reconegués, i per tant deixar d’estar subjecte a les lleis de qualsevol estat. I així, per extensió, totes les demés persones podrien fer el mateix, i viure tots en una anarquia sense autoritat, on cada persona decideix quina és la legalitat que més el beneficia individualment. Aquesta segurament és la fórmula més justa, ja que no hi ha cap imposició per la força, però tal com he plantejat, l’aplicació de la norma es pot estendre a una hipotètica situació on tothom és sobirà únicament sobre sí mateix, amb la qual cosa, la sobirania deixa de tenir sentit o simplement d’existir. Quina és la quantitat mínima de individus sobre els quals resideix el dret a la autodeterminació? És just que existeixi una quantitat mínima?

Per tant, la meva conclusió és que no existeix cap forma justa per legitimar la sobirania, ja que al cap i a la fi, la sobirania és un concepte parcial impossible d’assignar per un mètode just ni democràtic. Mai cap estat ha esdevingut sobirà de forma justa, i per tant ni la sobirania espanyola ni la sobirania catalana es poden justificar de forma legítima.

No obstant, i per aclarir a tots els qui em puguin recriminar la meva postura política sobre el conflicte català, vull acabar explicant que en l’escenari actual, posat a escollir algun dels 2 models injusts se m’ofereixen, com ja he explicat altres cops, i per la indignitat històrica amb que Felip V va usurpar el dret de les constitucions catalanes, considero menys immerescudes les sobiranies catalana i castellana per separat, que no pas la única espanyola.

Categories:Uncategorized

Comparativa Smartphones 2013

Ja sé que és un pèl tard, però aquest passat 2013 el mercat de smartphones ha estat una autèntica bogeria. Intentant reproduir les comparatives anteriors entre Samsung i HTC, aquest any m’ha estat impossible obviar altres models que fins ara no havia considerat, així que en comptes d’un duel a 2, he fet un duel a 5! Els escollits han estat :

  • El Samsung Galaxy S4
  • El HTC One
  • El Nexus 5
  • El LG G2
  • El Sony Xperia Z1

smartphones 2013

Cal reconèixer que no m’ha estat gens fàcil comparar aquests smartphones. En primer lloc cal tenir en compte que existeixen varis models per cadascun d’ells, i no sempre és evident distingir quin n’és el millor. Però com a punt de partida, i per poder fer un quadre comparatiu amb les seves característiques principals, aquests són els números :comparativaCom es pot veure, tots 5 smartphones són productes d’alta gamma, amb unes grans prestacions. Per hardware, segurament el Nexus. LG i Z1 tenen més potència, però per seleccionar el que millor s’ajusta a les nostres necessitats, cal fixar-se amb més detall a les peculiaritats que cada fabricant ha incorporat.

Llegeix més

Categories:Uncategorized
Enfilant el camí

Visualitzant el present per construir el futur

El Noguer

Visualitzant el present per construir el futur

Visualitzant el present per construir el futur