Mobiiltelefonide kasutamine kogu maailmas kasvab pidevalt. 2013. aasta seisuga tarbis umbes 73% Interneti-kasutajatest sisu mobiilseadme kaudu ja see protsent peaks eeldatavasti jõudma ligi 90% aastaks 2017.
Mobiilirevolutsioonil on muidugi palju põhjuseid. Kuid üks olulisemaid on see, et mobiilirakendused saavad üldjuhul juurdepääsu rikkalikumale kontekstile, kuna peaaegu kõik nutitelefonid on tänapäeval varustatud asukohaandurite, liikumisandurite, bluetoothi ja wifi-ga. Andmeid kasutades saavad rakendused saavutada kontekstiteadlikkuse, mis võib dramaatiliselt suurendada nende võimalusi ja väärtust ning võib neid rakenduste poodides tõeliselt esile tõsta.
Selles õpetuses uurime kontekstiteadlike rakenduste loomist keeruka sündmuste töötlemise näite kaudu. Kasutame üsna lihtsat näidet: kütusehinna rakendus, mis leiab teie piirkonna parimad kütusehinnad.
Sisse Rahuliku tehnoloogia kujundamine , Mark Weiser ja John Seely Brown kirjeldab rahulik tehnoloogia kui 'see, mis teavitab, kuid ei nõua meie tähelepanu ega tähelepanu'.
Kontekstiteadlikud mobiilirakendused on selle mõistega väga kooskõlas ja on oluline ja väärtuslik samm sellel teel. Nad kasutavad oma sensoritelt kogutud kontekstuaalset teavet, et pakkuda kasutajale ennetavalt väärtuslikku teavet ja teevad seda kasutaja minimaalsete jõupingutustega. Mark Weiser ja John Seely Brown kiidavad kahtlemata seda tehnoloogilist arengut.
Kontekstiteadlikkus on idee, mida rakendus saab tajuda ja reageerida kontekstuaalsete andmete põhjal, millele tal on juurdepääs. Selline rakendus kasutab rikkalikke anduriandmeid, mis on saadaval mobiilseadmes, et pakkuda kasutajale täpset ja asjakohast teavet sobivas kontekstis. Seadme kasutamise käigus jälgitavate suundumuste ja / või kasutaja tagasiside kaudu saab selline rakendus aja jooksul tegelikult 'õppida', muutudes seeläbi 'targemaks' ja kasulikumaks.
Kompleksne sündmuste töötlemine (CEP) on sündmuste töötlemise vorm, mis kasutab mitme sündmuse (s.t aja jooksul, erinevatest allikatest ja nii edasi) keerukamaid analüüse, integreerides ja analüüsides nende sisu, et tuletada sisukamat teavet ja mustreid.
Mobiilirakenduses saab CEP-d rakendada nii mobiilseadme anduritest loodud sündmustele kui ka välistele andmeallikatele, millele rakendusel on juurdepääs.
Oletame, et meie keeruka sündmuste töötlemise õpetuse jaoks on meie kütusehinna rakenduse funktsioonid piiratud järgmisega:
OK, alustame.
Alustame kasutaja kodu ja töökoha automaatse tuvastamise loogikast. Meie keerulise sündmuste töötlemise näite jaoks lihtsuse tagamiseks eeldame, et kasutajal on üsna tavaline töögraafik. Seetõttu võime eeldada, et kasutaja on tavaliselt kodus kella 2–3 ja tavaliselt oma kontoris kella 14–15.
Nende eelduste põhjal määratleme kaks CEP reeglit ja kogume asukoha ja aja andmeid kasutaja nutitelefonist:
Kõrgetasemeline asukohtade tuvastamise algoritm on kujutatud allpool.
Oletame asukohaandmete jaoks järgmist lihtsat JSON-i andmestruktuuri:
rahavoogude aruanne bilansist ja kasumiaruandest
{ 'uid': 'some unique identifier for device/user', 'location': [longitude, latitude] 'time': 'time in user's timezone' }
Märkus: Anduriandmete muutmine muutumatuks (või väärtuse tüüp) on alati hea tava, et CEP-i töövoo erinevad moodulid saaksid neid ohutult kasutada.
Rakendame oma algoritmi, kasutades a kokkupandav moodulimuster , kusjuures iga moodul täidab ainult ühte ülesannet ja helistab järgmisena, kui ülesanne on lõpule viidud. See vastab Unixile Modulaarsuse reegel filosoofia.
Täpsemalt, iga moodul on funktsioon, mis aktsepteerib config
objekt ja next
funktsioon, mida kutsutakse andmete edastamiseks järgmisele moodulile. Seega tagastab iga moodul funktsiooni, mis suudab anduriandmeid vastu võtta. Siin on mooduli põhiallkiri:
// nominal structure of each composable module function someModule(config, next) { // do initialization if required return function(data) { // do runtime processing, handle errors, etc. var nextData = SomeFunction(data); // optionally call next with nextData next(nextData); } }
Kasutaja kodu ja töökoha leidmise algoritmi juurutamiseks vajame järgmisi mooduleid:
Kõiki neid mooduleid on üksikasjalikumalt kirjeldatud järgnevates alapeatükkides.
Meie ajafilter on lihtne funktsioon, mis võtab asukohaandmete sündmused sisendina ja edastab andmed ainult next
moodul, kui sündmus toimus huvipakkuva aja jooksul. config
selle mooduli andmed koosnevad seega huvipakkuva ajasektsiooni algus- ja lõpuaegadest. (Mooduli keerukam versioon võib filtreerida mitme ajaviisi põhjal.)
Siin on ajafiltri mooduli pseudokoodi rakendamine:
function timeFilter(config, next) { function isWithin(timeval) { // implementation to compare config.start <= timeval <= config.end // return true if within time slice, false otherwise } return function (data) { if(isWithin(data.time)) { next(data); } }; }
Akumulaatori kohustus on lihtsalt koguda asukohateave, mis edastatakse seejärel next
moodul. See funktsioon hoiab andmete salvestamiseks sisemist kindla suurusega ämbrit. Iga uus asukoht lisatakse ämbrisse seni, kuni ämber on täis. Seejärel saadetakse kogumisse kogunenud asukohaandmed massiivina järgmisele moodulile.
Toetatakse kahte tüüpi akumulaatorikaupa. Rühma tüüp mõjutab seda, mida ämbri sisule tehakse pärast andmete edastamist järgmisse etappi:
Akna ämber (type = 'tumbling'
): pärast andmete edastamist tühjendatakse kogu ämber ja alustatakse värskelt (vähendatud ämbri suurus tagasi 0-ni)
Akna tüübi käitamine (type = 'running'
): pärast andmete edastamist visatakse ära ainult vanim andmeelement rühmas (vähendab rühma suurust 1 võrra)
Siin on akumooduli põhiline rakendamine:
function accumulate(config, next) { var bucket = []; return function (data) { bucket.unshift(data); if(bucket.length >= config.size) { var newSize = (config.type === 'tumbling' ? 0 : bucket.length - 1); next(bucket.slice(0)); bucket.length = newSize; } }; }
Muidugi on koordinaatgeomeetrias palju keerukaid tehnikaid 2D-andmete klasterdamiseks. Siin on üks lihtne viis asukohaandmete rühmitamiseks:
Siin on selle klastrialgoritmi (kasutades Lo-Dash
):
graafiline disain vs digitaalne disain
var _ = require('lodash'); function createClusters(location_data, radius) { var clusters = []; var min_points = 5; // Minimum cluster size function neighborOf(this_location, all_locations) { return _.filter(all_locations, function(neighbor) { var distance = distance(this_point.location, neighbor.location); // maximum allowed distance between neighbors is 500 meters. return distance && (500 > distance); } } _.each(location_data, function (loc_point) { // Find neighbors of loc_point var neighbors = neighborOf(loc_point, location_data, radius); _.each(clusters, function (cluster, index) { // Check whether some of the neighbors belong to cluster. if(_.intersection(cluster, neighbors).length){ // Expand neighbors neighbors = _.union(cluster, neighbors); // Remove existing cluster. We will add updated cluster later. clusters[index] = void 0; } }); if(neighbors.length >= min_points){ // Add new cluster. clusters.unshift(neighbors); } }); return _.filter(clusters, function(cluster){ return cluster !== void 0; }); }
Ülaltoodud kood eeldab a distance()
olemasolu funktsioon, mis arvutab kahe geograafilise asukoha vahelise kauguse (meetrites). See aktsepteerib kahte asukohapunkti kujul [longitude, latitude]
ja tagastab nende vahelise kauguse. Siin on sellise funktsiooni näidisrakendus:
function distance(point1, point2) { var EARTH_RADIUS = 6371000; var lng1 = point1[0] * Math.PI / 180; var lat1 = point1[1] * Math.PI / 180; var lng2 = point2[0] * Math.PI / 180; var lat2 = point2[1] * Math.PI / 180; var dLat = lat2 - lat1; var dLon = lng2 - lng1; var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); var arc = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var distance = EARTH_RADIUS * arc; return distance; }
Kui meie klastrialgoritm on määratletud ja juurutatud (varem näidatud funktsioonis createClusters()
), saame seda kasutada oma klastrimooduli aluseks:
function clusterize(config, next) { return function(data) { var clusters = createClusters(data, config.radius); next(clusters); }; }
Kõik vajalikud komponendi funktsioonid on nüüd määratletud, nii et oleme valmis oma kodu / töökoha reegleid kodeerima.
Siin on näiteks kodukoha reegli võimalik rakendamine:
var CLUSTER_RADIUS = 150; // use cluster radius of 150 meters var BUCKET_SIZE = 500; // collect 500 location points var BUCKET_TYPE = 'tumbling'; // use a tumbling bucket in our accumulator var home_cluster = clusterize({radius: CLUSTER_RADIUS}, function(clusters) { // Save clusters in db }); var home_accumulator = accumulate({size: BUCKET_SIZE, type: BUCKET_TYPE}, home_cluster); var home_rule = timeFilter({start: '2AM', end: '3AM'}, home_accumulator);
Nüüd, kui nutitelefonilt saadakse asukohateave (veebipesa, TCP, HTTP kaudu), edastame need andmed home_rule
funktsioon, mis omakorda tuvastab kasutaja kodu klastrid.
Seejärel eeldatakse, et kasutaja kodu asukoht on kodukoha klastri keskpunkt.
Märkus. Kuigi see ei pruugi olla täiesti täpne, on see meie lihtsa näite jaoks piisav, eriti kuna selle rakenduse eesmärk on igal juhul lihtsalt teada kasutaja kodu ümbritsevat piirkonda, mitte kasutaja täpse asukoha teadmist.
Siin on lihtne näitefunktsioon, mis arvutab klastri punktide hulga keskpunkti kõigi klastrihulgas olevate punktide laius- ja pikkuskraadide keskmise järgi:
function getCentre(cluster_data) { var len = cluster_data.length; var sum = _.reduce(cluster_data, function(memo, cluster_point){ memo[0] += cluster_point[0]; memo[1] += cluster_point[1]; return memo; }, [0, 0]); return [sum[0] / len, sum[1] / len]; }
Sarnast lähenemisviisi võiks kasutada ka töökoha väljaarvutamiseks, ainus erinevus on see, et see kasutaks ajafiltrit vahemikus 14–15 (erinevalt kell 2–3).
Meie kütuserakendus on seega võimeline automaatselt tuvastada kasutaja töö- ja kodukohad ilma kasutaja sekkumist nõudmata. See on kontekstiteadlik arvutamine parimal moel!
Kontekstiteadlikkuse loomiseks on nüüd tehtud raske töö, kuid vajame siiski veel ühte reeglit, et teha kindlaks, milliseid tanklakütuse hindu jälgida (st millised tanklad asuvad kasutaja kodu või töökoha jaoks piisavalt lähedal, et see oleks asjakohane). See reegel vajab juurdepääsu kõigile kütuserakenduse toetatud piirkondade kõigile tanklakohtadele. Reegel on järgmine:
Seda saab hõlpsasti rakendada, kasutades varem filtrina näidatud vahemaa funktsiooni, mis rakendub kõigile rakendusele teadaolevatele tanklatele.
Kui kütuserakendus on saanud kasutajale eelistatud (st läheduses asuvate) tanklate loendi, saab ta nendes jaamades hõlpsasti parimaid kütusehindu jälgida. Samuti saab ta teavitada kasutajat, kui ühel neist tanklatest on erihinnad või pakkumised, eriti kui kasutaja tuvastatakse nende tanklate läheduses.
Selles keerulises sündmuste töötlemise õpetuses oleme kontekstiteadliku arvutamise pinda vaevu napilt kraapinud.
Lisasime oma lihtsas näites muidu lihtsale kütusehinna aruandlusrakendusele asukoha konteksti ja muutsime selle targemaks. Rakendus käitub nüüd igas seadmes erinevalt ja tuvastab aja jooksul asukohamustrid, et oma kasutajatele pakutava teabe väärtust automaatselt parandada.
Meie kontekstiteadliku rakenduse täpsuse ja kasulikkuse suurendamiseks saab kindlasti lisada palju rohkem loogika- ja anduriandmeid. A nutikas mobiiliarendaja võiks näiteks kasutada sotsiaalvõrgustike andmeid, ilmaandmeid, POS-terminali tehinguandmeid ja nii edasi, et lisada meie rakendusele veelgi rohkem kontekstiteadlikkust ja muuta see elujõulisemaks ja turustatavamaks .
Kontekstiteadliku arvutamise korral on võimalused lõputud. Rakendusepoodides ilmub jätkuvalt üha rohkem nutirakendusi, mis kasutavad seda võimsat tehnoloogiat, et muuta meie elu lihtsamaks.