| Bots de conversa | Exemples | Dades pràctiques | Recursos CITCEA | |
| Google Apps Script | Projectes | Interacció | Inici |
En aquest exemple obtindrem la representació d'una funció, que pot ser contínua o discontínua. Per a cada funció caldrà definir el rang de valors (en ambdós eixos) que volem representar. En el programa que es mostra a continuació hem marcat en color les línies que corresponen a la definició de la funció i els rangs de visualització, la resta del programa serà igual per a qualsevol funció.
var token = "^^34328844:AAFIpk-e7j3UZtYQYQaTduf4hEhnDqIcNXI"; // API Token de Telegram
var telegramUrl = "https://api.telegram.org/bot" + token; // URL que comunica el bot de conversa amb Telegram
var ssId = "^^ThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA"; // Identificador del full de càlcul
var id_carpeta = "^^Hlod5Y4qEsLF9HrIsE6oYQa32f6NHeo"; // Carpeta on guardarem el fitxer
// Definim els colors
var negre = "#000000";
var blau = "#0000FF";
var gris = "#888888";
var transparent = "null";
function doGet(e){
var resp = grafic();
var nomFitxer = "grafic";
var fitxerNou = DriveApp.getFolderById(IdCarpeta).createFile(nomFitxer + ".svg",resp);
var idFitxer = fitxerNou.getId();
var urlDescFitxer = fitxerNou.getDownloadUrl();
var urlFitxer = "https://drive.google.com/uc?export=view&id=" + idFitxer;
var pagina = "<!DOCTYPE HTML>" + "\n";
pagina = pagina + "<html>" + "\n";
pagina = pagina + "<head>" + "\n";
pagina = pagina + "<meta charset='UTF-8'>" + "\n";
pagina = pagina + "</head>" + "\n";
pagina = pagina + "<body>" + "\n";
pagina = pagina + "<h1>Representació de la funció</h1>" + "\n";
pagina = pagina + resp + "\n";
pagina = pagina + "</body>" + "\n";
pagina = pagina + "</html>" + "\n";
return HtmlService.createHtmlOutput(pagina);
}
function doPost(e){
var data = JSON.parse(e.postData.contents); // Llegeix les dades rebudes per JSON i les guarda
var text = data.message.text; // Comanda enviada
var id = data.message.chat.id; // Identificador de la finestra d'on prové el missatge
var id_usuari = data.message.from.id; // Identificador de l'usuari
var id_missatge = data.message.message_id; // Identificador del missatge
var lang = data.message.from.language_code ; // Idioma de l'usuari
var nom_usr = data.message.from.first_name ; // Nom de l'usuari
var location = data.message.location; // Localització de l'usuari (si es sap)
var realitzat = false;
if(text == '/grafic'){
var resposta = "Estem preparant el gràfic. Espera un moment.";
sendText(id,resposta);
var resp = grafic();
var nomFitxer = "grafic";
var fitxerNou = DriveApp.getFolderById(IdCarpeta).createFile(nomFitxer + ".svg",resp);
var idFitxer = fitxerNou.getId();
var urlDescFitxer = fitxerNou.getDownloadUrl(); // Enllaç per descarregar el fitxer
// Enllaç per veure el fitxer al navegador
var urlFitxer = "https://drive.google.com/uc?export=view&id=" + idFitxer;
var blob = UrlFetchApp.fetch(urlFitxer).getBlob();
var b64 = blob.getContentType() + ';base64,'+ Utilities.base64Encode(blob.getBytes());
var htmlEst = '<style type="text/css" media="print">@page {size: landscape;} </style>';
var htmlInst = htmlEst + '<img src="data:' + b64 + '" width=900 alt="Histograma">';
var html = HtmlService.createHtmlOutput(htmlInst);
var pdf = DriveApp.createFile(html.getAs("application/pdf").setName(nomFitxer + ".pdf"));
var urlDescPDF = pdf.getDownloadUrl(); // Enllaç per descarregar el fitxer
var pdfId = pdf.getId();
var repetir = true;
var cnt = 0;
while(repetir){
var thumb = DriveApp.getFileById(pdfId).getThumbnail();
Utilities.sleep(100);
cnt++;
if((cnt > 100) || (thumb)){
repetir = false;
}
}
var descrip = "Pots descarregar el PDF aquí: " + urlDescPDF;
sendBlobFile(id,thumb,descrip);
realitzat = true;
}
if (!realitzat){
var resposta = "Comanda desconeguda";
sendText(id,resposta);
}
}
// Definim el rang de valors dels eixos i la distància entre marques
var minX = -2 * Math.PI;
var maxX = 2 * Math.PI;
var incX = Math.PI / 4;
var minY = -1.5;
var maxY = 1.5;
var incY = 0.25;
// Funció que volem representar
function funcio(x){
try{ // Fem un try per prevenir valors anòmals, com infinit
var y = Math.cos(x) - 0.2 * Math.cos(3 * x);
} catch(err) {
var y = ""; // Si hi ha un error, torna una cadena buida
}
return y;
}
function grafic(){
// Creem la capçalera
var grafic = cap(640, 480, "Capa 1")+ '\n';
// Fem els eixos
var zeroX = 50;
var zeroY = 435;
var fiX = 620;
var fiY = 25;
grafic = grafic + linia(zeroX-5, zeroY, fiX, zeroY, 3, negre, "eixX") + '\n';
grafic = grafic + linia(zeroX, fiY, zeroX, 440, 3, negre, "eixY") + '\n';
// Posem les divisions de l'eix Y
var divY = (maxY - minY) / incY;
for (i = 0; i <= divY; i++){
var ym = zeroY - ((zeroY - fiY) / divY) * i;
var valor = incY * i + minY;
valor = Math.round(valor * 100) / 100; // Posem valors amb dos decimals
var val = valor.toString().replace(".",","); // Canviant punts per comes
var noml = 'my' + i;
var nomt = 'tmy' + i;
if(valor == 0){ // Marquem la posició del zero
grafic = grafic + linia(zeroX-5, ym, fiX, ym, 2, gris, noml + "e0") + '\n';
var y0 = ym;
}
grafic = grafic + linia(zeroX-5, ym, zeroX + 1, ym, 2, negre, noml) + '\n';
grafic = grafic + text(zeroX-10, ym+5, val, 16, negre, "d", 0, 0, nomt) + '\n';
}
// Posem les divisions de l'eix X
var divX = (maxX - minX) / incX;
for (i = 0; i <= divX; i++){
var xm = zeroX - ((zeroX - fiX) / divX) * i;
var valor = incX * i + minX;
valor = Math.round(valor * 100) / 100; // Posem valors amb dos decimals
var val = valor.toString().replace(".",","); // Canviant punts per comes
var noml = 'mx' + i;
var nomt = 'tmx' + i;
if(valor == 0){ // Marquem la posició del zero
grafic = grafic + linia(xm, zeroY+5, xm, fiY, 2, gris, noml + "e0") + '\n';
}
grafic = grafic + linia(xm, zeroY+5, xm, zeroY, 2, negre, noml) + '\n';
grafic = grafic + text(xm, zeroY + 25, val, 16, negre, "c", 0, 0, nomt) + '\n';
}
// Dibuixem la línia del gràfic
incX = incX / 20; // Ara farem 20 punts per a cada divisió de l'escala
divX = (maxX - minX) / incX;
var numpunts = (maxX - minX) / incX;
var yp = ""; // El primer segment correspondrà al segon punt
for (i = 0; i <= numpunts; i++){
var valX = incX * i + minX;
var xm = zeroX - ((zeroX - fiX) / divX) * i;
var valY = funcio(valX); // Calculem la Y aplicant la funció sobre la X
// Si el punt és anòmal, no dibuixem
if(valY !== ""){ // Posem !== perquè "" == 0 però no "" === 0
var ym = y0 - ((zeroY - fiY) / (maxY - minY)) * valY;
if((valY <= maxY) && (valY >= minY)){ // Només dibuixem si queda dins
if(yp !== ""){ // Si el punt anterior no val, tampoc dibuixem
var nomlg = 'L' + i;
grafic = grafic + linia(xp, yp, xm, ym, 4, blau, nomlg) + '\n';
}
} else {
var ym = ""; // Si quedava fora, el punt no val com a anterior
}
} else {
var ym = ""; // El punt no era vàlid
}
var xp = xm; // El punt actual passa a anterior per a la propera iteració
var yp = ym;
}
// Posem el final del fitxer svg
grafic = grafic + peu();
return grafic;
}
function linia(xi, yi, xf, yf, gruix, color, ident){
var resp = '<line id="' + ident + '" x1="' + xi + '" y1="' + yi + '" x2="' + xf + '" y2="' + yf;
resp = resp + '" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="';
resp = resp + gruix + '" stroke="' + color + '" fill="none"/>';
return resp;
}
function text(x, y, txt, mida, color, alin, negreta, cursiva, ident){
if (alin == "e"){ // Esquerra
var aln = "start";
}
if (alin == "c"){ // Centre
var aln = "middle";
}
if (alin == "d"){ // Dreta
var aln = "end";
}
var resp = '<text id="' + ident + '" xml:space="preserve" text-anchor="' + aln;
resp = resp + '" font-family="serif" font-size="' + mida + '" x="' + x + '" y="' + y +'"';
if (negreta == 1){
resp = resp + ' font-weight="bold"';
}
if (cursiva == 1){
resp = resp + ' font-style="italic"';
}
resp = resp + ' stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="';
resp = resp + color + '" fill="' + color + '">' + txt + '</text>';
return resp;
}
function cap(ample, alt, titol){
var resp = '<svg width="' + ample + '" height="' + alt;
resp = resp + '" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">' + '\n'
resp = resp + '<g>' + '\n' + '<title>' + titol + '</title>';
return resp;
}
function peu(){
var resp = '</g>' + '\n' + '</svg>';
return resp;
}
function sendText(chatId,text_env,keyBoard){ // Funció que envia un text o un teclat a Telegram
keyBoard = keyBoard || 0;
if(keyBoard.inline_keyboard || keyBoard.keyboard){
var data = {
method: "post",
payload: {
method: "sendMessage",
chat_id: String(chatId),
text: text_env,
parse_mode: "HTML",
reply_markup: JSON.stringify(keyBoard)
}
}
} else {
var data = {
method: "post",
payload: {
method: "sendMessage",
chat_id: String(chatId),
text: text_env,
parse_mode: "HTML"
}
}
}
UrlFetchApp.fetch( telegramUrl + '/', data);
}
function sendBlobFile(chatId,blob_data,caption){
var payload = {
method: "sendPhoto",
chat_id: String(chatId),
photo: blob_data,
caption: caption,
parse_mode: "HTML"
};
var options = {
method: "POST",
payload: payload,
muteHttpExceptions: true
};
UrlFetchApp.fetch( telegramUrl + '/', options);
}
El gràfic obtingut és el següent:

Per veure com quedaria una funció discontínua, podem canviar les línies marcades en color per les següents:
var minX = -5;
var maxX = 7;
var incX = 1;
var minY = -3;
var maxY = 1.5;
var incY = 0.25;
// Funció que volem representar
function funcio(x){
try{ // Fem un try per prevenir valors anòmals, com infinit
var y = (1 / (x - 2)) - 1;
} catch(err) {
var y = ""; // Si hi ha un error, torna una cadena buida
}
return y;
}
El gràfic obtingut és el següent:


Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.