Commit 81e416db authored by Richard's avatar Richard

worked on report

parent d4f30553
No preview for this file type
...@@ -4,36 +4,52 @@ ...@@ -4,36 +4,52 @@
\usepackage{amsfonts} \usepackage{amsfonts}
\usepackage{amssymb} \usepackage{amssymb}
\usepackage{listings} \usepackage{listings}
\usepackage{graphicx}
\author{Richard Torenvliet - 6138861} \author{Richard Torenvliet - 6138861}
\title{Flood Simulation Browser} \title{Flood Simulation Browser}
\begin{document} \begin{document}
\maketitle \maketitle
\section{Introduction} \section{Introduction}
This project concerns the flood simulation browser. The concept of this browser is to illustrate/visualize a flood in a particular area. With this technology people can see the flow that the water will take. When a dike breaks it is important to know where the water will flow. That way the information about which locations in the area will be under water first. By using this information the government can be informed. People with the authority to take measures against these floods are provided with the right information. This system already exists but this project involves taking advantage of this system and make it easier available and accessible. This project concerns the Flood Simulation Browser. The concept of this browser is to illustrate/visualize a flood in a particular area. With this technology people can see the flow that the water will take. When a dike breaks it is important to know where the water will flow and at which time-step. Information about which locations in the area will be under water first can result in a successful evacuation plan. This system already exists but this project involves taking advantage of this system and make it easier available and accessible. Which makes it more likely that someone with the right authority can take decisions about placing dikes and creating a successful early warning system.
The implementation of this application will be on a multi-touch device. In particular iPads and Android tablets. but can be launched on other tablets as well. Users can use this application in an intuitive way and get more intelligence about the complex situation at hand. They have the ability to choose from several simulations that where already made for a specific area. The implementation of this application will be on a multi-touch device. In particular iPad and Android tablets. Users can use this application in an intuitive way and get more intelligence about the complex situation at hand. They have the ability to choose from several simulations that where already made for a specific area and also creating new ones.
This document covers design choices/options in order to reach that goal. The first step is to get an idea of the existing simulation system of which this application will take use of. This includes a clarification of what is already made and what is not. For instance, what type of data is already made at the system side. The next step will be finding what out the requirements of the tablet implementation, like what features does it have to contain in order to be to maintain the intuitiveness. Just by showing the data would not be sufficient. The function of this App is to extend the simulation system with a use-ability factor. This document covers design choices/options in order to reach that goal. The first step is to get an idea of the existing simulation system of which this application will take use of. This includes a clarification of which part of the system this Browser will take. The next step will be finding what out the requirements of the tablet implementation, like what features does it have to contain in order to be to maintain the intuitiveness. Just by showing the data would not be sufficient. The function of this App is to extend the simulation system with a use-ability factor.
A side assignment of this project is testing the scalability of the REST server. By testing how much requests the server can handle at ones it helps the urban flood project to estimate how much people can use the application at ones. The original multi touch application on the multi touch table was only only one client. It's important to know that an early warning system stays online under the pressure of al lot of clients.
\section{Flood Simulation System} \section{Flood Simulation System}
The system that already exists runs in the Cloud. That means it does all the calculation for the client and it is not important to know at physical computer it runs. The system can calculate other simulation by providing it parameters about a certain area. When a simulation is run it will be stored on in the system. With other calls the system return a set of simulation that are present in the current database. Now the important thing to note is that the simulation consists of images that have to be displayed on a map, let's say Google Maps. The flood simulation system preforms a complex simulation with the height map of the area. The height map consists of detailed information about the height of an area. With this data the flow of the water can be calculated and turned in to images. The system that already exists runs in the Cloud. That means it does all the calculation for the client and it is not important to know at which physical computer it runs. The system can calculate other simulation by providing parameters about a certain area. When a simulation is run it will be stored in the system. With other calls the system returns a set of simulation that are present in the current database. Now the important thing to note is that the simulation consists of images that have to be displayed on a map, let's say Google Maps. The flood simulation system preforms a complex simulation with the height map of the area. The height map consists of detailed information about the height of an area. With this data the flow of the water can be calculated and turned in to images.
\section{Flood API} \subsection{Flood API}
The API is a REST api that returns a JSON formatted string. It's a client server system where requests are done by the client and the appropriate data is transferred back to the client. The API is a REST api that returns a JSON formatted string. It's a client server system where requests are done by the client and the appropriate data is transferred back to the client. With this data, information about a certain simulation can be displayed.
\subsection{Scalability}
A side assignment of the project is to test the scalability of the server. The server address is sangkil.science.uva.nl. To test this server it is needed to exclude any other parameter of the client. Such as maximum download speed, maximum throughput, latency of the network that the testing is finding place. The idea is not to test this at a home pc, but test it in a server that is hooked up in the same network as sangkil.science.uva.nl. If this is the case the exclusion of restricted variables at client side is possible.
For stress testing the server there is a tool available called siege\footnote{http://www.joedog.org/siege-home/}. With this tool it is possible to launch request to a url with n-nodes with k fire-ing connections per second. Siege registers the following data:
\begin{itemize}
\item Transmissions - total
\item Elapsed Time - seconds
\item Data Transfer - (MB/s)
\item Response Time -
\item Transfer Rate
\item Throughput
\item Concurrent
\item OKAY,
\item Failed
\end{itemize}
With this data new insight can be provided. By increasing the number of simultaneous connections, values could start to change. The expectations are that the response time might be longer. With more clients to serve, it could take longer if there are more clients active. If processor power is limited, maximum available memory is reached or the implementation of the server for handling requests could effect in the response time.
\section{Flood Simulation App} \section{Flood Simulation App}
\subsection{Platform considerations} \subsection{Platform considerations}
As stated in the introduction the app is meant for tablets, but not specific for iOS or Android. How can we maintain this demand on the application. This means that the application is not native programmed but consists of one code-base. There is a technology called PhoneGap that uses HTML5 CSS and Javascript to build the app. In essence the developer build a mobile website and PhoneGap can wrap this in an application. The native web engine is that used to render the mobile website. PhoneGap can result in a huge speed up in development which is a huge advantage. Also by the skills gained by webdevelopment can be re-used. Therefore there is no need to learn a new programming environment used for native apps in Objective C with Xcode for iOS and Java with Eclipse for Android. The advantage that is the learning curve is not high, but it can still feel like a mobile website in stead of a native application. Luckily frameworks exists where native-like elements are created for you. As stated in the introduction the app is meant for tablets, but not specific for iOS or Android. How can we maintain this demand on the application? Is one of the research question. This means that the application is not native programmed but consists of one code-base and runs on more devices. There is a technology called PhoneGap that uses HTML5 CSS and Javascript to build the app. In essence the developer builds a mobile website and PhoneGap can wrap this in an application. The native web engine is that used to render the mobile website. PhoneGap can result in a huge speed-up in development which is a huge advantage because of the skills gained by webdevelopment can be re-used. Therefore there is no need to learn a new programming environment used for native apps in Objective C with Xcode for iOS and Java with Eclipse for Android. The advantage that is easy to learn and re-using earlier experiences in web development can be re-used, the disadvantage can be that it feels like a mobile website in stead of a native application. Luckily frameworks exists where native-like elements are created for you.
Another option can be a Titanium Mobile, the Appcelerator. Titanium Mobile can build mobile applications that are in fact native applications. By programming in Javascript and call functions to create native elements. The framework builds native code, in contrary to PhoneGap what is really a mobile webpage in an application. The development for this platform is fast and an application for both iOS and Android are quickly from the ground. But there is also a disadvantage by using Titanium. The applications are big, around 11MB no matter what you did. Not only that, the native elements look good on iOS but no so much on Android. So true cross platform is never reached. This can be a Titanium Mobile, the Appcelerator. Titanium Mobile can build mobile applications that are in fact native applications. By programming in Javascript and call functions to create native elements. The framework builds native code, in contrary to previously discussed PhoneGap. The development for this platform is fast and an application for both iOS and Android are quickly of the ground. But there is also a disadvantage by using Titanium. The applications are big, around 11MB no matter what. Not only is do they take a lot of space on the storage device, but also has trouble of memory leaks(link). Developing and testing on iOS provides expected behaviour and a lot is possible, for Android the native elements are mostly not the elements you thought the look like. To reach cross-platform apps you need to constantly check if your building an element for iOS or for Android. It might be stated that the functionalities of the platforms are randomly picked from the API. The idea of Titanium Mobile is great, it works fine but will delay developing time when you truly want to reach crossplatform.
\subsubsection*{Javascipt frameworks} \subsubsection*{Javascipt frameworks}
As already explained, PhoneGap only provides the possibility to make an app out of a website. This website can be build in any way the developer likes using webtechnologies supported on the native device. There are frameworks that can speed up the development to make an intuitive application. Two frameworks that can be considered jQuery Mobile and Sencha Touch. As already explained, PhoneGap only provides the possibility to create an app out of a website. This website can be build in any way the developer likes using webtechnologies supported on the native device. There are frameworks that can speed up the development to make an intuitive application. Two frameworks that can be considered jQuery Mobile and Sencha Touch.
\begin{description} \begin{description}
\item [jQuery Mobile] \item [jQuery Mobile]
This Javascriptwork is build out of one Javascript file and one css file that the developer includes. By giving certain HTML elements a data attribute, which is a HTML5 element, the framework uses this to create views. A page is made by declaring a div adding data-role="page". Such a page can be given a footer like div data-role="footer". This Javascript framework is build out of one Javascript file and one css file that the developer includes. By giving certain HTML elements a data attribute, which is a HTML5 element, the framework uses this to create views. A page is made by declaring a div adding data-role="page". Such a page can be given a footer like div data-role="footer".
Switching frame one page to the other can be as simple as giving a html anchor a href to an id of a page. The next example will result in two pages, the both pages have a button. Both buttons link to the other page (foo, bar), so tapping on one button will change the page to the other page.
Switching frame one page to the other can be as simple as giving a html anchor an href to an id of a page.
\begin{figure} \begin{figure}
\begin{lstlisting} \begin{lstlisting}
<div data-role="page" id='bar'> <div data-role="page" id='bar'>
...@@ -47,10 +63,10 @@ Switching frame one page to the other can be as simple as giving a html anchor a ...@@ -47,10 +63,10 @@ Switching frame one page to the other can be as simple as giving a html anchor a
\caption{jQuery Mobile, pages example} \caption{jQuery Mobile, pages example}
\end{figure} \end{figure}
The downside of jQuery mobile is that in order to create an application where views look a like, you have to repeat yourself. Every page gets the same footer. It can be a burden when changes have to be made in the footer. The conclusion is that jQuery mobile is really easy and the developer does indeed use html, css to create views. But is is not easy to build a modular application. Creating to pages are quickly made, the downside of jQuery mobile is that in order to create an application where views look a like, you have to repeat yourself. You have to create pages with other id's but with the same The conclusion is that jQuery mobile is really easy and the developer does indeed use html, css to create views. But it is not easy to build a modular application. It is always possible to create such a modular application yourself, but when creating an application which is not such a framework the developer will run in to creating a framework in stead of the intended application.
\item [Sencha Touch] \item [Sencha Touch 2]
Sencha touch is a framework focused on the Model View Controller design pattern. It encourages the developer to use this pattern. The way of developing really differs from jQuery mobile. There where jQuery mobile sets you free to do whatever you like, sencha touch constraints the developer. The difference can be easily explained with an example. Sencha touch 2 is a framework focused on the Model View Controller design pattern. It encourages the developer to use this pattern. The way of developing really differs from jQuery mobile. There where jQuery mobile sets you free to do whatever you like, sencha touch constraints the developer using components that are available in sencha touch. The difference can be easily explained with an example.
\begin{figure}[h!] \begin{figure}[h!]
\begin{lstlisting} \begin{lstlisting}
...@@ -71,12 +87,27 @@ Ext.application({ ...@@ -71,12 +87,27 @@ Ext.application({
} }
}); });
\end{lstlisting} \end{lstlisting}
\label{fig:sencha}
\caption{Sencha Touch application example} \caption{Sencha Touch application example}
This example creates an application with the %name 'foo'. The html can be placed inside the items array. This example creates an application with the name 'foo'. The html can be placed inside the items array.
\end{figure} \end{figure}
\end{description} \end{description}
In the items array in the example there but other items like lists, tabview or a map. And items are configured with the config attribute. Any component present in the sencha touch framework. The advantage is an application that is structured out of the box with a design pattern that is current standard(MVC). With sencha touch 2 there is no need for PhoneGap, unlike jQuery Mobile. Sencha Touch 2 provides the possibility to run the code on your simulator or native device by the command line tool. Testing for Android an iOS became much more simplistic resulting in less developing time. Running PhoneGap for Android needs Eclipse to build, on iOS you need to build in the Xcode. When testing on both devices you'll need to be able to test in both environments which is highly less desirable than building from command line. A disadvantage of sencha touch could be, as seen in figure \ref{fig:sencha}, the syntax of sencha touch is not so easy at first. So the learing curve could be very .
\subsection{App Design} \subsection{App Design}
The application will be used on tablets so a lot of space can be used. Working with tablets the screen gets larger than mobile phones. Which can result in a bigger travel distance of the user's hands. The GUI design has to be build with the considerations of the interaction capability of the users. For instance, unlike with mobile phones, according to Clark(2012) a leading designer in creating multi-touch applications, people intend to hold a tablet on the top halve of the tablet when holding with both hands, figure \ref{fig:perimeter}. The focus of the user is going from top to down. The top elements of the application will draw the first attention of the user. That's why Clark(2012) advises to place the important controls on the top half of the screen. The components that are important have to be placed in the left or right top of the screen. By taking Clark's advise the Flood Simulation Browser can be inspired.
First of all the flood simulations are within different cities. This can typically be a list of cities, also a list is scrollable and can be seen as an infinite array of cities around the world. Every city has it's own array of simulations to show. So it makes sense to also show these in a second list. When a city is selected, the user has no use of the capability to select other cities and it's simulations. This is because it makes sense to only have one Map object in the view where one location (latitude, longitude) can be shown at a time. The map object is the component that is the important part of the browser. Inspired by Clark(2012) it can be stated that a hierarchy in importance of different view components can result in a different place on the screen. By placing the Map component always in the view and also as the biggest component the idea of placing objects in a hierarchy of importance in the view is considered.
The list component where cities and simulations are placed is the left side of the view, it could also be the right side but it would not matter. Two hands are more or less symmetrical so placing the list object left or right would not be a problem. It does matter concerning controls, but which controls shown in the top bar is not clear at this moment. Controls that would be needed is the ability to change the image placed on the map. A simulation consists of multiple images on different time steps. By giving the user control of which image is seen at which time step is a crucial feature in the browser.
The flood simulation browser already build for the multi touch table has the ability to submit new simulations to be simulated in the cloud. The spot of the simulation can be arbitrary on the map, by simply touching a place on the map and alter some parameters the cloud service can create a new simulation to be seen. Although this feature can be an seen as an extension of my project with time left, this feature can be build in. That's why it can be considered in the App's design. The controls of these parameters need to be somewhere in view, by placing this in the neighbourhood of the place where the user placed touched the map could be intuitive. But not if happens when your only are browsing through the map, the user has to know that it is in the mode of with picking a place where to create a new simulation. The specification about these controls are discussed in the end report.
\begin{figure}[h!]
\center
\includegraphics[scale=0.3]{touch.png}
\caption{Portrait touch perimeter(Clark, 2012)}
\label{fig:perimeter}
\end{figure}
%http://www.netmagazine.com/features/designing-touch John Clark 2012 on February 01, 2012
\end{document} \end{document}
\ No newline at end of file
...@@ -5,9 +5,9 @@ Ext.Loader.setPath({ ...@@ -5,9 +5,9 @@ Ext.Loader.setPath({
//</debug> //</debug>
Ext.application({ Ext.application({
controllers: ["Main"], controllers: ["Lsm", "Main"],
models: ["SimulationModel", "SimulationDetails"], models: ["SimulationModel", "SimulationDetails"],
stores: ['SimulationStore', 'SimulationDetailsStore', 'SimulationsSummary'], stores: ['SimulationStore', 'SimulationDetailsStore', 'SimulationsSummary', 'LsmStore'],
name: 'app', name: 'app',
...@@ -15,7 +15,8 @@ Ext.application({ ...@@ -15,7 +15,8 @@ Ext.application({
'Ext.MessageBox', 'app.CustomProxy' 'Ext.MessageBox', 'app.CustomProxy'
], ],
views: ['Main', "Home", "Simulation", "List", 'Map', 'StepsOverlay', 'OptionsPanel'], views: ['Main', "Home", "Simulation", "List", 'Map', 'StepsOverlay', 'OptionsPanel',
'SimulationList', 'LsmSimulationList'],
icon: { icon: {
57: 'resources/icons/Icon.png', 57: 'resources/icons/Icon.png',
......
...@@ -16,6 +16,11 @@ Ext.define('app.controller.Main', { ...@@ -16,6 +16,11 @@ Ext.define('app.controller.Main', {
playBackw: '#play-backw', playBackw: '#play-backw',
pauseBackw: '#pause-backw', pauseBackw: '#pause-backw',
mapView: 'SimulationMap', mapView: 'SimulationMap',
simulationList: {
selector: 'summary',
xtype: 'SimulationList',
autoCreate: true,
},
/*use this format if this object is not yet created*/ /*use this format if this object is not yet created*/
overlay: { overlay: {
selector: '#overlay', selector: '#overlay',
...@@ -24,11 +29,27 @@ Ext.define('app.controller.Main', { ...@@ -24,11 +29,27 @@ Ext.define('app.controller.Main', {
}, },
/*use this format if this object is not yet created*/ /*use this format if this object is not yet created*/
simulationOptions: { simulationOptions: {
selector: 'simulation_options', selector: '#simulation-options',
xtype: 'SimulationOptions', xtype: 'SimulationOptions',
autoCreate: true, autoCreate: true,
}, },
simOptionsButton: {
selector: '#simulationOptions',
autoCreate: true,
},
optionsList: {
selector:'#optionsList',
autoCreate: true,
},
lsmSimulation: {
selector: 'lsmsimulation-list',
xtype: 'LsmSimulationList',
autoCreate: true,
},
/*the list simulations available in the area selected*/ /*the list simulations available in the area selected*/
simulation: 'simulationpanel' simulation: 'simulationpanel'
}, },
...@@ -36,11 +57,13 @@ Ext.define('app.controller.Main', { ...@@ -36,11 +57,13 @@ Ext.define('app.controller.Main', {
/*all event listeners*/ /*all event listeners*/
control: { control: {
'listpanel #cities': { 'listpanel #cities': {
itemtap: 'showOverlay', itemtap: 'showList',
show: 'initiateCities'
}, },
'listpanel #summary': { 'listpanel #summary': {
itemtap: 'simulation', itemtap: 'simulate',
scroll: 'scroll'
}, },
'#mapa': { '#mapa': {
...@@ -60,7 +83,7 @@ Ext.define('app.controller.Main', { ...@@ -60,7 +83,7 @@ Ext.define('app.controller.Main', {
}, },
'#simulationOptions': { '#simulationOptions': {
tap: 'openSimulations' tap: 'openSimulationsOptions'
}, },
'#pause': { '#pause': {
...@@ -78,15 +101,37 @@ Ext.define('app.controller.Main', { ...@@ -78,15 +101,37 @@ Ext.define('app.controller.Main', {
'#play-backw': { '#play-backw': {
tap: 'playBackwImages' tap: 'playBackwImages'
}, },
'#optionsList': {
itemtap: 'changeSimulationType',
},
'listpanel #lsmsimulation-list':{
itemtap: 'simulate',
show: 'allo',
} }
}
},
scroll: function(){
console.log('scroll');
}, },
allo: function(){
console.log("allo");
},
initiateCities: function(){
this.getSimOptionsButton().show();
},
/* first function to call */ /* first function to call */
setMap: function(extmap, map){ setMap: function(extmap, map){
this.test_id = null; this.test_id = null;
this.globalMap = map; this.globalMap = map;
this.getMapView().setGlobalMap(extmap, map); this.getMapView().setGlobalMap(extmap, map);
this.selectedIndex = []; this.selectedIndex = [];
/*default simulation type*/
this.SimulType = 'Flood';
}, },
stopBackwImages: function(button){ stopBackwImages: function(button){
...@@ -117,6 +162,7 @@ Ext.define('app.controller.Main', { ...@@ -117,6 +162,7 @@ Ext.define('app.controller.Main', {
this.getPause().show(); this.getPause().show();
/*create reference of the mapview, setInterval looses this. scope */ /*create reference of the mapview, setInterval looses this. scope */
var instance = this.getMapView(); var instance = this.getMapView();
/*store this.interval, for later removal*/
this.interval = setInterval(function() {instance.nextImage()}, 500); this.interval = setInterval(function() {instance.nextImage()}, 500);
}, },
...@@ -142,9 +188,11 @@ Ext.define('app.controller.Main', { ...@@ -142,9 +188,11 @@ Ext.define('app.controller.Main', {
}, },
closeoverlay: function() { closeoverlay: function() {
/*show play button and hide pause button*/ /*show play buttons and hide pause buttons*/
this.getPlay().show(); this.getPlay().show();
this.getPause().hide(); this.getPause().hide();
this.getPlayBackw().show()
this.getPauseBackw().hide();
/*clear interval, even if there wasn't any*/ /*clear interval, even if there wasn't any*/
clearInterval(this.interval); clearInterval(this.interval);
...@@ -155,15 +203,15 @@ Ext.define('app.controller.Main', { ...@@ -155,15 +203,15 @@ Ext.define('app.controller.Main', {
/* Initialize simulation, responds when tapped on a list item /* Initialize simulation, responds when tapped on a list item
* of the simulation panel * of the simulation panel
*/ */
simulation: function(list, index, element, record) { simulate: function(list, index, element, record) {
console.log('simulate call');
var me = this;
/*first, remove all images, even if there werent any*/ /*first, remove all images, even if there werent any*/
this.getMapView().removeImages(); this.getMapView().removeImages();
//console.log(this.getOverlay()); //console.log(this.getOverlay());
/*create reference, cb looses scope of this.*/ /*create reference, cb looses scope of this.*/
var map = this.getMapView(), var map = this.getMapView(),
/*The simulationDetailStore has the details of the */ /*The simulationDetailStore has the details of the get test_id*/
/*get test_id*/
test_id = record.get('test_id'), test_id = record.get('test_id'),
/*bounds variable used later on*/ /*bounds variable used later on*/
bounds; bounds;
...@@ -173,14 +221,17 @@ Ext.define('app.controller.Main', { ...@@ -173,14 +221,17 @@ Ext.define('app.controller.Main', {
/* callback, executed when ajax call returns /* callback, executed when ajax call returns
* this function calls the map object to create overlays * this function calls the map object to create overlays
* for retrieved timessteps * for retrieved timesteps
*/ */
var cb = function(result){ var cb = function(result){
if (result['timesteps'].length > 0) var timesteps = result['timesteps'] || result['images'];
map.createOverlayImage(bounds, test_id, result['timesteps']); console.log(timesteps);
if (timesteps.length > 0)
map.createOverlayImage(bounds, test_id, timesteps, me.SimulType);
} }
var store = Ext.getStore('SimulationDetailsStore'); var store = Ext.getStore('SimulationDetailsStore');
/*Get visbounds, for later use in overlay map*/ /*Get visbounds, for later use in overlay map*/
store.each(function(r) { store.each(function(r) {
bounds = r.get('visbounds'); bounds = r.get('visbounds');
...@@ -189,7 +240,15 @@ Ext.define('app.controller.Main', { ...@@ -189,7 +240,15 @@ Ext.define('app.controller.Main', {
/* The information of the simulation, has data of the time /* The information of the simulation, has data of the time
* steps available, crucial data for the displaying the images. * steps available, crucial data for the displaying the images.
*/ */
this.requestInfo(test_id, cb); //console.log(this.getSimulationOptions().getSelectedCls())
var url = '';
if (this.SimulType == 'Flood')
{
url = 'http://sangkil.science.uva.nl:8003/drfsm/'+ test_id +'/info.json';
console.log(this.SimulType);
}
else url = 'http://sangkil.science.uva.nl:8003/lsm/'+ test_id +'/visualization/paru/info.json';
this.requestInfo(test_id, cb, url);
/*show overlay*/ /*show overlay*/
this.getOverlay().showBy(this.getMapView(), 'br-br'); this.getOverlay().showBy(this.getMapView(), 'br-br');
...@@ -200,7 +259,10 @@ Ext.define('app.controller.Main', { ...@@ -200,7 +259,10 @@ Ext.define('app.controller.Main', {
* Set map center to the center of the area that was tapped * Set map center to the center of the area that was tapped
* Create a polygon dikes if there is information about them * Create a polygon dikes if there is information about them
*/ */
showOverlay: function(list, index, element, record){ showList: function(list, index, element, record){
this.getSimOptionsButton().hide();
//console.log(this.getSimulationOptions());
//this.getSimulationOptions().hide();
/*Remove images, even if there werent any*/ /*Remove images, even if there werent any*/
this.getMapView().removeImages(); this.getMapView().removeImages();
/*store center*/ /*store center*/
...@@ -217,7 +279,9 @@ Ext.define('app.controller.Main', { ...@@ -217,7 +279,9 @@ Ext.define('app.controller.Main', {
/* Instance of the store of all images data*/ /* Instance of the store of all images data*/
var store = Ext.getStore('SimulationsSummary'); var store = Ext.getStore('SimulationsSummary');
var store_lsm = Ext.getStore('LsmStore');
store_lsm.clearFilter();
store_lsm.filter("area_id", area_id);
/* clear filter, if the flters are not cleared, they will /* clear filter, if the flters are not cleared, they will
* be filtered on top of each other, resuting in an unwanted * be filtered on top of each other, resuting in an unwanted
* state. * state.
...@@ -226,26 +290,17 @@ Ext.define('app.controller.Main', { ...@@ -226,26 +290,17 @@ Ext.define('app.controller.Main', {
store.filter("area_id", area_id); store.filter("area_id", area_id);
/*push the side panel, in future create the view somewhere else*/ /*push the side panel, in future create the view somewhere else*/
this.getSidepanel().push({ console.log(this.SimulType);
showAnimation: { if (this.SimulType == 'Flood')
type: 'slide', {
direction: 'left', this.setThumb(center);
duration: 200 this.getSidepanel().push(this.getSimulationList());
}, }
id: 'summary', else if(this.SimulType == 'Lsm')
xtype: 'list', this.getSidepanel().push(this.getLsmSimulation());
store: 'SimulationsSummary',
itemTpl: '<div><img class="map_thumb" id="{test_id}_map"' +
'src=""/> ' +
'<img class="flood_thumb" id="{test_id}_flood"' +
'style:"width: 100px;" src=""/>' +
'<div style:"clear:both">' +
'<div id="{test_id}_control" class="control"></div>' +
'</div><b>{test_id}</b>: {submitted}</div></div>',
});
/*set thumb images*/ /*set thumb images*/
this.setThumb(center); //this.setThumb(center);
/*the store with details of the of the simulation*/ /*the store with details of the of the simulation*/
var store = Ext.getStore('SimulationDetailsStore'); var store = Ext.getStore('SimulationDetailsStore');
...@@ -268,6 +323,9 @@ Ext.define('app.controller.Main', { ...@@ -268,6 +323,9 @@ Ext.define('app.controller.Main', {
if (dikes.length != 0) if (dikes.length != 0)
this.getMapView().createOverlayPolygon(dikes); this.getMapView().createOverlayPolygon(dikes);
this.getMapView().createMarker(center); this.getMapView().createMarker(center);
this.getSimulationOptions().show();
this.getSimulationOptions().hide();
} }
this.getMapView().setCenterMap(center); this.getMapView().setCenterMap(center);
...@@ -275,28 +333,30 @@ Ext.define('app.controller.Main', { ...@@ -275,28 +333,30 @@ Ext.define('app.controller.Main', {
}, },
/* Set the thumb, the image is the last image of the simulation */ /* Set the thumb, the image is the last image of the simulation */
setThumb: function(center){ setThumb: function(){
if (typeof this.test_id == undefined) if (typeof this.test_id == undefined)
return; return;
var me = this; var me = this;
var summary_store = Ext.getStore('SimulationsSummary'); var summary_store = Ext.getStore('SimulationsSummary');
// var mapImage ='http://maps.googleapis.com/maps/api/staticmap?center='+ center[0] +','+ center[1] + '&zoom=13&size=300x180&maptype=roadmap&sensor=false'; // var mapImage ='http://maps.googleapis.com/maps/api/staticmap?center='+ center[0] +','+ center[1] + '&zoom=13&size=300x180&maptype=roadmap&sensor=false';
summary_store.each(function(record){ summary_store.each(function(record){
var test_id = record.get('test_id'); var test_id = record.get('test_id');
var setImages = function(result){ var setImages = function(result){
// document.getElementById(test_id + "_map").src = mapImage;//me.getMapView().getFloodImage(test_id, result['timesteps'][result['timesteps'].length - 1]); // document.getElementById(test_id + "_map").src = mapImage;//me.getMapView().getFloodImage(test_id, result['timesteps'][result['timesteps'].length - 1]);
var image = me.getMapView().getFloodImage(test_id, result['timesteps'][result['timesteps'].length - 1]) || 'recourses/images/noimage.png'; var image = me.getMapView().getFloodImage(test_id, result['timesteps'][result['timesteps'].length - 1]) || 'resources/images/noimage.png';
document.getElementById(test_id + "_flood").src = image; document.getElementById(test_id + "_flood").src = image;
} }
me.requestInfo(record.get('test_id'), setImages); me.requestInfo(record.get('test_id'), setImages);
}); });
}, },
requestInfo: function(test_id, callback){ requestInfo: function(test_id, callback, url){
var url = url || 'http://sangkil.science.uva.nl:8003/drfsm/'+ test_id +'/info.json';
var request = Ext.Ajax.request({ var request = Ext.Ajax.request({
method: 'GET', method: 'GET',
url: 'http://sangkil.science.uva.nl:8003/drfsm/'+ test_id +'/info.json', url: url,//'http://sangkil.science.uva.nl:8003/drfsm/'+ test_id +'/info.json',
success: function(response, opts){ success: function(response, opts){
var result = Ext.decode(response.responseText); var result = Ext.decode(response.responseText);
...@@ -309,7 +369,23 @@ Ext.define('app.controller.Main', { ...@@ -309,7 +369,23 @@ Ext.define('app.controller.Main', {
}); });
}, },
openSimulations: function(element){ openSimulationsOptions: function(element){
this.getSimulationOptions().show(); this.getSimulationOptions().showBy(element);
},
closeSimulationsOptions: function(element){
this.getSimulationOptions().hide();
},
changeSimulationType: function(list, index, element, record){
if (record.get('type') == 'Lsm' && this.SimulType != 'Lsm')
this.SimulType = 'Lsm'
else if (record.get('type') == 'Flood' && this.SimulType != 'Flood')
this.SimulType = 'Flood'
this.getSimulationOptions().hide();
},
pushSimulationList: function(){
//this.getSidepanel().push(this.getLsmSimulation());
} }
}); });
...@@ -17,9 +17,19 @@ Ext.define("app.view.List", ...@@ -17,9 +17,19 @@ Ext.define("app.view.List",
navigationBar: navigationBar:
{ {
title: 'simulations',
ui: 'darker_blue', ui: 'darker_blue',
//html: '<h1>Simulations Panel</h1>', items : [{
id: 'simulationOptions',
xtype: 'button',
text: 'simulations',
left: '100%',
top: 7,
ui: ['square','blue'],
}]
}, },
items: [ items: [
{ {
id: 'cities', id: 'cities',
......
Ext.define('app.view.LsmSimulationList', {
extend: 'Ext.List',
xtype: 'LsmSimulationList',
id: 'lsmsimulation-list',
config: {
store: 'LsmStore',
itemTpl: '{submitted}',
}
});
\ No newline at end of file
...@@ -9,6 +9,8 @@ Ext.define("app.view.Main", { ...@@ -9,6 +9,8 @@ Ext.define("app.view.Main", {
items: [ items: [
{ {
xtype: 'listpanel', xtype: 'listpanel',
width: '20%',
style: 'border-right: 1px solid #373737',
flex: 1, flex: 1,
}, },
{ {
......
...@@ -54,19 +54,30 @@ Ext.define('app.view.Map', { ...@@ -54,19 +54,30 @@ Ext.define('app.view.Map', {
var pos = new google.maps.LatLng(pos[0], pos[1]); var pos = new google.maps.LatLng(pos[0], pos[1]);
new google.maps.Marker({ new google.maps.Marker({
position: pos, position: pos,
icon: 'Google_Maps_Marker.png', icon: 'resources/images/Google_Maps_Marker.png',
map: this.globalMap, map: this.globalMap,
title: 'you' title: 'you'
}); });
}, },
// 'http://sangkil.science.uva.nl:8003/drfsm/199419691/visualization/level/map/600.png' // 'http://sangkil.science.uva.nl:8003/drfsm/199419691/visualization/level/map/600.png'
// 'http://sangkil.science.uva.nl:8003/drfsm/207/visualization/level/map/300.png' ; // 'http://sangkil.science.uva.nl:8003/drfsm/207/visualization/level/map/300.png' ;
/*create overlays with area_id, bounds and timesteps /*create overlays with area_id, bounds and timesteps
* Bounds: array(4) * Bounds: array(4)
*/ */
createOverlayImage: function(bounds, area_id, timesteps) { createOverlayImage: function(bounds, area_id, timesteps, simulationType) {
console.log(timesteps);
var url = '';
if (simulationType == 'Flood')
{
url = 'http://sangkil.science.uva.nl:8003/drfsm/' + area_id + '/visualization/level/map/';
}
else if (simulationType == 'Lsm')
{
url = 'http://sangkil.science.uva.nl:8003/lsm/' + area_id + '/visualization/paru/map/';
}
else return false;
console.log(url);
this.imageIndex = 0; this.imageIndex = 0;
this.imageBounds = new google.maps.LatLngBounds( this.imageBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(bounds[2],bounds[3]), new google.maps.LatLng(bounds[2],bounds[3]),
...@@ -75,30 +86,41 @@ Ext.define('app.view.Map', { ...@@ -75,30 +86,41 @@ Ext.define('app.view.Map', {
if (this.overlayImages.length > 1) if (this.overlayImages.length > 1)
this.removeImages(); this.removeImages();
//var image = 'http://sangkil.science.uva.nl:8003/lsm/' + area_id +'/visualization/level/map/400.png'; //var image = 'http://sangkil.science.uva.nl:8003/lsm/' + area_id +'/visualization/level/map/400.png';
for (i in timesteps) for (i in timesteps)
{ {
var image = 'http://sangkil.science.uva.nl:8003/drfsm/' + area_id + '/visualization/level/map/' + timesteps[i] + '.png'; //var image = 'http://sangkil.science.uva.nl:8003/drfsm/' + area_id + '/visualization/level/map/' + timesteps[i] + '.png';
this.overlayImages.push(new google.maps.GroundOverlay(image, this.imageBounds)); var image = new Image();
image.src = url + timesteps[i] + '.png';
console.log(image.src);
this.overlayImages.push(new google.maps.GroundOverlay(image.src, this.imageBounds));
} }
this.overlayImages[0].setMap(this.globalMap); this.overlayImages[0].setMap(this.globalMap);
this.imageIndex = this.overlayImages.length;
}, },
/* set next Image*/ /* set next Image*/
nextImage: function() nextImage: function()
{ {
var lastImagesIndex = this.imageIndex; if (this.overlayImages.length <= 1)
this.imageIndex += this.imageIndex <= this.overlayImages.length - 2 ? 1 : 0; return;
if (this.imageIndex != lastImagesIndex) var lastIndex = (this.overlayImages.length + this.imageIndex) % this.overlayImages.length;
{ this.imageIndex = (this.overlayImages.length + this.imageIndex + 1) % this.overlayImages.length;
//this.imageIndex = (this.overlayImages.length + this.imageIndex + 1) % (this.overlayImages.length);
console.log(this.imageIndex);
//this.overlayImages[this.imageIndex - 1].setMap(null);
this.overlayImages[this.imageIndex].setMap(this.globalMap); this.overlayImages[this.imageIndex].setMap(this.globalMap);
this.overlayImages[this.imageIndex - 1].setMap(null); this.overlayImages[lastIndex].setMap(null);
} //this.imageIndex = (this.imageIndex + 1) % (this.overlayImages.length);
console.log(this.imageIndex);
}, },
/*set prev image*/ /*set prev image*/
prevImage: function() prevImage: function()
{ {
if (this.overlayImages.length <= 1)
return;
this.overlayImages[this.imageIndex].setMap(null); this.overlayImages[this.imageIndex].setMap(null);
this.imageIndex -= this.imageIndex > 0 ? 1 : 0; this.imageIndex -= this.imageIndex > 0 ? 1 : 0;
......
...@@ -2,20 +2,24 @@ Ext.define('app.view.OptionsPanel', { ...@@ -2,20 +2,24 @@ Ext.define('app.view.OptionsPanel', {
extend: 'Ext.Panel', extend: 'Ext.Panel',
xtype: 'SimulationOptions', xtype: 'SimulationOptions',
id: 'simulation_options', id: 'simulation_options',
requires: ['Ext.dataview.List'],
config: { config: {
layout: 'hbox',
right: 40, right: 40,
width: 200, width: 200,
height: 100, height: 100,
//scroll: true, hideOnMaskTap: true,
modal: true, modal: true,
items: [{ items: [
{
xtype: 'list', xtype: 'list',
fullscreen: true, id: 'optionsList',
width: '100%',
itemTpl: 'Simulation {type}', itemTpl: 'Simulation {type}',
data: [ data: [
{type: "Flood Simulation"}, {type: "Flood"},
{type: "Lsm"} {type: "Lsm"}
], ],
}] }],
} }
}); });
\ No newline at end of file
...@@ -10,14 +10,6 @@ Ext.define('app.view.Simulation', { ...@@ -10,14 +10,6 @@ Ext.define('app.view.Simulation', {
xtype: 'toolbar', xtype: 'toolbar',
ui: 'darker_blue', ui: 'darker_blue',
title: 'Flood Simulation Browser', title: 'Flood Simulation Browser',
items : [{
id: 'simulationOptions',
xtype: 'button',
text: 'simulations',
right: 0,
top: 7,
ui: ['square','blue'],
}]
}, },
{ {
xtype: 'SimulationMap', xtype: 'SimulationMap',
...@@ -25,47 +17,3 @@ Ext.define('app.view.Simulation', { ...@@ -25,47 +17,3 @@ Ext.define('app.view.Simulation', {
}], }],
} }
}); });
\ No newline at end of file
// {
// xtype: 'panel',
// id: 'overlay',
// hidden: true,
// width: 300,
// height: 80,
// scroll: false,
// items: [
// {
// xtype: 'button',
// id: 'closebutton',
// iconCls: 'delete',
// iconMask: true,
// width: 45,
// top: -30,
// left: -20,
// },
// {
// layout: 'vbox',
// top: 15,
// align: 'center',
// items : [
// {
// xtype: "button",
// id: 'backwards',
// width: 45,
// iconCls: 'arrow_left',
// floating: 'right',
// iconMask: true,
// left: 90,
// align: 'center',
// },
// {
// xtype: "button",
// id: 'forward',
// width: 45,
// floating: 'left',
// iconCls: 'arrow_right',
// align: 'center',
// left: 155,
// iconMask: true,
// }]
// },
\ No newline at end of file
Ext.define('app.view.SimulationList', {
extend: 'Ext.List',
xtype: 'SimulationList',
id: 'summary',
config: {
scrollable: {
momentum: false
},
fullscreen: true,
store: 'SimulationsSummary',
itemTpl: '<div><img class="map_thumb" id="{test_id}_map"' +
'src=""/> ' +
'<img class="flood_thumb" id="{test_id}_flood"' +
'style:"width: 100px;" src=""/>' +
'<div style:"clear:both">'+
'<div id="{test_id}_control" class="control"></div>' +
'</div><h3><b>submitted:</b></h3> <bold>{submitted}</bold></div></div>'
},
listeners : {
scroll: function() {
console.log('scroll');
}
}
});
\ No newline at end of file
...@@ -7,6 +7,7 @@ Ext.define('app.view.StepsOverlay', { ...@@ -7,6 +7,7 @@ Ext.define('app.view.StepsOverlay', {
config: { config: {
style: "background: none", style: "background: none",
id: 'overlay', id: 'overlay',
html: 'Controls',
showAnimation: { showAnimation: {
type: 'slideIn', type: 'slideIn',
direction:'left', direction:'left',
...@@ -17,10 +18,9 @@ Ext.define('app.view.StepsOverlay', { ...@@ -17,10 +18,9 @@ Ext.define('app.view.StepsOverlay', {
direction:'right', direction:'right',
}, },
//autoDestroy: true,
hidden: true, hidden: true,
width: 200, width: 220,
height: 100, height: 130,
scroll: false, scroll: false,
items: [ items: [
{ {
...@@ -38,7 +38,7 @@ Ext.define('app.view.StepsOverlay', { ...@@ -38,7 +38,7 @@ Ext.define('app.view.StepsOverlay', {
}, },
{ {
top: 10, top: 10,
left: 30, left: 35,
align: 'center', align: 'center',
items : [ items : [
{ {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -64,19 +64,13 @@ ...@@ -64,19 +64,13 @@
} }
} }
.x-container .x-scroll-view{
border-right: solid #ababab;
}
.flood_thumb { .flood_thumb {
position: relative; position: relative;
z-index: 100; z-index: 100;
left: 10px; left: 0px;
top: 10px; top: 10px;
width: 300px; width: 80%;
height: 180px; /* height: 180px;*/
border: solid #ababab;
} }
.map_thumb { .map_thumb {
......
...@@ -64,19 +64,13 @@ ...@@ -64,19 +64,13 @@
} }
} }
.x-container .x-scroll-view{
border-right: solid #ababab;
}
.flood_thumb { .flood_thumb {
position: relative; position: relative;
z-index: 100; z-index: 100;
left: 10px; left: 0px;
top: 10px; top: 10px;
width: 300px; width: 80%;
height: 180px; /* height: 180px;*/
border: solid #a0a0a0;
} }
.map_thumb { .map_thumb {
......
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
* This is the name of your application, which is displayed on the device when the app is installed. On IOS, this should match * This is the name of your application, which is displayed on the device when the app is installed. On IOS, this should match
* the name of your application in the Apple Provisioning Portal. * the name of your application in the Apple Provisioning Portal.
*/ */
"applicationName":"My Application", "applicationName":"Flood Simulation",
/** /**
* @cfg {String} applicationId * @cfg {String} applicationId
* This is the name namespace for your application. On IOS, this should match the name of your application in the Apple Provisioning Portal. * This is the name namespace for your application. On IOS, this should match the name of your application in the Apple Provisioning Portal.
*/ */
"applicationId":"com.codefabriek.tipspottmp", "applicationId":"com.uva.floodsimulation",
/** /**
* @cfg {String} versionString * @cfg {String} versionString
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -25,4 +25,10 @@ ...@@ -25,4 +25,10 @@
//@include sencha-msgbox; //@include sencha-msgbox;
x-list-item {
// needs latest Compass, add '@import "compass"' to your scss
@include filter-gradient(#00000000, #a6000000, horizontal); // IE6-9
@include background-image(linear-gradient(left, rgba(0,0,0,0) 0%,rgba(132,2,2,0.77) 76%,rgba(5,0,0,1) 99%,rgba(0,0,0,0.65) 100%));
copied to clipboard copy
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment