Introduction
In a web application, Pagination, or Page Navigation, is a technique often used to display a large set of data. For a large hundred or thousand or even million of records, it would cause large performance problem to return all of that data in a single page. Pagination is used to present data to user one page at a time, typically 25 to 100 records per page. Moreover, keyword search, advance search option and column sorting are features often needed together with Pagination.
This article will focus on an implementation of Pagination with Spring Framework that will provide full features of pagination, search option and column sorting.
Features of Pagination Framework
Pagination Framework includes the following features:
- Fine-grained options to cater varies pagination requirement.
- Customizable search options
- Column sorting by one or more db columns
- Customizable look and feel
- Compatible with Spring Framework version 1.x, 2.x, 3.x, 4.x
- Support JSF 1 and JSF 2
- Support JSP 2.0 and JSP 2.1 and JSP 2.2
- Support JDK 1.5, 1.6, 1.7
- Support Object Relational Mapping (ORM) Data Access including Hibernate, JPA, JDBC
- Search engine friendly URL - to make pagination links shorter and SEO friendly.
- AJAX pagination - make pagination links update only part of our web page, without reloading the whole page. (JSP only)
- Remember search result - recall previous search results after leaving for other pages.
- Override ORM Data Access by writing an implementation of Data Access of your choice (e.g. JDO, iBATIS SQL Maps, etc.)
- Architecturally correct (and beautiful) implementation with Business Object, Controller, Service, Data Access Object (DAO) and View layers well defined.
Technologies
In this example, the following technologies are needed:
- Pagination Framework for Spring
- Spring Framework 3.2.3.RELEASE
- Hibernate as JPA provider
- JSP 2.2 and JSTL 1.2 (JEE 6)
- Lucene 3.6.1
- JDK 1.7
Approach
This article will use a top-down approach, starting with user interface (View), working the way down to Controller, then to Service and Repository (Model / DAO) layer.
Suppose our Project Manager has gathered user requirements for a Basketball (NBA) Statistic System and an application prototype produced:
Top of the page will have a few search options for users to search through statistics. On the middle left there are 2 action buttons for users to delete or add statistics. On the middle right side total number of basketball players and the corresponding page number will be shown. The basketball players are displayed to user one page at a time, 10 players per page. Columns can be sorted by Season, Player Name, etc. And finally, pagination component is rendered for user to change page. The left most part is for go to the first page; follow by link to go to previous page; follow by numeric items to go to a specific page; follow by next page and last page link.
In order to implement pagination, we will need to create the following files:
| Object |
Extends |
Description |
| BoSeasonStat |
BoPaginationResultRow |
Business Object for storing search options |
| BoSeasonStatSearchParam |
BoPaginationParam |
Business Object for storing one row of data |
| SeasonStatController |
PaginationControllerAbstract |
Controller to interpret user input and set data into model |
| SeasonStatService |
PaginationServiceAbstract |
Service layer for business logic. Raw data from JPA is mapped to Business Object |
| SeasonStatDao |
PaginationDaoDbEntityManagerAbstract |
Data Access Object (DAO) for Database query |
| seasonstat.jsp |
http://pagination/pagination-spring3.tld |
User Interface presentation |
Maven Setup
Artifact "pagination" is the our pagination implementation.
Artifact "pagination-taglibs" is the our pagination tag library.
If you have a single WAR project, add the following dependency to your pom.xml:
<dependency>
<groupId>com.github.paginationspring</groupId>
<artifactId>pagination</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.github.paginationspring</groupId>
<artifactId>pagination-taglibs</artifactId>
<version>1.0.3</version>
</dependency>
Notice that pagination and pagination-taglibs do not have maven dependency on spring framework (scope=optional). Therefore, we will need to add spring framework dependencies to pom.xml as well.
If you have a EAR project with WAR module inside, add "pagination" dependency to yourEAR/pom.xml and "pagination-taglibs" dependency to yourWAR/pom.xml.
Non-Maven Setup
You can simply download the two jar files and put it into your project.
If you have a WAR project, put both pagination-1.0.3.jar and pagination-taglibs-1.0.3.jar into your yourWAR/WEB-INF/lib directory.
If you have a EAR project, put pagination-1.0.3.jar into your-EAR/lib directory and put pagination-taglibs-1.0.3.jar into your-EAR/yourWAR/WEB-INF/lib directory.
User Interface (JSP)
To create a JSP page for Basketball Statistics System, we will use Pagination Framework for Spring. Pagination Framework contains a predefined JSP Tag Library for generating our pagination page. We will also need spring tag library and spring form tag library, together with standard JSTL core library.
<%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@taglib prefix="pg" uri="http://pagination/pagination-spring3.tld" %>
Next, we will need html form tag for search option submission. We will use spring form tag to create our form. With this form tag, we will expose a business object pparam (short for page parameters) using attribute modelAttribute. The action attribute is set to the page url, which is defined in another business object paginationResult. Business objects (BO) pparam and paginationResult formed the 2 (and only 2) POJO objects that we will use to present our pagination data.
<c:url value="${paginationResult.pageLink}" var="pageLink"/>
<form:form id="pgform" method="post" modelAttribute="pparam" action="${pageLink}">
.
.
.
</form:form>
Next, use Pagination Framework tag library to create our pagination search and data content. Pagination tag library has tag-file name "pagination" (<pg:pagination>) to help generate the pagination content. pg:pagination has 6 attributes: pparam, paginationResult, searchContent, controlButton, columnsContent and contentAfterLastRow. For pparam and paginationResult, I will explain them in more details in Business Object section below. Now let’s first look at how we use <pg:pagination> tag:
<pg:pagination pparam="${pparam}" paginationResult="${paginationResult}">
<jsp:attribute name="searchContent">

Filter:

<form:select path="season" cssStyle="width:110px;">
<form:option value="" label="--- Season ---"/>
<form:option value="2009" label="2009"/>
<form:option value="2008" label="2008"/>
<form:option value="2007" label="2007"/>
<form:option value="2006" label="2006"/>
<form:option value="2005" label="2005"/>
<form:option value="2004" label="2004"/>
<form:option value="2003" label="2003"/>
<form:option value="2002" label="2002"/>
<form:option value="2001" label="2001"/>
<form:option value="2000" label="2000"/>
</form:select>

<form:select path="teamName">
<form:option value="" label="--- Team ---"/>
<form:options items="${teamList}" />
</form:select>

Player Name:
<form:input path="playerName" cssStyle="width:150px;"/>

<form:button id="searchButton" name="buttonAction" value="searchButton" class="button">Search</form:button>

<form:button id="clearButton" name="buttonAction" value="clearButton" class="button">Clear</form:button>

</jsp:attribute>
<jsp:attribute name="controlButton">

<form:button id="deleteButton" name="buttonAction" value="deleteButton" class="button">Delete</form:button>

<form:button id="addButton" name="buttonAction" value="addButton" class="button">Add</form:button>

</jsp:attribute>
<jsp:attribute name="columnsContent">

<c:out value="${bo.season}"/>

<c:out value="${bo.playerName}"/>

<span style="white-space:nowrap;" title="<c:out value="${bo.teamName}"/>">
<c:out value="${bo.teamAlias}"/>

<c:out value="${bo.position}"/>

<c:out value="${bo.gamePlay}"/>

<fmt:formatNumber type="number" value="${bo.minutePerGame}" pattern="###">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.fgPercent}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.tpPercent}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.ftPercent}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.reboundPerGame}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.assistPerGame}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.turnoverPerGame}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.stealPerGame}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.blockPerGame}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.pfPerGame}" pattern="##0.0">
</fmt:formatNumber>

<fmt:formatNumber type="number" value="${bo.pointPerGame}" pattern="##0.0">
</fmt:formatNumber>

</jsp:attribute>
</pg:pagination>
- searchContent, controlButton, columnsContent and contentAfterLastRow are all jsp fragments.
- searchContent contains the search options; form objects (input, radiobutton, button, etc.) use spring form tag library with attribute "path" set to variable in pparam (remember we set modelAttribute="pparam" in our form). For example, <form:input path="season"> will reference pparam.season variable.
- controlButton contains 2 buttons for delete and add action.
- columnsContent defines how we present the search result, i.e. each row of data (each player), to our users. Here an object instance named "bo" is binded to this jsp fragment and can be used to load data from our BoSeasonStat object (see below).
- contentAfterLastRow should defines an area below the last row of data. We didn't need it in this example.
Business Object (BO)
pparam
Page Parameter (pparam) is a business-object representing the search options. We declare this object in
com.github.paginationspring.example.lucene.bo.BoSeasonStatSearchParam. This object extends
com.github.paginationspring.bo.BoPaginationParam (POJO) and added 3 fields from our search options:
public class BoSeasonStatSearchParam extends BoPaginationParam {
private String season;
private String playerName;
private String teamName;
pparam will keep value of search option in this pojo and use it in our pagination framework.
paginationResult
Pagination Result is a business-object representing results of our search. It contains one page of data (as seen by user on his current page), and it also contains some settings like record-per-page, default sorting order, etc. Each row of data (in our case, each player) is represented by declaring object
com.github.paginationspring.example.lucene.bo.BoSeasonStat.
Controller
Controller will define settings of our pagination page, map requests URLs into a handler method and pass business logic to service layer. First we define our controller with @Controller annotation and extend a controller base PaginationControllerAbstract<BoSeasonStatSearchParam> as shown here:
@Controller
public class SeasonStatController extends PaginationControllerAbstract {
In our constructor, we will define some settings for our pagination results.
public SeasonStatController() {
setOptionDisplayCheckbox(true);
setOptionDisplaySerialNo(true);
setOptionWidth(950);
setDefaultRecordPerPage(10);
setDefaultSortName("Season");
setDefaultSortAscDesc("d");
setPageLink("/org/pagination/example/lucene/bball-season-stat.do"); // url
}
| setOptionDisplayCheckbox |
whether or not the left side checkbox should be displayed |
| setOptionDisplaySerialNo |
whether or not the left side serial no. should be displayed |
| setOptionWidth |
the width of our search results, in pixels |
| setDefaultRecordPerPage |
default record per page |
| setDefaultSortName |
default sorting column |
| setDefaultSortAscDesc |
default sorting order, value "a" is ascending and "d" is decending. |
| setPageLink |
url of your pagination page |
| setRewriteUrl |
to give you nicer, SEO (Search Engine Optimization) friendly, urls. For example, by setting setRewriteUrl to true, URL mailclient/inbox.do?sortAscDesc=a&sortName=From becomes mailclient/sort/From/a/inbox.do |
Next, we will need to map request URLs into a handler method. We do this by using the @RequestMapping, @ModelAttribute and @RequestParam annotations:
@RequestMapping(value="/bball-season-stat.do", method = {RequestMethod.GET, RequestMethod.POST})
public String defineJsp(@ModelAttribute(PPARAM) BoSeasonStatSearchParam pparam
, @RequestParam(value=BUTTON_ACTION, required=false) String buttonAction, Model model) throws Exception {
Map map = assignModel(pparam, buttonAction);
model.addAllAttributes(map);
model.addAttribute("teamList", seasonStatService.retrieveTeamAliass());
if ( "deleteButton".equalsIgnoreCase(buttonAction) && !ArrayUtils.isEmpty(pparam.getSelectedIds()) ) {
// deleteButton button is pressed
for ( String pk : pparam.getSelectedIds() ) {
log.info("selected id="+pk);
}
}
return "/org/pagination/example/lucene/view/seasonstat";
}
In @RequestMapping, you will notice URL1, URL2, URL 3 and URL 4 variables. There constant variables predefined some url patterns to be used when we set option setRewriteUrl to true. If setRewriteUrl is set to false, simply use @RequestMapping(value="/bball-season-stat.do").
In our method declaration, the return type String is logical view name and in our case, the jsp file name. Method argument pparam is annotated with @ModelAttribute to bind request parameters to bean properties from our form object (remember we have <form:form modelAttribute="pparam">). Method argument buttonAction is annotated with @RequestParam to access button request parameter searchButton, clearButton, deleteButton and addButton. Finally, method argument model is used to expose paginationResult object to web view.
Inside this method, we will call a parent method assignModel from our Pagination Framework, set the returned objects into our model arguments and result the jsp url. The assignModel method will call a service bean, which we will be injecting into our controller. The service bean implements our business logic in our pagination, which we will explain in the next section.
Map map = assignModel(pparam, buttonAction);
model.addAllAttributes(map);
.
.
.
return "/org/pagination/example/lucene/view/seasonstat";
At last, inject our service bean with @Autowired annotation and call a parent method setPaginationService:
@Autowired
public void setPaginationService(SeasonStatService seasonStatService) {
super.setPaginationService(seasonStatService);
this.seasonStatService=seasonStatService;
}
Service
Service bean serves two purposes: 1) map database raw data into our business object and 2) define column properties for result data.
First, we define our service bean with @Service annotation and extend a service base PaginationServiceAbstract as shown here:
@Service
public class SeasonStatService extends PaginationServiceAbstract {
Type inference of
represent our page parameter, business object and data entity object respectively. Document is Lucene document.
To map database raw data into our business object, override assignDataToBo method:
@Override
protected BoSeasonStat assignDataToBo(Document document) throws Exception {
BoSeasonStat bo = new BoSeasonStat();
bo.setNbaSeasonId(Integer.parseInt(document.get("nbaSeasonId")));
bo.setPlayerName (document.get("playerName"));
bo.setHeight (document.get("height"));
bo.setWeight (document.get("weight"));
bo.setTeamName (document.get("teamName"));
bo.setTeamAlias (document.get("teamAlias"));
bo.setPosition (document.get("position"));
bo.setSeason (document.get("season"));
bo.setGamePlay (Integer.parseInt(document.get("gamePlay")));
if ( bo.getGamePlay() != 0 ) {
bo.setMinutePerGame (Double.parseDouble(document.get("minutePerGame")));
bo.setPointPerGame (Double.parseDouble(document.get("pointPerGame")));
bo.setReboundPerGame (Double.parseDouble(document.get("reboundPerGame")));
bo.setAssistPerGame (Double.parseDouble(document.get("assistPerGame")));
bo.setStealPerGame (Double.parseDouble(document.get("stealPerGame")));
bo.setBlockPerGame (Double.parseDouble(document.get("blockPerGame")));
bo.setTurnoverPerGame (Double.parseDouble(document.get("turnoverPerGame")));
bo.setPfPerGame (Double.parseDouble(document.get("pfPerGame")));
}
bo.setFgPercent (Double.parseDouble(document.get("fgPercent")));
bo.setTpPercent (Double.parseDouble(document.get("tpPercent")));
bo.setFtPercent (Double.parseDouble(document.get("ftPercent")));
return bo;
}
To define column properties, override assignColumnsDefinition method:
@Override
public void assignColumnsDefinition(List columns)
throws Exception {
BoPaginationColumn col = null;
col = new BoPaginationColumn();
col.setColumnName("Season");
col.setOrderColumns("a.season, c.teamAlias, b.lastName, b.firstName");
col.setOrderDirections("desc, asc, asc, asc");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Player Name");
col.setOrderColumns("b.lastName, b.firstName, a.season");
col.setOrderDirections("asc, asc, asc");
col.setWidth(150);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Team");
col.setOrderColumns("c.teamAlias, a.season, b.lastName, b.firstName");
col.setOrderDirections("asc, asc, asc, asc");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Pos.");
col.setOrderColumns("b.position, a.season, c.teamAlias, b.lastName, b.firstName");
col.setOrderDirections("asc, asc, asc, asc, asc");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("G");
col.setOrderColumns("a.gamePlay, a.season, c.teamAlias, b.lastName, b.firstName");
col.setOrderDirections("asc, asc, asc, asc, asc");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Min");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("FG%");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("3PT%");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("FT%");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Reb");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Ast");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("TO");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Stl");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("Blk");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("PF");
col.setWidth(30);
columns.add(col);
col = new BoPaginationColumn();
col.setColumnName("PPG");
col.setOrderColumns("(a.point/a.gamePlay), a.season, c.teamAlias, b.lastName, b.firstName");
col.setOrderDirections("desc, asc, asc, asc, asc");
col.setWidth(30);
columns.add(col);
}
We create a new BoPaginationColumn bean for each column. BoPaginationColumn has 4 variables: columnName, orderColumns, orderDirections and width. The columnName is the name of column to be displayed to user. The orderColumns is a query string to be added to our JPA query "order by" clause. The orderDirections has value "asc" or "desc" for ascending or descending shorting of the column. For sorting across multiple fields, use comma to separate between required fields (as shown in "From" column above). The width variable defines the column width in pixels.
At last, inject our DAO bean with @Autowired annotation and call a parent method setPaginationDao:
@Autowired
public void setPaginationDao(SeasonStatLuceneDao seasonStatLuceneDao) {
super.setPaginationDao(seasonStatLuceneDao);
this.seasonStatLuceneDao = seasonStatLuceneDao;
}
Data Access Layer (DAO)
DAO bean load the raw data from database using JPA entity manager. First, we define our DAO with @Repository annotation and extends PaginationDaoDbEntityManagerAbstract from Pagination Framework:
@Repository
public class SeasonStatDao extends PaginationDaoLuceneAbstract {
BoSeasonStatSearchParam is the incoming page parameters.
First, we will setup query to load data from lucene:
@Override
protected File loadLuceneIndexDirectory() {
URL url = SeasonStatLuceneDao.class.getResource("/luceneindex");
return new File(url.getFile());
}
@Override
protected QueryParser loadQueryParser() {
Analyzer analyzer = new KeywordAnalyzer();
QueryParser parser = new QueryParser(Version.LUCENE_36, "season", analyzer);
return parser;
}
@Override
protected String composeQuery(BoSeasonStatSearchParam pparam) {
StringBuilder sb = new StringBuilder();
if ( !StringUtils.isEmpty(pparam.getSeason()) ) {
sb.append("season:\""+pparam.getSeason()+"\"");
} else {
sb.append("season:[2000 TO 2009]");
}
if ( !StringUtils.isEmpty(pparam.getPlayerName()) ) {
String token;
StringTokenizer tokens = new StringTokenizer(pparam.getPlayerName(), " ");
while (tokens.hasMoreTokens()) {
token = tokens.nextToken().trim();
token = token.toLowerCase();
sb.append(" AND playerName:");
sb.append(token+"*");
}
}
if ( !StringUtils.isEmpty(pparam.getTeamName()) ) {
sb.append(" AND teamName:\""+pparam.getTeamName()+"\"");
}
return sb.toString();
}
loadLuceneIndexDirectory method return the file location of our lucene index.
loadQueryParser method return the QueryParser object, which also set the Analyzer.
composeQuery method return the Lucene query used to find our results. Please reference http://lucene.apache.org/core/2_9_4/queryparsersyntax.html for Lucene query syntax.
Spring Framework Setup
To setup spring framework, we setup spring MVC in web.xml as we normally would:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/org/pagination/example/lucene/*</url-pattern>
</servlet-mapping>
In applicationContext.xml file, define the following for our annotated components:
<context:annotation-config />
<context:component-scan base-package="com.github.paginationspring.example.lucene" />
<mvc:annotation-driven />
In dispatcher-servlet.xml, define the following for view resolver:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
Additional Features
Additional features can be enabled in pagination framework are:
- Search engine friendly URL - to make pagination links shorter and SEO friendly.
- AJAX pagination - make pagination links update only part of our web page, without reloading the whole page.
- Remember search result - recall previous search results after leaving for other pages.
- Override ORM Data Access by writing an implementation of Data Access of your choice (e.g. JDO, iBATIS SQL Maps, etc.)
See my other blog posts on http://paginationspring.blogspot.com for details.
Running our example
Click "Download Zip" button on this page https://github.com/paginationspring/pagination-example-lucene.
The zip file included full source code in this document. Make sure you have Maven and JDK installed. Open command prompt and type run.bat (for window OS) or ./run.sh (for linux OS). Choose your application server and wait around 30 seconds for the server to startup. After server started, go to url http://localhost:8080/pagination-example-lucene
Help improve this document
You can help improve this document by "fork" this repository https://github.com/paginationspring/pagination/tree/master/doc.
After making changes to this document, you can submit a pull request and I will change this document accordingly.
To report bugs, please use https://github.com/paginationspring/pagination/issues.


Welcome to the Data Commons Import Wizard! We've created this tool (still in early beta) to simplify the process of importing and mapping data from CSV files. Please review all of the information below before proceeding to import. This version is intended to help our closest partners import clean CSV files with very specific requirements.
We welcome any feedback at<EMAIL_ADDRESS>while we iterate on improvements.
CSV Format Requirements
-
Each CSV file is expected to have columns corresponding to the Values (numeric) about a Variable, Place and Date. For example, in the table shown below, there are separate columns for Variable (Variable), Place (Country), Date (Year) and Value (Value) and each row of the CSV corresponds to one observation of the Variable about a Place at the specified Date.
Year Country Variable Value Extra Column Another Extra Column 2017 UK Life Expectancy 81.25609756 1 random text 2017 UK Population 65844142 1 random text 2017 KR Life Expectancy 82.62682928 2 random text ... ... ... ... ... ... - If all observations in the CSV are about the same Place and/or the same Date and/or the same Variable, then those do not need to be specified as columns. They can be specified as constants. After mapping columns, if any of Date, Variable (statvars), or Place are not mapped, then there will be a section for users to enter constants for the missing things.
-
It is possible to specify Date OR Variable as column headers (but not both at the same time).
-
Example 1: In the table shown below, all values in each Date column (2017, 2018) are assumed to be observations that correspond to the Date specified in the column header.
Country Variable 2017 2018 Extra Column Another Extra Column UK Life Expectancy 81.2560975609756 81.2560975609756 1 random text KR Population 51361911 51606633 1 random text UK Population 65844142 66273576 2 random text ... ... ... ... ... ... -
Example 2: In the table shown below, all values in each Variable column (Life Expectancy, Population) are assumed to be observations that correspond to the Variable specified in the column header.
Year Country Life Expectancy Population Extra Column Another Extra Column 2017 UK 81.25609756 65844142 1 random text 2017 KR 82.62682928 51361911 2 random text 2017 US 78.5390243902439 325147121 3 random text ... ... ... ... ... ...
-
Example 1: In the table shown below, all values in each Date column (2017, 2018) are assumed to be observations that correspond to the Date specified in the column header.
Terminology Glossary
- Place - Only Country and State (USA and India) level data supported for now. See Supported Date and Place Formats for more details.
- Name of Variable - Ex: Population, Life expectancy, Median Income. Also referred to as 'Statistical Variables' and 'StatVars' in Data Commons.
- Date - See Supported Date and Place Formats section for more details.
- Observation Value - The numerical values within a column.
- Not Mapped - Columns to be excluded from the mapping .
- Constant - If all observations in the CSV are about the same Place and/or the same Date and/or the same Variable, then those do not need to be specified as columns.
Supported Date and Place Formats
-
Date formats supported: ISO-8601 format only
- Example: YYYY-MM-DD like 2022-08-23
- Example: YYYYMMDD like 20220823
- Example: YYYY-MM like 2022-08 (but not YYYYMM)
- Example: YYYY-MM-DD like 2022-08-23
-
Place types and formats supported:
- Type: Country
- Formats (case-insensitive):
- Type: State (only USA and India supported at this time)
- Type: Country
Import Steps
- Review CSV Format Requirements, Terminology Glossary, and Supported Date and Place Formats.
- Review your CSV file and make any necessary edits to conform to these requirements.
- Select Choose File and import your .csv file (see below upload button).
- Confirm Mappings in the Import Wizard, one column at a time.
- Identify Place, Variable, Date, and Observation Values Using the Wizard
- Each column title in the uploaded CSV file can specify:
- a specific [Place, Variable, Date, or Observation Value] with corresponding observation values underneath it - option 1 radio button
- that the rows underneath it are a [Place, Variable, Date, or Observation Value] - option 2 radio button
- If none of these apply, you can choose to Skip this Column - option 3 radio button
- After completing the full mapping, press next to generate and download a zip file containing the TMCF and JSON files.
- Share the files with the Data Commons team.
- Use Google Drive to share a link to the URL
- Share URL in an email to<EMAIL_ADDRESS>- Datacommons will validate the import and reach out to you if necessary.


I do stuff, and learn stuff, and i want to learn programming and web development so i can be more usefuler at my joerb
I am trying to figure out web development, but i'm pretty good at music and stuff, too
Just email me, i'm not in the mood for text/calls


4 Behaviors Leaders Must Model to Build a Culture of Trust
Trust is a concept most companies tout as one of their core values. The word "trust" sounds good at the annual employee retreat, it looks great on a plaque, and it seems like a no-brainer when you read it on the back of a brochure. But in reality, it’s often just a buzzword. Oh sure, leaders nod in professional approval when they hear it, but then they go right out and behave in a manner that makes everybody mistrust the manager. Business owners will often say, “trust is established with behavioral consistency.” In other words, if you behaved appropriately yesterday and today, then I’ll trust you to behave appropriately tomorrow. The truth is consistency of behaviors only works for creating a culture filled with trust when it’s a behavior you desire, and even then, some consistent behaviors still won’t get you there. For example, someone may be consistently charismatic yet unreliable -- hence not leading to trust. Even worse, what if two of your team members behaved obnoxiously or inappropriately yesterday and today? In fact, what if they were downright jerks yesterday and today? Then I only trust they’ll be jerks tomorrow too, which means I don’t actually trust them. Predictive behavior is not how you establish trust across your company’s culture.
Entrepreneur.com


This is what you need to run this software:
$settings['create_thumbnails']
variable to false
in the /config/settings.php
file. This way, the thumbnails will show as a scaled version of the main picture.Note: This gallery is not compatible with IE 5.x Mac since it seems not to support AJAX. the gallery will show a message to the user explaining this (this browser is discontinued by Microsoft, so please do not ask support for it).
Server Check: If you don't know if you have PHP installed in your host, try the following:
<?php phpinfo(); ?>
test.php
and upload it via ftp to your webspace.http://yourdomain/path/to/file/test.php
. Scrolling down you will find the current version of PHP and whether or not GD/GD2 is installed.Once you have checked that your server meets the prerequisites as listed above you are ready to begin the installation.
/config/settings.php
in a text editor (not Word! Notepad/TextEdit will do, saving as plain text) and make the changes you wish. Save and close the file.$settings['create_thumbnails']
and $settings['cache_thumbnails']
(check other variables that might be related). The thumbnail folders will be created inside the /cache/
directory, named after the gallery starting with cache_
(e.g. /cache/cache_yourgallery/
)./galleries/
folder. The $settings['show_sub_galleries']
flag will let you display galleries you have organized in heiarchical folders (i.e. /galleries/Traveling/Europe_2008/Rome
). Each gallery is treated individually in the sorting procedure and is listed with its full path. Note: be careful to upload images in data (binary) format, and text files in text (ascii) format.
/cache/
directory to 0777.That should be all!
Movies and videos can be added with your images and played direclty through the site. All videos are played at a constant size, which can be changed with the settings $settings['video_size_width']
and $settings['video_size_height']
. The default is YouTube sized videos (480x360).
Note: Only FLV (Adobe Flash) videos are supported. To convert your videos, use SUPER (Windows) or ffmpeg (Linux/Mac/Windows) (see this tutorial or this page for more details on how to use ffmpeg).
By default, a generic camcorder icon is used for video thumbnails. If you want custom thumbnails of videos to show up on the gallery page, place a JPEG image with the same name as the video in the directory. For instance, if you have a video named "Video.flv"
, you would put "Video.jpg"
in the same directory. Note the case of the flv and jpg must match (i.e. "Video.FLV" => "Video.JPG"
or "Video.flv" => "Video.jpg"
). The Picasa picture manager makes creating these video thumbnail images easy. When you click the Export button, select the "Export movies using: First Frame" option.
The JW FLV Media Player is used to play the FLV videos. You will need to make sure you abide by the license. If your usage is commerical (see details on what counts as commercial), you will need to buy a license of JW FLV Media Player.
If you want to have your galleries to appear in a specific order in the menu, just prepend a number and a dash NN-
to the folder name in the order you want. These numbers won't appear in the gallery title. In my opinion, a good practice is to append every gallery with the date formatted as YYMMDD-
if you want to order them by date.
Note: this setting might not work in some OSes/Hosts. If this is your case, let me know in the community
If you want your images to appear in a specific order, prepend a number and a dash NN-
to the image name. If you set $settings['show_thumb_number']
to false
those numbers won't show as part of the image caption.
If you want a gallery temporarily not to show in the menu, just prepend an underscore (_
) to the gallery folder name (eg. /galleries/_yourgallery/
). The same applies to images you want temporarily not to appear in a gallery.
If you want a description for the gallery, put it on a text file, name it _info.txt
(the default name) and save it inside the gallery images folder.
Note: you can change this file's default name in the /config/settings.php
file.
If you want to show a description of the image, just name the image with the text you want to appear as a caption.
Note: Underscores (_
) will be parsed and shown as spaces (), and Dashes (
-
) will be parsed and shown like this (-
), eg.my_image-comment.jpg
will look likemy image - comment
.
Picasa, Photoshop, and other image gallery/editing software will store captions in the IPTC field of a JPEG. If $settings['show_iptc_caption']
is set to true, this field will be extracted and displayed with the filename. This lets you caption your images in your favorite image managing software without having to mess with the filenames. For iPhoto users, look at something called Caption Buddy or search for exporting iPhoto pictures with IPTC captions embedded.
If you want to change any text on the gallery, look for it in the language files, inside /languages/
directory
If you want to add html code to let your gallery look like your site, you can add it in the Header/Footer files. Open the /add_header.php
and add al the Header code (the code that goes on top of the gallery), and do the same with the /add_footer.php
for the Footer code (the code that goes below the gallery). Follow the instructions on the files for adding the code. Then add the CSS definitions for the Header/Footer html in the /styles/includes.css
css file.
Note: When adding to the /styles/includes.css
, be careful with the CSS id/class naming, as if some conflict with the minishowcase css definitions, your gallery's look might suffer some problems.
minishowcase is supplied with a generic set of default values that can be customised to work better within your own site. Most of the variables for the working of the gallery are contained in the /config/settings.php
file. This means that you can change many of the features by editing just one file.
At this stage, customisation is still at a minimum level. Expect improved and more thorough customisation in the (near) future.
There are /*comments*/
throughout to assist with site redesigns.
Note: themes are now working again. Be aware that old themes are not compatible with the latest release of minishowcase Luckily, they're easily upgradeable. Just duplicate a new theme, copy the values of your old theme and add the missing ones accordingly. Please check afterwards since some values might have change their appearance.
Themes are preconfigured visual styles and they include overall color scheme and images. They're a good way to adapt (for now, colors and images) minishowcase to resemble more your website's appearance.
Themes are contained within the /themes/
folder. To make your own theme, just copy one of the provided ones, modify the images and the colors in the /themes/data.php
file. Then rename the theme's folder (it acts as the theme's name)
Themes included in the minishowcase download:
Other themes available for download:
If you make a new theme, and want to share it with the rest of us, send a .zip
compressed copy to<EMAIL_ADDRESS>and it may be showcased in the themes section. Please include all relevant information, including:
If the gallery names are looking funny or weird, and/or some characters look erroneous, or the galleries just don't load at all and you're using non-ASCII characters in the gallery names:
Open /config/settings.php
and set $settings['set_double_encoding']
to true
(default is false
, if yours is false
, then set it to true
).
Open the /galleries/index.php
file and set $thumbnail_creation
to true
. Then go to http://your-gallery/galleries/?thumbnails
and voilà! you can create thumbnails for every gallery.
Thumbnails will be created with the size set in /config/settings.php
under $settings['cached_thumbs_size']
. Change this value if you want better (or less) quality/size images. Default is 128px as max size, so for square thumbs is 128x128px, and for real aspect ratio (no square) is 128px max for the larger side.
If you decide to change the way your images show (by changing $settings['square_thumbnails']
) then you might have to rebuild the cached thumbs for them to keep the selected aspect ratio (square vs. real aspect ratio).
NOTE: In some cases, you might have to delete the thumbnails manually through FTP since the script might not be able to delete the thumbnails due to PHP strict file handling permissions.
Please remember to set $thumbnail_creation
back to false
in order to avoid other people recreating all your thumbnails!
Open the /config/settings.php file and change in line 243:
$settings['gallery_sorting'] = 4; //2 <-- CHANGE TO "4"
$settings['thumbnail_sorting'] = 0; //6 <-- CHANGE TO "0"
This seems to be the solution if you're getting an error on line 822 as discussed in this thread
That should help and make thumbnails show. If that does not solve your problem, or if you want more information, read and post on this thread
(Not supported AT ALL, use at your own risk)
On the first lines of the /libraries/ajax.init.js
file, you'll find some advance settings:
If you don't want to jump to the next gallery block when you are at the last image and click the arrow, set this to false
// jump from last block image to next block first image
var continuous_nav = true;
If you set to true
all images will be load simultaneously. It'll slightly accelerate thumbnail loading but it might crash or block the browser on galleries with many thumbnails.
// load thumbnails one by one
var use_load_interval = true;
If you don't want to show the AJAX loader bar, set this to false
// show ajax loader
var show_loading_bar = true;
Set to true
if you want the minishowcase Preview pane to animate (fade in/out) when showing an image
// animate preview pane show/hide
var animate_preview = false;
Set to true
if you want to go right directly to the permalink URL when you click on the 'permalink' link (Does not work right, use at your own risk)
// clicking on permalink loads it directly
var active_permalink = false;
This one is just for debugging purposes. Do not change it.
// resize the thumbnail container
var set_thumbnail_container_height = false;
Set to true
if you want visited galleries to change color
// set visited galleries to 'visited' color
var show_visited_galleries = false;
If you need help and your issue is not described here, please post your issue in the community forums
Any doubt, information or request might be discussed in the community. I am oftentimes very busy, a freelancer that travels from time to time, and it may happen that I don't check the threads immediately, but do not doubt that your suggestions and requests will be taken into consideration and a prompt answer is likely to be delivered.
IMPORTANT: Please read this INSTRUCTIONS thoroughly before sending any complaint/bug/feature request. If you don't receive an answer to your post or email, chances are the answer has already been covered here and I just cannot be bothered to rewrite it.
This program is freeware, you may use it at your own discretion, If you want, you can write to me and tell me where are you using it, just to check it out.
This program is in a very alpha version, I am only distributing it because it is such a simple gallery, it might be useful to others. The web is full of full-fledged, perfectly-functional php image galleries, this one is for those that want an extremely simple, easy yet powerful and configurable gallery. If you're learning php, this is a very nice place where to start. And, after all, it is offered at no cost.
This software is provided 'As Is', and no implied warranties are to be considered in any way watsoever, not even the implied warranty of FITNESS OF MERCHANTABILITY OR FOR A PARTICULAR PURPOSE. It is free, you can do whatever you want with it, it is safe, it is just server scripting code, that should be enough. By downloading this software you are deemed to this agreement.


{% extends "sentry/account/twofactor/configure.html" %} {% load i18n %} {% load sentry_helpers %} {% block twofactor_info %} {{ block.super }} {% with auth.get_registered_devices as devices %} {% if devices %}


Purple background represents the prize to the boss directly left to it.
For the 9th and 10th bosses, they require certain medallions to enter the dungeon. Click the medallion to change it to any of the three.
Click the boss when the boss is completed.
Click the item to toggle or advance the item.
Double click to reset the icon.


How the Internet Works
Date: May 4, 2014
The internet is an indispensable part of many people's lives around the world. It is a system of networks that connects people and faciilitiates the sharing and transfer of information. I will attempt to briefly explain how this complex system works in today's blog post.
First of the internet is a system of networks, or networks of networks. Most people have an Internet Service Provider (ISP) that they connect to, and are part of the ISP's network, which also can be a part of a larger network. Another option for connecting to the internet is a Local Area Network (LAN) which people mainly use at say a business, and this network can also be part of the larger networks that make up the Internet.
Another important thing in this discussion is that the internet is not only one network, or controlled by one master network. There are just high level networks that connect to each other through Network Access Points (NAP). Different ISPs all over the world in different areas interconnect at various NAPs and data is interchanged at these points.
That's just the big picture of how computers are able to communicate through networks. Next up is what happens when you access a webpage.
First off, each device (i.e. computer) has an assigned Internet Protocol address (IP address) that is unqiue. All web address that you access, like "http://github.com," actually can be access through their corresponding IP address. A neat thing called Domain Name System (DNS), lets you type in "github.com" and the computer will automatically link that to the right IP address to access.
Secondly, each machine that accesses the internet can be classified as client or server. The difference between them is that servers host content/data and provide access to other devices, while clients access these services. When you connect to a webpage using your computer, your computer is the client and you are accessing the webpage's server. The server's IP address usually doesn't change often, while client IP addresses can change frequently.
When you access a webpage, basically your computer sends a request over the internet. This request for information travels through networks until it hits a DNS, where it will look for a match for the domain that you entered. If it finds the match, it will send the request to the right server's IP address. If not, it will send your request along to another DNS that has more information.
When the request finally reaches the correct server, it will send the information requested along in packets. The information is basically broken down into small parts (packets) that are sent along to you. These packets have the IP of your computer in them so they know where to go, and they also have data of the order they need to be arranged in. Not all the packets may travel the same path back to your computer, that way if certain parts of the internet are down or congested, it is still possible to recieve information/packets through other routes.
This concludes my brief explanation of how the internet works. There are definitely more steps inbetween the ones I have listed, but this is a general breakdown for now.


Pmw.CounterDialog() - selection dialog displaying a counter
A counter dialog is a dialog window which displays a counter which can be used to prompt the user for a value.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
component('entry').delete()
.
component('entry').index()
.
component('entry').insert()
.
class Demo: def __init__(self, parent): # Create the dialog to prompt for the number of times to ring the bell. self.dialog = Pmw.CounterDialog(parent, label_text = 'Enter the number of times to\n' + \ 'sound the bell (1 to 5)\n', counter_labelpos = 'n', entryfield_value = 2, counter_datatype = 'numeric', entryfield_validate = {'validator' : 'numeric', 'min' : 1, 'max' : 5}, buttons = ('OK', 'Cancel'), defaultbutton = 'OK', title = 'Bell ringing', command = self.execute) self.dialog.withdraw() # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show counter dialog', command = self.dialog.activate) w.pack(padx = 8, pady = 8) def execute(self, result): if result is None or result == 'Cancel': print 'Bell ringing cancelled' self.dialog.deactivate() else: count = self.dialog.get() if not self.dialog.valid(): print 'Invalid entry: "' + count + '"' else: print 'Ringing the bell ' + count + ' times' for num in range(string.atoi(count)): if num != 0: self.dialog.after(200) self.dialog.bell() self.dialog.deactivate()
Pmw 1.2 -
5 Aug 2003
- Home
Manual page last reviewed: 18 May 2002


General Public Education Module
a GVSU senior project component
Click the arrows, use your arrow keys, or swipe to advance slides
What does PV stand for?
- PV stands for Photovoltaic
- Etymology
- Photo is derived from phos, the Greek word for light
- Voltaic is derived from volt, the English word for electrical potential
How Does Solar Energy Work?
- There are two types of solar energy systems: ON GRID, and OFF GRID
- On grid systems have a connection to the local power grid, and allow for electricity to be produced by the solar sources to be supplemented with power from the grid, if the output is too low, or the electricity can be sold back if there is excess production.
- Off grid systems have no connectino to the local grid, instead they have deep-cycle battery banks which are used to store electricity for use when the solar sources are not producing enough electricity. The stored electricity comes from times when there is an excess production of electricity.
How Does Solar Energy Work? - On Grid
- Solar cells in PV panels or shingles collect sunlight and convert it to direct current (DC) electricity.
- The DC electricity travels through an inverter, converting it into alternating current (AC) electricity. (This is what comes out of the outlets in your home).
- From the inverter, the electricity is either sent into the powered building for use, or sold back if it is not needed.
- If the electricity is sold back, it travels through a meter to measure how much electricity has been sold back to the utility company so that the proper balance is paid by the utility company to the property owner.
How Does Solar Energy Work? - Off Grid
- Just like on grid systems, solar cells collect sunlight and convert it into DC electricity.
- The electricity is sent to a charge controller, which manages the charging and discharging rate of the batteries, so that they are never over-taxed or over-charged
- From the batteries, the electricity needed to power the building is drawn into the inverter, to once again convert from DC to AC electricity.
- The AC electricity is then supplied to the building for use.
Question 1:
Click or Tap the option that fills the blanks:
On grid systems ______ while off grid systems ______.
a) store surplus electricity in batteries, sell surplus electricity
b) burn surplus electricity, store surplus electricity in batteries
c) sell surplus electricity, burn surplus electricty
d) sell surplus electricity, store surplus electricity in batteries
In What Conditions Will a Solar Power System Work?
- Several different factors can affect the viability of solar collection systems such as:
- Weather
- Location (on the planet)
- Environment (surrounding topography)
What Weather Conditions can a Solar Power System Withstand?
- Rain is anticipated by solar panel and shingle manufacturers, and they are ensured to be waterproof, thus even strong downpours are not an issue.
- Solar panels are rated to withstand impacts from objects such as hail, up to 1” in diameter at 50 mph.
- Wind is also anticipated, so panels are mounted on brackets which are secured to the load bearing structure of the roof. Solar shingles are equally as susceptible to wind as normal shingles.
What Weather Conditions can a Solar Power System Withstand?
- Arid regions, such as the south-western United States, will need to ensure that solar sources remain free of dust and loose debris that could be blown onto the collectors over night or over time. Buildup can cause electrical production to be significantly lower than expected.
- In locations where snow is a factor, panels are designed such that the snow will typically be sloughed off naturally throughout the day. In extreme circumstances, snow should be removed from the panels to prevent excessive amounts of weight from building up.
Where Will a Solar Power System Work?
- A solar power system can be installed anywhere on Earth with the exception of the poles.
- As Earth orbits around the sun, it is on a tilted axis. This means that at times certain parts of Earth are closer to the sun and some are further away.
- To get the largest amount of electricity production from PV cells, they should be facing the sun as squarely as possible.
- This is accomplished by tilting the PV cells to a specific angle given the latitude of the location. These angles can be found at various sites online.
What Environment can a Solar Power System Work In?
- Any shading of solar panels or shingles will reduce their output, so the more a location has direct sunlight throughout the day, the greater production there can be from a solar power system.
- Extreme humidity can significantly reduce the efficiency of a solar power system, so less humid areas are ideal.
Question 2
Click or Tap the option that fills the blank:
Solar panels should not be used if ______.
a) the area is heavily shaded
b) the area can receive snow
c) the area receives heavy rainfall
d) there is strong wind blowing around the panels
Question 3
Click or Tap an option:
(True/False) Solar power systems should only be installed on the north and south poles.
Question 4
Click or Tap the option that fills the blank:
High humidity causes a solar power system to ______.
How is the Power System Mounted?
There are three methods to mount a solar panel system, while shingles are only used in the same fashion as traditional shingles:
- Two-axis tracking - allows the system to follow the sun on its' east-west journey each day. It also allows for the north-south tilt angle, which will gradually change with the seasons, to be adjusted periodically.
- One-axis tracking - allows the system to only follow one of the two paths of a two-axis tracking system.
- Fixed - the system is completely restrained and has no motion. Residential and light commercial roof installations are typically fixed.
From here on out, we will focus on a fixed system.
What Regular Maintenance is Needed?
There is little maintenance needed for the overall system, as there are no moving parts, but consider the following:
- Clean off the exposed the glass periodically, especially if you live in a dusty or windy climate, any debris can block some light and reduce your system output (imagine never cleaning your car windshield!)
- Monitor your system output, so you know to check the system if the output dips unexpectedly.
What Components Does a Solar Power System Need?
- On Grid
- Solar collector (panels or shingles)
- Inverter (micro or string)
- Optional:
- Battery bank
- Charge controller
- Off Grid
- Solar collector
- Charge controller
- Battery bank
- Inverter
Solar Collection Methods
- Panels
- Larger footprint
- Higher efficiency
- Lower cost
- Less aesthetic value
- Shingles
- Smaller footprint
- Lower efficiency
- Higher cost
- Higher aesthetic value
Inverters
- String Inverter
- Accept from multiple collectors
- Generally used with panel groups
- Shading on a single panel will significantly drop the output of the whole panel group
- Lower cost
- Micro-Inverter
- Only accepts input from one collector
- Generally used with shingles
- Allows for partial shading of panels without significantly dropping overall output
- Higher cost
Question 5
Click or Tap an option:
- (True/False) You need a battery bank for an on grid system.
Question 6
Click or Tap the option that fills the blank:
Microinverters work with ______.
What to do with Excess Power?
- Sell it Back
- Local electric companies are usually willing to buy back extra electricity in the form of credits applied to your monthly bill. This is called net metering.
- Contact your electricity provider to determine how to set this up
- Store it!
- Battery banks can be used to store electricity for later use.
- Be sure to properly size your battery bank.
- Include a charge controller to prevent overcharging the batteries.
Battery Sizing
Properly sizing a battery bank will require the following metrics:
- Average daily energy use.
- How man days you want the batteries to sustain the building.
- System voltage
Expected System Lifetime
- Solar panels are built to last over 25 years. As they age their output decreases down to as low as 80% of their original maximum output.
- Modern inverters are made to last between 20 and 25 years as well.
- Batteries are generally good between 10 and 15 years, however there is significant variance depending on the type of battery used.
/


Ravel Residence / OZ
- Curated by María Francisca González
- about 7 hours
Housing · Amsterdam, The Netherlands
- version="1.0" encoding="UTF-8"? Architects: OZ
- AreaArea of this architecture projectArea: 24500.0 m2
- version="1.0" encoding="UTF-8"?YearCompletion year of this architecture project Year: 2015
- version="1.0" encoding="UTF-8"?PhotographsPhotographs: Ronald Tilleman
- version="1.0" encoding="UTF-8"?ManufacturersBrands with products used in this architecture project Manufacturers: Cape Cod, Carl Stahl, Jan Snel, Plastica
- Design Team John Bosch, Thijs Ultee, Martin de Jong, Harmen Meijer, Wilgo Elshot
- Clients The Student Experience / Verwey Holding Mijdrecht
- Engineering Jan Snel
- Consultants Promad, BoGro BV and LBP Sight
- Project Management Bouwsupport 1
More Specs Less Specs
Text description provided by the architects. The Ravel Residence is a versatile, sustainable campus for 800 students, designed to have a positive impact on the urban environment. The goal was to give the Ravel location a new urban identity, with a better connection to the urban and cultural climate in Amsterdam. The use of bicycles and public transport is stimulated and encouraged.
A mix of functions provides a viable and enjoyable living and working environment in a green urban environment. Ravel Residence is a durable, recyclable building shaped by detailed attention to flexibility. Long term quality assurance is achieved through careful management of energy, environmental, and social services.
Student housing is primarily housing for young people who are at the start of their (living) career. This growing group is on the lookout for good, affordable, sustainable, and flexible accommodation. They all want places of their own, with plenty of privacy, but also with opportunities to build up a social student life. Preferably in a dynamic urban setting close to amenities and public transport.
The location provides everything a student needs for pleasant and comfortable living. There are study rooms for individual or collective use; facilities designed in the manner of a grand café, a lounge, or a private dining room — in order to cook and eat with guests. There is a laundry, a large bicycle storage and a courtyard, as well as a unique sports field installed on the roof of the building. There is even a general practitioner’s practice, where a neighbourhood doctor visits the Ravel Residence twice a week for consultations.
We were asked to make an entrance at the side of Antonio Vivaldistraat and create a special program that stimulates liveliness in the area at the corner of the Boelelaan. By removing a number of apartments at strategic locations, we were able to create spaces for public, commercial, and collective purpose. The mix of public and private functions, complemented by two separate outdoor spaces, each with its own character, ensures a pleasant living environment.


1 egg*
1/3 cup olive oil
2/3 cup milk
Scant 1 1/2 cups (170 grams) tapioca flour
1/2 cup (packed, about 66 grams) grated cheese, your preference, though we got the best results from Mexican farmer's cheese - queso fresco
1 teaspoon of salt (or more to taste)
*It helps when baking with eggs to start with eggs at room temperature. If you don't plan ahead (that would be me, usually) you can put the egg in a bowl of warm water for a few minutes to gently take off the chill of the fridge.
Preheat oven to 400°F. Grease a mini-muffin tin. Put all of the ingredients into a blender and pulse until smooth. You may need to use a spatula to scrape down the sides of the blender so that everything gets blended well. At this point you can store the batter in the refrigerator for up to a week.
Bake in the oven for 15-20 minutes, until all puffy and just lightly browned. Remove from oven and let cool on a rack for a few minutes.
Eat while warm or save to reheat later.
Note that Brazilian cheese bread is very chewy, a lot like Japanese mochi.


This is an interactive data visualization of my
last.fm listening history.
It showcases which artists I've listened to on a weekly basis.
Select a date range below and hover over areas of the
Listening history to explore the data.
Click on an area to show its extent.


Store Performance Metrics
(All Locations) -
Cafe
Roastery
Locations
Net Sales by Gross Profit
Net Sales, Total Cost by Profit Margin
Location Metrics
Labor - Food - Facility Cost by Gross Profit


Change Log: 2.073.0
Download D 2.073.0
released Jan 22, 2017
Compiler changes
Library changes
- Added std.traits.Promoted to get the result of scalar type promotion in multi-term arithmetic expressions
- Added std.algorithm.searching.maxIndex to get the index of the maximum element of a range.
- Added std.meta.staticIsSorted to check if an AliasSeq is sorted according to some template predicate.
- Added std.algorithm.searching.minIndex to get the index of the minimum element of a range.
- std.traits.hasFunctionAttributes has been added
- std.experimental.ndslice has been deprecated.
Language changes
List of all bug fixes and enhancements in D 2.073.0.
Compiler changes
- New command line option -mscrtlib=libname for Windows MS-COFF object files.
If building MS-COFF object files with -m64 or -m32mscoff, this option specifies the reference to the C runtime library libname that is embedded into the object file containing main, DllMain or WinMain for automatic linking. The default is libcmt (release version with static linkage), the other usual alternatives are libcmtd, msvcrt and msvcrtd. If libname is empty, no C runtime library is automatically linked in.
- The builtin Ddoc theme has been overhauled.
Dmd will now use more modern looking theme for generated documentation, also see dmd#6173.
Library changes
- Added std.traits.Promoted to get the result of scalar type promotion in multi-term arithmetic expressions
std.traits.Promoted gets the type to which a scalar type will be promoted in multi-term arithmetic expressions
import std.traits : Promoted; static assert(is(typeof(ubyte(3) * ubyte(5)) == Promoted!ubyte)); static assert(is(Promoted!ubyte == int));
See the D specification on scalar type promotions for more information.
- Added std.algorithm.searching.maxIndex to get the index of the maximum element of a range.
std.algorithm.searching.maxIndex gets the index of the maximum element of a range, according to a specified predicate. The default predicate is "a > b".
import std.algorithm.searching : maxIndex; int[] a = [5, 4, 2, 1, 9, 10]; assert(a.maxIndex == 5); int[] a; assert(a.maxIndex == -1);
- Added std.meta.staticIsSorted to check if an AliasSeq is sorted according to some template predicate.
std.meta.staticIsSorted checks whether an AliasSeq is sorted according to some template predicate.
enum Comp(T1, T2) = T1.sizeof < T2.sizeof; import std.meta : staticIsSorted; static assert( staticIsSorted!(Comp, byte, uint, double)); static assert(!staticIsSorted!(Comp, bool, long, dchar));
Additionally, the compile-time performance of std.meta.staticSort has been greatly improved. Nevertheless, due to compiler limitations it is still an extraordinarily expensive operation to perform on longer sequences; strive to minimize such use.
- Added std.algorithm.searching.minIndex to get the index of the minimum element of a range.
std.algorithm.searching.minIndex gets the index of the minimum element of a range, according to a specified predicate. The default predicate is "a < b".
import std.algorithm.searching : minIndex; int[] a = [5, 4, 2, 1, 9, 10]; assert(a.minIndex == 3); int[] a; assert(a.minIndex == -1);
- std.traits.hasFunctionAttributes has been added
It exposes a user-friendly way to query for function attributes:
import std.traits : hasFunctionAttributes; // manually annotated function real func(real x) pure nothrow @safe { return x; } static assert(hasFunctionAttributes!(func, "@safe", "pure")); static assert(!hasFunctionAttributes!(func, "@trusted")); // for templated function types are automatically inferred bool myFunc(T)(T b) { return !b; } static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow")); static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
- std.experimental.ndslice has been deprecated.
The synchronization between Phobos and Mir turned out to be a lot of work with litte gain. Users of std.experimental.ndslice are advised to switch to the upstream mir package.
Language changes
List of all bug fixes and enhancements in D 2.073.0:
DMD Compiler regressions
- Bugzilla 16102: [REG2.070] struct dtor replace value on stack
- Bugzilla 16278: [REG2.067] undefined reference when class template is instantiated only in 'is' expression
- Bugzilla 16574: [REG 2.072.0-b1] Unexplained errors about functions that overridde anything
- Bugzilla 16598: [REG2.069] ICE with void ternary + finalizers
- Bugzilla 16678: [REG] Fix for issue 16193 creates major breakage
- Bugzilla 16699: [REG 2.070] stack corruption with scope(exit)
- Bugzilla 16747: [Reg 2.072] Cannot have stack allocated classes in @safe code
- Bugzilla 16980: [REG2.072.0] wrong interface called
- Bugzilla 17029: [Reg 2.072] scope variable may not be returned
- Bugzilla 17059: [REG 2.072.2] incorrect circular reference with is(Klass : Interface)
- Bugzilla 17072: [REG 2.073.0-b1] missing symbols with -inline
- Bugzilla 17073: [Reg 2.071.0] Priority clash with void default initialization of struct fields
- Bugzilla 17074: extern(C++, keyword) crashes compiler
- Bugzilla 17087: [REG2.072] Wrong generated with cfloat and creal when casting from int
DMD Compiler bugs
- Bugzilla 922: export keyword causes undefined references on linux
- Bugzilla 1761: TypeInfo.toString for function types always indicates no-parameter function
- Bugzilla 5995: string append negative integer causes segfault
- Bugzilla 8838: Slicing static arrays should be considered unsafe (@system)
- Bugzilla 10447: Refused increment of double2 with a immutable(double2)
- Bugzilla 11118: undefined identifier in template structs functions
- Bugzilla 11961: Can't select CRT to link against
- Bugzilla 12430: non compile-time __simd opcode causes ICE
- Bugzilla 13927: optimizer hangs in optelem with SIMD initialization
- Bugzilla 14238: DIP25: escape checks can be circumvented with delegate
- Bugzilla 14613: DMD: Internal error: backend/cod1.c 1567 on '-O' switch
- Bugzilla 15544: Escaping fields to a heap delegate must be disallowed in @safe code
- Bugzilla 15576: extern(C++, namespace) wrong mangling of variables (Windows)
- Bugzilla 15862: Functions that return types with mutable indirections should be weakly pure, not strongly pure
- Bugzilla 15989: Initializing manifest constants with CTFE allocated data
- Bugzilla 16116: Infinite loop on (somewhat complex) simd math
- Bugzilla 16146: postblit is not called on struct creation with "{field:value}" syntax
- Bugzilla 16381: Wrapping a float4 array leads to segfault.
- Bugzilla 16488: [spec][optimization] broadcast scalar to simd vector
- Bugzilla 16499: Misleading error message for 'in' operator with wrong argument
- Bugzilla 16523: [ICE] Internal error: backend/symbol.c 1031
- Bugzilla 16589: Taking address of stack variables in @safe code is allowed in some cases
- Bugzilla 16679: prefetch on old pentium d results in an illegal instruction
- Bugzilla 16743: Intrinsic recognition sometimes fails if a software implementation is available
- Bugzilla 16854: Inline assembler has VMOVLHPS and VMOVHLPS swapped
- Bugzilla 16967: No switch case fallthrough warnings in in/out contracts
- Bugzilla 16977: bad debug info for function default arguments
- Bugzilla 17034: DMD 32 bit PIC wrong code
DMD Compiler enhancements
- Bugzilla 768: A switch to print predefined version identifiers
- Bugzilla 13474: Discard excess precision for float and double (x87)
- Bugzilla 16449: add support for RDTSCP in iasm
- Bugzilla 16558: [Mir] Generic unaligned load/store like (like LDC loadUnaligned and storeUnaligned)
- Bugzilla 16560: [Mir] Prefetch intrinsics like in LDC
- Bugzilla 16703: Support indexing of SIMD vector types
- Bugzilla 16798: Extend -Ipath switch to -Imodule=path so path heirarchy doesn't have to match package heirarchy
- Bugzilla 16958: replace -mavx switch with -mcpu=id
Phobos regressions
- Bugzilla 16609: std.experimental.ndslice.slice issues warnings when building Phobos
- Bugzilla 16661: [REG2.072] std/format.d(1070): Incorrect format specifier: .2f for wstring and dstring
- Bugzilla 16663: [REG 2.072] std.unit.toUpper rejects an alias this to a string
- Bugzilla 16667: [REG] dub test fails on std.conv after upgrade to dmd 2.072.0
- Bugzilla 16682: [REG 2.072] "privatization" of symbols in std.stdio breaks DFMT
- Bugzilla 17066: [REG2.073a] std.regex captures got immutable
Phobos bugs
- Bugzilla 6716: Linking a C program with D library causes DEH errors
- Bugzilla 8087: Improve clarity of std.algorithm documentation
- Bugzilla 9378: std.internal.digest.sha_SSE3 breaks if compiled with PIC
- Bugzilla 9391: Constant std.regex.regex
- Bugzilla 13314: BinaryHeap assumes Store has dup property
- Bugzilla 16048: std.getopt: duplicated options are not detected
- Bugzilla 16135: missing std.format import in std.algorithm.comparison
- Bugzilla 16255: std.algorithm.iteration.each on opApply doesn't support ref
- Bugzilla 16352: dead-lock in std.allocator.free_list unittest
- Bugzilla 16419: issue with ndslice.slice toHash
- Bugzilla 16478: Don't allow to!T() in constraint
- Bugzilla 16588: uniq's BidirectionalRange behavior is inconsistent with its InputRange behavior
- Bugzilla 16611: std.traits.fullyQualifiedName fails with error 'Unrecognized type const(void)'
- Bugzilla 16624: std.path.setExtension ddoc comment is strangely formated
- Bugzilla 16634: std.math exposes yl2x and yl2xp1 publicly
- Bugzilla 16653: ParameterDefaultValueTuple fails to compile when function has lazy param
- Bugzilla 16724: RandomCover.popFront is a no-op for the first call
- Bugzilla 16758: Variant.opIndex result not modified after opAssign
- Bugzilla 16794: dmd not working on Ubuntu 16.10 because of default PIE linking
- Bugzilla 16955: std.process.spawnProcessImpl can crash due to alloca
- Bugzilla 16959: bringToFront fails on char arrays
- Bugzilla 16970: Fix deprecations and warnings when compiling Phobos
- Bugzilla 16996: std.algorithm.remove with SwapStrategy.unstable removes more entries
Phobos enhancements
- Bugzilla 4125: std.numeric.gcd can use a binary GCD
- Bugzilla 16249: std.signals: disconnect() is unsafe during emit()
- Bugzilla 16571: Unittests should not list /tmp/ recursively
- Bugzilla 16628: Special case std.algorithm.equal for known empty or infinite ranges
Druntime regressions
- Bugzilla 16974: [REG2.068] Equal associative arrays with associative array keys are considered unequal
Druntime bugs
- Bugzilla 16651: atomicOp!"-="(ulong, uint) = wrong result/codegen
- Bugzilla 16654: hashOf returns different hashes for the same string value
- Bugzilla 16764: hashOf is misleading, error-prone, and useless
Druntime enhancements
- Bugzilla 16797: Zero clock resolution lead to division by zero
dlang.org bugs
- Bugzilla 16592: Building dlang.org does not work without a preexisting dmd installation
- Bugzilla 16948: broken links in std.stdio due to inccorrect use of WEB macro
dlang.org enhancements
- Bugzilla 8799: Give example of Tuple mapped to a function
- Bugzilla 16147: Provide shiny 404 error pages
Tools regressions
- Bugzilla 14296: RDMD fails at building a lib when the source is in a subdir
- Bugzilla 16962: rdmd --build-only --force -c main.d fails: ./main: No such file or directory
- Bugzilla 16978: [REG2.072.0] pragma(lib) is broken with rdmd
Tools bugs
- Bugzilla 16966: rdmd: AssertError@rdmd.d(489): should have been created by compileRootAndGetDeps
Tools enhancements
- Bugzilla 16593: Building "tools" produces deprecation warnings