Skip to content

Commit

Permalink
Merge branch 'master' into batchrunner.fix
Browse files Browse the repository at this point in the history
  • Loading branch information
dmasad committed Nov 8, 2018
2 parents 54999e3 + c40c418 commit 003b9ea
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 30 deletions.
5 changes: 2 additions & 3 deletions examples/Schelling/analysis.ipynb
Expand Up @@ -122,14 +122,13 @@
" <tr>\n",
" <th>1</th>\n",
" <td>73</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>72</td>\n",
" <td>67</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>73</td>\n",
" <td>72</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
Expand Down
16 changes: 16 additions & 0 deletions examples/bank_reserves/bank_reserves/model.py
Expand Up @@ -80,6 +80,22 @@ def get_total_loans(model):


class BankReserves(Model):
"""
This model is a Mesa implementation of the Bank Reserves model from NetLogo.
It is a highly abstracted, simplified model of an economy, with only one
type of agent and a single bank representing all banks in an economy. People
(represented by circles) move randomly within the grid. If two or more people
are on the same grid location, there is a 50% chance that they will trade with
each other. If they trade, there is an equal chance of giving the other agent
$5 or $2. A positive trade balance will be deposited in the bank as savings.
If trading results in a negative balance, the agent will try to withdraw from
its savings to cover the balance. If it does not have enough savings to cover
the negative balance, it will take out a loan from the bank to cover the
difference. The bank is required to keep a certain percentage of deposits as
reserves and the bank's ability to loan at any given time is a function of
the amount of deposits, its reserves, and its current total outstanding loan
amount.
"""

# grid height
grid_h = 20
Expand Down
2 changes: 1 addition & 1 deletion mesa/visualization/modules/CanvasGridVisualization.py
Expand Up @@ -54,7 +54,7 @@ class CanvasGrid(VisualizationElement):
template: "canvas_module.html" stores the module's HTML template.
"""
package_includes = ["GridDraw.js", "CanvasModule.js"]
package_includes = ["GridDraw.js", "CanvasModule.js", "InteractionHandler.js"]

def __init__(self, portrayal_method, grid_width, grid_height,
canvas_width=500, canvas_height=500):
Expand Down
2 changes: 1 addition & 1 deletion mesa/visualization/modules/HexGridVisualization.py
Expand Up @@ -39,7 +39,7 @@ class CanvasHexGrid(VisualizationElement):
template: "canvas_module.html" stores the module's HTML template.
"""
package_includes = ["HexDraw.js", "CanvasHexModule.js"]
package_includes = ["HexDraw.js", "CanvasHexModule.js", "InteractionHandler.js"]
portrayal_method = None # Portrayal function
canvas_width = 500
canvas_height = 500
Expand Down
12 changes: 12 additions & 0 deletions mesa/visualization/templates/css/visualization.css
Expand Up @@ -12,3 +12,15 @@ div.tooltip {
border-radius: 8px;
pointer-events: none;
}

canvas.world-grid {
position:absolute;
top:50px;
left:15px;
border:1px dotted
}

canvas.chartjs-render-monitor {
position: absolute;
top: 560px;
}
13 changes: 8 additions & 5 deletions mesa/visualization/templates/js/CanvasHexModule.js
Expand Up @@ -2,24 +2,27 @@ var CanvasHexModule = function(canvas_width, canvas_height, grid_width, grid_hei
// Create the element
// ------------------

// Create the tag:
var canvas_tag = "<canvas width='" + canvas_width + "' height='" + canvas_height + "' ";
canvas_tag += "style='border:1px dotted'></canvas>";
// Create the tag with absolute positioning :
var canvas_tag = `<canvas width="${canvas_width}" height="${canvas_height}" class="world-grid"/>`
// Append it to body:
var canvas = $(canvas_tag)[0];
var interaction_canvas = $(canvas_tag)[0];
//$("body").append(canvas);
$("#elements").append(canvas);
$("#elements").append(interaction_canvas);

// Create the context and the drawing controller:
var context = canvas.getContext("2d");

var canvasDraw = new HexVisualization(canvas_width, canvas_height, grid_width, grid_height, context);
var interactionHandler = new InteractionHandler(canvas_width, canvas_height, grid_width, grid_height, interaction_canvas.getContext("2d"));

var canvasDraw = new HexVisualization(canvas_width, canvas_height, grid_width, grid_height, context, interactionHandler);

this.render = function(data) {
canvasDraw.resetCanvas();
for (var layer in data)
canvasDraw.drawLayer(data[layer]);
// canvasDraw.drawGridLines("#eee");
canvasDraw.drawGridLines("#eee");
};

this.reset = function() {
Expand Down
17 changes: 12 additions & 5 deletions mesa/visualization/templates/js/CanvasModule.js
Expand Up @@ -2,17 +2,24 @@ var CanvasModule = function(canvas_width, canvas_height, grid_width, grid_height
// Create the element
// ------------------

// Create the tag:
var canvas_tag = "<canvas width='" + canvas_width + "' height='" + canvas_height + "' ";
canvas_tag += "style='border:1px dotted'></canvas>";
// Create the tag with absolute positioning :
var canvas_tag = `<canvas width="${canvas_width}" height="${canvas_height}" class="world-grid"/>`


// Append it to body:
var canvas = $(canvas_tag)[0];
var interaction_canvas = $(canvas_tag)[0];

//$("body").append(canvas);
$("#elements").append(canvas);
$("#elements").append(interaction_canvas);

// Create the context and the drawing controller:
// Create the context for the agents and interactions and the drawing controller:
var context = canvas.getContext("2d");
var canvasDraw = new GridVisualization(canvas_width, canvas_height, grid_width, grid_height, context);

// Create an interaction handler using the
var interactionHandler = new InteractionHandler(canvas_width, canvas_height, grid_width, grid_height, interaction_canvas.getContext("2d"));
var canvasDraw = new GridVisualization(canvas_width, canvas_height, grid_width, grid_height, context, interactionHandler);

this.render = function(data) {
canvasDraw.resetCanvas();
Expand Down
10 changes: 9 additions & 1 deletion mesa/visualization/templates/js/GridDraw.js
Expand Up @@ -38,7 +38,7 @@ other agent locations, represented by circles:
*/

var GridVisualization = function(width, height, gridWidth, gridHeight, context) {
var GridVisualization = function(width, height, gridWidth, gridHeight, context, interactionHandler) {

// Find cell size:
var cellWidth = Math.floor(width / gridWidth);
Expand All @@ -50,6 +50,9 @@ var GridVisualization = function(width, height, gridWidth, gridHeight, context)

// Calls the appropriate shape(agent)
this.drawLayer = function(portrayalLayer) {
// Re-initialize the lookup table
(interactionHandler) ? interactionHandler.mouseoverLookupTable.init() : null

for (var i in portrayalLayer) {
var p = portrayalLayer[i];

Expand All @@ -63,6 +66,9 @@ var GridVisualization = function(width, height, gridWidth, gridHeight, context)
// normally keep y-axis in plots from bottom to top.
p.y = gridHeight - p.y - 1;

// if a handler exists, add coordinates for the portrayalLayer index
(interactionHandler) ? interactionHandler.mouseoverLookupTable.set(p.x, p.y, i) : null;

// If the stroke color is not defined, then the first color in the colors array is the stroke color.
if (!p.stroke_color)
p.stroke_color = p.Color[0]
Expand All @@ -76,6 +82,8 @@ var GridVisualization = function(width, height, gridWidth, gridHeight, context)
else
this.drawCustomImage(p.Shape, p.x, p.y, p.scale, p.text, p.text_color)
}
// if a handler exists, update its mouse listeners with the new data
(interactionHandler) ? interactionHandler.updateMouseListeners(portrayalLayer): null;
};

// DRAWING METHODS
Expand Down
49 changes: 35 additions & 14 deletions mesa/visualization/templates/js/HexDraw.js
Expand Up @@ -38,7 +38,7 @@ other agent locations, represented by circles:
*/

var HexVisualization = function(width, height, gridWidth, gridHeight, context) {
var HexVisualization = function(width, height, gridWidth, gridHeight, context, interactionHandler) {

// Find cell size:
var cellWidth = Math.floor(width / gridWidth);
Expand All @@ -48,14 +48,23 @@ var HexVisualization = function(width, height, gridWidth, gridHeight, context) {
// cell of the grid.
var maxR = Math.min(cellHeight, cellWidth)/2 - 1;

// Configure the interaction handler to use a hex coordinate mapper
(interactionHandler) ? interactionHandler.setCoordinateMapper("hex") : null;

// Calls the appropriate shape(agent)
this.drawLayer = function(portrayalLayer) {
// Re-initialize the lookup table
(interactionHandler) ? interactionHandler.mouseoverLookupTable.init() : null
for (var i in portrayalLayer) {
var p = portrayalLayer[i];
// Does the inversion of y positioning because of html5
// canvas y direction is from top to bottom. But we
// normally keep y-axis in plots from bottom to top.
p.y = gridHeight - p.y - 1;

// if a handler exists, add coordinates for the portrayalLayer index
(interactionHandler) ? interactionHandler.mouseoverLookupTable.set(p.x, p.y, i) : null;

if (p.Shape == "hex")
this.drawHex(p.x, p.y, p.r, p.Color, p.Filled, p.text, p.text_color);
else if (p.Shape == "circle")
Expand All @@ -65,6 +74,8 @@ var HexVisualization = function(width, height, gridWidth, gridHeight, context) {
else
this.drawCustomImage(p.Shape, p.x, p.y, p.scale, p.text, p.text_color)
}
// if a handler exists, update its mouse listeners with the new data
(interactionHandler) ? interactionHandler.updateMouseListeners(portrayalLayer): null;
};

// DRAWING METHODS
Expand Down Expand Up @@ -202,21 +213,31 @@ var HexVisualization = function(width, height, gridWidth, gridHeight, context) {
Draw Grid lines in the full gird
*/

this.drawGridLines = function() {
this.drawGridLines = function(strokeColor) {
context.beginPath();
context.strokeStyle = "#eee";
maxX = cellWidth * gridWidth;
maxY = cellHeight * gridHeight;

// Draw horizontal grid lines:
for(var y=0; y<=maxY; y+=cellHeight) {
context.moveTo(0, y+0.5);
context.lineTo(maxX, y+0.5);
}
context.strokeStyle = strokeColor || "#eee";
const maxX = cellWidth * gridWidth;
const maxY = cellHeight * gridHeight;

const xStep = cellWidth * 0.33;
const yStep = cellHeight * 0.5;

var yStart = yStep;
for(var x=cellWidth/2; x<=maxX; x+= cellWidth) {
for(var y=yStart; y<=maxY; y+=cellHeight) {

context.moveTo(x - 2 * xStep, y);

context.lineTo(x - xStep, y - yStep)
context.lineTo(x + xStep, y - yStep)
context.lineTo(x + 2 * xStep, y )

context.lineTo(x + xStep, y + yStep )
context.lineTo(x - xStep, y + yStep )
context.lineTo(x - 2 * xStep, y)

for(var x=0; x<=maxX; x+= cellWidth) {
context.moveTo(x+0.5, 0);
context.lineTo(x+0.5, maxY);
}
yStart = (yStart === 0) ? yStep: 0;
}

context.stroke();
Expand Down

0 comments on commit 003b9ea

Please sign in to comment.