;(function() { window.createMeasureObserver = (measureName) => { var markPrefix = `_uol-measure-${measureName}-${new Date().getTime()}`; performance.mark(`${markPrefix}-start`); return { end: function() { performance.mark(`${markPrefix}-end`); performance.measure(`uol-measure-${measureName}`, `${markPrefix}-start`, `${markPrefix}-end`); performance.clearMarks(`${markPrefix}-start`); performance.clearMarks(`${markPrefix}-end`); } } }; /** * Gerenciador de eventos */ window.gevent = { stack: [], RUN_ONCE: true, on: function(name, callback, once) { this.stack.push([name, callback, !!once]); }, emit: function(name, args) { for (var i = this.stack.length, item; i--;) { item = this.stack[i]; if (item[0] === name) { item[1](args); if (item[2]) { this.stack.splice(i, 1); } } } } }; var runningSearch = false; var hadAnEvent = true; var elementsToWatch = window.elementsToWatch = new Map(); var innerHeight = window.innerHeight; // timestamp da última rodada do requestAnimationFrame // É usado para limitar a procura por elementos visíveis. var lastAnimationTS = 0; // verifica se elemento está no viewport do usuário var isElementInViewport = function(el) { var rect = el.getBoundingClientRect(); var clientHeight = window.innerHeight || document.documentElement.clientHeight; // renderizando antes, evitando troca de conteúdo visível no chartbeat-related-content if(el.className.includes('related-content-front')) return true; // garante que usa ao mínimo 280px de margem para fazer o lazyload var margin = clientHeight + Math.max(280, clientHeight * 0.2); // se a base do componente está acima da altura da tela do usuário, está oculto if(rect.bottom < 0 && rect.bottom > margin * -1) { return false; } // se o topo do elemento está abaixo da altura da tela do usuário, está oculto if(rect.top > margin) { return false; } // se a posição do topo é negativa, verifica se a altura dele ainda // compensa o que já foi scrollado if(rect.top < 0 && rect.height + rect.top < 0) { return false; } return true; }; var asynxNextFreeTime = () => { return new Promise((resolve) => { if(window.requestIdleCallback) { window.requestIdleCallback(resolve, { timeout: 5000, }); } else { window.requestAnimationFrame(resolve); } }); }; var asyncValidateIfElIsInViewPort = function(promise, el) { return promise.then(() => { if(el) { if(isElementInViewport(el) == true) { const cb = elementsToWatch.get(el); // remove da lista para não ser disparado novamente elementsToWatch.delete(el); cb(); } } }).then(asynxNextFreeTime); }; // inicia o fluxo de procura de elementos procurados var look = function() { if(window.requestIdleCallback) { window.requestIdleCallback(findByVisibleElements, { timeout: 5000, }); } else { window.requestAnimationFrame(findByVisibleElements); } }; var findByVisibleElements = function(ts) { var elapsedSinceLast = ts - lastAnimationTS; // se não teve nenhum evento que possa alterar a página if(hadAnEvent == false) { return look(); } if(elementsToWatch.size == 0) { return look(); } if(runningSearch == true) { return look(); } // procura por elementos visíveis apenas 5x/seg if(elapsedSinceLast < 1000/5) { return look(); } // atualiza o último ts lastAnimationTS = ts; // reseta status de scroll para não entrar novamente aqui hadAnEvent = false; // indica que está rodando a procura por elementos no viewport runningSearch = true; const done = Array.from(elementsToWatch.keys()).reduce(asyncValidateIfElIsInViewPort, Promise.resolve()); // obtém todos os elementos que podem ter view contabilizados //elementsToWatch.forEach(function(cb, el) { // if(isElementInViewport(el) == true) { // // remove da lista para não ser disparado novamente // elementsToWatch.delete(el); // cb(el); // } //}); done.then(function() { runningSearch = false; }); // reinicia o fluxo de procura look(); }; /** * Quando o elemento `el` entrar no viewport (-20%), cb será disparado. */ window.lazyload = function(el, cb) { if(el.nodeType != Node.ELEMENT_NODE) { throw new Error("element parameter should be a Element Node"); } if(typeof cb !== 'function') { throw new Error("callback parameter should be a Function"); } elementsToWatch.set(el, cb); } var setEvent = function() { hadAnEvent = true; }; window.addEventListener('scroll', setEvent, { capture: true, ive: true }); window.addEventListener('click', setEvent, { ive: true }); window.addEventListener('resize', setEvent, { ive: true }); window.addEventListener('load', setEvent, { once: true, ive: true }); window.addEventListener('DOMContentLoaded', setEvent, { once: true, ive: true }); window.gevent.on('allJSLoadedAndCreated', setEvent, window.gevent.RUN_ONCE); // inicia a validação look(); })();
  • AssineUOL
Topo

Redes sociais e mapa de calor: como tecnologia ajuda em resgates na Turquia

Felipe Mendes

Colaboração para Tilt, em São Paulo

11/02/2023 10h24

O terremoto que devastou cidades na Turquia e Síria na última segunda-feira (6) já deixou mais de 23 mil mortos até o momento. Contudo, outras milhares de pessoas seguem desaparecidas e mais de 50 mil ficaram feridas devido aos tremores.

Dentre todas as formas de apoio empregadas para encontrar sobreviventes, voluntários da área de tecnologia estão desenvolvendo ferramentas para auxiliar nos resgate aos que ainda estão com vida em meio aos escombros.

Furkan Kiliç, engenheiro fundador da startup de software Datapad, e Eser Özvataf, CTO da empresa, começaram a reunir voluntários no Twitter para criarem um projeto que auxiliasse nas buscas. Em poucas horas, organizaram o movimento Earthquake Help Project ("Projeto de Ajuda ao Terremoto", na tradução livre).

De acordo com os responsáveis, os programas desenvolvidos já receberam mais de 100 mil visitas ate o momento.

"Recebemos mensagens de que pessoas estão sendo encontradas nos escombros e salvas por causa desses aplicativos. Este é o impacto real que esperávamos", afirmou Kiliç ao Wired.

Aplicativos e sites contra o desastre

Para desenvolver produtos e ajudar as pessoas, Kiliç e Özvataf criaram um canal no Discord para determinar o fluxo no trabalho. Em poucas horas, contavam com 15 mil desenvolvedores dispostos a utilizar a internet na busca por sobreviventes.

Inicialmente o projeto estava funcionando apenas na Turquia, mas os responsáveis já direcionaram esforços para conectar com ONGs na Síria.

"Muitas pessoas se candidataram ao mesmo tempo para ajudar e temos estilos de trabalho diferentes. Às vezes, tem sido um desafio organizar todos com uma função", afirmou Kiliç ao Wired.

O primeiro aplicativo colocado no ar pelos desenvolvedores vasculha as redes sociais para encontrar pedidos de ajuda. Ao registrar o pedido, os desenvolvedores alimentavam um mapa de calor para que os socorristas identificassem onde as pessoas estavam.

Aplicativo com mapa de calor ajuda em resgates na Turquia - Afetharita.com/Reprodução - Afetharita.com/Reprodução
Aplicativo com mapa de calor ajuda em resgates na Turquia
Imagem: Afetharita.com/Reprodução

Os especialistas também criaram um portal que pode ser utilizado tanto por vítimas quanto por voluntários. Nele, pessoas afetadas pelo terremoto podem relatar se estão seguras ou se precisam de ajuda. Já os voluntários podem fazer doações online ou ainda encontrar pontos onde podem levar ajuda.

Ao Wired, Kiliç afirmou que uma das dificuldades do projeto é conseguir acelerar o tempo de carregamento das páginas desenvolvidas, já que as conexões de internet foram interrompidas nas áreas afetadas.

"A tecnologia é incrivelmente poderosa", afirma o engenheiro. "Se combinarmos a tecnologia com o trabalho das equipes de resgate, podemos ajudar as pessoas mais rapidamente. Com esta tecnologia, podemos acabar salvando mais vidas."