;

Jízdní řády on-line: Seznam začal strojově zpracovávat data CHAPS a zajistí další rozvoj aplikace Pubtran

29. 4. 2015
Doba čtení: 3 minuty

Sdílet

Autor: seznam.cz
Seznam.cz využil veřejně dostupná data firmy CHAPS pro vlastní aplikaci jízdních řádů a nově provozuje i Pubtran. Na Mapy.cz najdete jízdní řády pro celou ČR.

Několik let soudních tahanic mezi společností Seznam.cz a CHAPS o otevřenost dat o veřejné dopravě dnes pravděpodobně skončilo. Seznam.cz chytá CHAPS za slovo a využije veřejně publikovaná data, která CHAPS dává k dispozici na svých stránkách v excelových tabulkách. Výsledkem je to, že nyní můžete v aplikaci Mapy.cz plánovat trasu veřejnou dopravou kdekoliv v ČR. Seznam.cz také spravuje aplikaci Pubtran a chystá se jí dál rozvíjet.

Nové řešení kombinuje pěší dopravu s veřejnou dopravou, a proto lze plánovat cestu z konkrétního místa v mapě do jiného a není přitom nutné plánovat ji jen ze zastávky na zastávku. Strojově zpracovaná data z excelovských tabulek CHAPSu se kombinují vlastními naměřenými údaji o zastávkách hromadné dopravy a nad výsledným souborem se pak používá vlastní plánovač dopravy na Mapy.cz.

„Po skoro čtyřech letech tahanic o zpřístupnění dat jízdních řádů v otevřené podobě jsme se vydali cestou, kterou je strojové zpracovávání CHAPSem zveřejňovaných excelovských tabulek s jízdními řády. Přestože se jedná o poměrně náročnou úlohu, chytáme tímto krokem CHAPS za slovo v jejich vlastní argumentaci, že data použitelná pro další zpracování již zveřejňují právě ve formátu Excel. Zároveň se nic nemění v našem úsilí data zpřístupnit ve skutečně otevřeném a strukturovaném formátu, což ostatně předjímá loni schválená vyhláška ministerstva dopravy, která v otázce jízdních řádů vejde od 1. 9. 2015 v účinnost,“ komentoval současnou situaci Michal Feix, prokurista Seznam.cz.

Akvizice aplikace Pubtran

V rámci akvizice Seznam.cz několik posledních týdnů pracoval na tom, aby aplikace Pubtran mohla běžet na jejích datech. „Aplikace Pubtran využívala data společnosti CHAPS. Původně jsem ji mohl nabízet zdarma – to ale nadále CHAPS neumožňoval, proto jsem hledal cestu, jak aplikaci Pubtran pro lidi ponechat bezplatnou. Spojení se společností Seznam.cz mi toto umožní,“ komentuje prodej své aplikace Pubtran společnosti Seznam.cz František Hejl, její autor.

„Jízdní řády potřebují i svoji mobilní aplikaci. Potřeba vyhledávání dopravního spojení je nejčastější úlohou právě v terénu. Akvizice aplikace Pubtran pro nás byla logickou cestou,“ komentoval důvody spojení Michal Feix.

Během dnešního dne nabídne aplikace Pubtran svým uživatelům možnost automatické aktualizace. S ní se změní nejen design aplikace, ale i některé její funkce, protože začne fungovat na jiných datech a s tím se bude i mírně jinak chovat.

Čtěte také:
→ Seznam.cz Email nově pro iOS
Zatímco specializované aplikace pro Android i Windows Phone jsou již nějakou dobu na světě, nyní přichází i verze určená pro mobilní zařízení Apple.
→ Mapy.cz nabídnou celý svět i nápady na výlety
Novinky je možné již vyzkoušet ve veřejné beta verzi. Technologickým upgradem prošla i Panorama, letecké 3D snímky a vyhledávání.

Cyber25

Zaujal vás tento článek?
Zaregistrujte se k odběru našeho e-mailového newsletteru. Každý týden tak pohodlně získáte přehled o důležitých událostech v IT branži.

G+

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
OSZAR »