1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/20euros_ynh.git synced 2024-09-03 18:05:53 +02:00

first commit

This commit is contained in:
admin 2015-03-08 14:02:54 +00:00
parent 61613f9a17
commit c8d5fadc9f
28 changed files with 2931 additions and 0 deletions

5
README.md Normal file
View file

@ -0,0 +1,5 @@
# 20euros
A clone of 2048 game with euro coins and bills
https://github.com/jatekos101/20euros

13
conf/nginx.conf Normal file
View file

@ -0,0 +1,13 @@
location YNH_WWW_PATH {
alias YNH_WWW_ALIAS ;
# Force https
if ($scheme = http) {
rewrite ^ https://$server_name$request_uri? permanent;
}
index index.html;
# Include SSOWAT user panel.
include conf.d/yunohost_panel.conf.inc;
}

43
manifest.json Normal file
View file

@ -0,0 +1,43 @@
{
"name": "20euros",
"id": "20euros",
"description": {
"en": "2048 - 20euros",
"fr": "2048 - 20euros"
},
"developer": {
"name": "Moul",
"email": "moul@moul.re"
},
"multi_instance": "false",
"arguments": {
"install" : [
{
"name": "domain",
"ask": {
"en": "Choose a domain for 20euros",
"fr": "Choisissez un nom de domaine pour 20euros"
},
"example": "domain.org"
},
{
"name": "path",
"ask": {
"en": "Choose a path for 20euros",
"fr": "Choisissez un chemin pour 20euros"
},
"example": "/20euros",
"default": "/20euros"
},
{
"name": "is_public",
"ask": {
"en": "Is it a public game?",
"fr": "Est-ce un jeu public ?"
},
"choices": ["Yes", "No"],
"default": "Yes"
}
]
}
}

41
scripts/install Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
# Retrieve arguments
domain=$1
path=$2
is_public=$3
# Check domain/path availability
sudo yunohost app checkurl $domain$path -a 20euros
if [[ ! $? -eq 0 ]]; then
exit 1
fi
# Save app settings
sudo yunohost app setting 20euros is_public -v "$is_public"
# Copy files to the right place
final_path=/var/www/20euros
sudo mkdir -p $final_path
sudo cp -a ../sources/* $final_path
# Set permissions
sudo chown -R www-data: $final_path
# Modify Nginx configuration file and copy it to Nginx conf directory
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
sed -i "s@YNH_WWW_ALIAS@$final_path/@g" ../conf/nginx.conf
nginxconf=/etc/nginx/conf.d/$domain.d/20euros.conf
sudo cp ../conf/nginx.conf $nginxconf
sudo chown root: $nginxconf
sudo chmod 600 $nginxconf
if [ "$is_public" = "Yes" ];
then
sudo yunohost app setting 20euros skipped_uris -v "/"
fi
# Reload web server & sso
sudo service nginx reload
sudo yunohost app ssowatconf

6
scripts/remove Executable file
View file

@ -0,0 +1,6 @@
#!/bin/bash
domain=$(sudo yunohost app setting 20euros domain)
sudo rm -rf /var/www/20euros
sudo rm -f /etc/nginx/conf.d/$domain.d/20euros.conf

34
scripts/upgrade Normal file
View file

@ -0,0 +1,34 @@
#!/bin/bash
# Retrieve settings
domain=$(sudo yunohost app setting 20euros domain)
path=$(sudo yunohost app setting 20euros path)
is_public=$(sudo yunohost app setting 20euros is_public)
# Remove trailing "/" for next commands
path=${path%/}
# Copy files to the right place
final_path=/var/www/20euros
sudo mkdir -p $final_path
sudo cp -a ../sources/* $final_path
# Set permissions
sudo chown -R www-data: $final_path
# Modify Nginx configuration file and copy it to Nginx conf directory
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
sed -i "s@YNH_WWW_ALIAS@$final_path/@g" ../conf/nginx.conf
nginxconf=/etc/nginx/conf.d/$domain.d/20euros.conf
sudo cp ../conf/nginx.conf $nginxconf
sudo chown root: $nginxconf
sudo chmod 600 $nginxconf
if [ "$is_public" = "Yes" ];
then
sudo yunohost app setting 20euros skipped_uris -v "/"
fi
# Reload web server & sso
sudo service nginx reload
sudo yunohost app ssowatconf

8
sources/README.md Normal file
View file

@ -0,0 +1,8 @@
20euros
=======
A 2048 variant with Euro coins and notes.
You'll find the game forum here: http://20euros.freeforums.net/
Feel free to fork my version and make pull requests!

33
sources/comment.html Normal file
View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en" manifest="cache.appcache">
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=http://20euros.freeforums.net/">
<title>20 Euros Forum</title>
<link href="style/main.css" rel="stylesheet" type="text/css">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
</head>
<body>
<script type="text/javascript">
var sc_project=9719822;
var sc_invisible=1;
var sc_security="bccc6417";
var scJsHost = (("https:" == document.location.protocol) ?
"https://secure." : "http://www.");
document.write("<sc"+"ript type='text/javascript' src='" +
scJsHost+
"statcounter.com/counter/counter.js'></"+"script>");
</script>
<noscript><div class="statcounter"><a title="ingyenes
webstatisztika" href="http://www.statcounter.hu/"
target="_blank"><img class="statcounter"
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
alt="ingyenes webstatisztika"></a></div></noscript>
</body>
</html>

79
sources/faq.html Normal file
View file

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en" manifest="cache.appcache">
<head>
<meta charset="utf-8">
<title>20 Euros FAQ</title>
<link href="style/main.css" rel="stylesheet" type="text/css">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta property="og:title" content="20euro game"/>
<meta property="og:site_name" content="20euro game"/>
<meta property="og:description" content="Join the coins and get the 20 Euro tile!"/>
<meta property="og:image" content="http://gabrielecirulli.github.io/2048/meta/og_image.png"/>
</head>
<body>
<div class="container">
<div class="heading">
<h1 class="title">20 Euros FAQ</h1>
</div>
<p class="game-intro">Frequently asked questions about my game <a href="http://jatekos101.github.io/20euros">20 Euros</a>.</p>
<hr>
<h2>Rules</h2>
<p><b>Q:</b> The game is buggy, sometimes it won't let me add two equal coins.<br>
<b>A:</b> Read the rules under the game first! For example, you can't add up two 2's to make 5, it wouldn't even make sense! To make a 5 cent coin, you have to combine two 2's and a 1.</p>
<p><b>Q:</b> Why doesn't 2+2+2+2+2 make 10?<br>
<b>A:</b> It's clearly written in the rules that at most 3 coins can merge at a time. Otherwise it would be too easy.</p>
<p><b>Q:</b> Can I continue after winning and make a 50 Euro note?<br>
<b>A:</b> Yes! You can even go all the way up to the 500 Euro note, if you can! <a href="http://20euros.freeforums.net/thread/8/500-achievement">That has actually been achieved (with an AI).</a></p>
<hr>
<h2>Variants</h2>
<p><b>Q:</b> Does the game have any variants?<br>
<b>A:</b> The only official variant is the <a href="http://jatekos101.github.io/20euros-undo">undo version</a>.</p>
<p><b>Q:</b> Can I make my own variant/fork?<br>
<b>A:</b> Yes! You are free to make your own forks based on my variant, you can download it or <a href="http://github.com/jatekos101/20euros">fork it on GitHub.</a></p>
<hr>
<h2>Others</h2>
<p>
<b>Q:</b> Is there a forum about the game?<br>
<b>A:</b> Yes, it's <a href="http://jatekos101.github.io/20euros/comment.html">here</a>. Feel free to add comments, suggestions or further questions!</p>
<p><b>Q:</b> Are the statistics of the game public?<br>
<b>A:</b> Yes, you can find them <a href="http://jatekos101.github.io/20euros/statistics.html">here</a>.</p>
<hr>
If you didn't find the answer to your question, you can ask it on the <a href="http://jatekos101.github.io/20euros/comment.html">forum</a>.
</div>
<script type="text/javascript">
var sc_project=9719822;
var sc_invisible=1;
var sc_security="bccc6417";
var scJsHost = (("https:" == document.location.protocol) ?
"https://secure." : "http://www.");
document.write("<sc"+"ript type='text/javascript' src='" +
scJsHost+
"statcounter.com/counter/counter.js'></"+"script>");
</script>
<noscript><div class="statcounter"><a title="web analytics"
href="http://statcounter.com/" target="_blank"><img
class="statcounter"
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
alt="web analytics"></a></div></noscript>
</body>
</html>

BIN
sources/images/bg_hr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

161
sources/index.html Normal file
View file

@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="en" manifest="cache.appcache">
<head>
<meta charset="utf-8">
<title>20 Euros</title>
<link href="style/main.css" rel="stylesheet" type="text/css">
<link href="style/example.css" rel="stylesheet" type="text/css">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta property="og:title" content="20euro game"/>
<meta property="og:site_name" content="20euro game"/>
<meta property="og:description" content="Join the coins and get the 20 Euro tile!"/>
<meta property="og:image" content="http://gabrielecirulli.github.io/2048/meta/og_image.png"/>
<script type="text/javascript" src="https://cdn.firebase.com/v0/firebase.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<div class="heading">
<h1 class="title">20 Euros</h1>
<div align="right"><a href="http://jatekos101.github.io/20euros/faq.html">FAQ</a> - <a href="http://jatekos101.github.io/20euros/comment.html">FORUM</a></div>
<p>
<div class="scores-container">
<div class="score-container">0</div>
<div class="best-container">0</div>
</div>
</div>
<p class="game-intro">Join the coins until you reach <strong>20 Euro</strong>!
</p>
<div class="game-container">
<div class="game-message">
<p></p>
<div class="lower">
<a class="keep-playing-button">Continue (maybe 50 Euro?)</a>
<a class="retry-button">Retry</a>
<div class="score-sharing"></div>
</div>
</div>
<div class="grid-container">
<div class="grid-row">
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
</div>
<div class="grid-row">
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
</div>
<div class="grid-row">
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
</div>
<div class="grid-row">
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
</div>
<div class="grid-row">
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
<div class="grid-cell"></div>
</div>
</div>
<div class="tile-container">
</div>
</div>
<p class="game-explanation">
<strong class="important">HOW TO PLAY: </strong> Use your <strong>arrow keys</strong> to move the coins. If two or three mergeable coins touch, they <strong>merge into one!</strong> Your goal is to reach the <strong>20 Euro</strong> note! Restart with <strong>Space</strong>.
</p>
<hr>
<p class="game-explanation">
<strong class="important">Mergeable combinations: </strong> <br>
1+1=2<br>
2+2+1=5<br>
5+5=10<br>
10+10=20 or 5+10+5=20<br>
20+20+10=50<br>
and so on.
</p>
<hr>
<p>
<strong class="important">FAQ: </strong> <a href="http://jatekos101.github.io/20euros/faq.html">Click here for the frequently asked questions.</a><br>
<strong class="important">Forum: </strong> <a href="http://jatekos101.github.io/20euros/comment.html">Click here for the game's forum.</a><br>
<strong class="important">Statistics: </strong> <a href="http://jatekos101.github.io/20euros/statistics.html">Click here for the statistics.</a>
</p>
<hr>
<p>
<strong class="important">Undo version: </strong> <a href="http://jatekos101.github.io/20euros-undo">You can play the undo version of the game here.</a>
<br>
<strong class="important">GITHUB: </strong> <a href="https://github.com/jatekos101/20euros">You can see and fork my game on GitHub here.</a>
</p>
<hr>
<p>
This is not the original version of 2048.<br>
Original created by Gabriele Cirulli.
</p>
</div>
<script src="js/animframe_polyfill.js"></script>
<script src="js/keyboard_input_manager.js"></script>
<script src="js/html_actuator.js"></script>
<script src="js/grid.js"></script>
<script src="js/tile.js"></script>
<script src="js/local_score_manager.js"></script>
<script src="js/game_manager.js"></script>
<script src="js/application.js"></script>
<script>
(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,"script","//www.google-analytics.com/analytics.js","ga");
ga("create", "UA-42620757-2", "gabrielecirulli.github.io");
ga("send", "pageview");
</script>
<script type="text/javascript">
var sc_project=9719822;
var sc_invisible=1;
var sc_security="bccc6417";
var scJsHost = (("https:" == document.location.protocol) ?
"https://secure." : "http://www.");
document.write("<sc"+"ript type='text/javascript' src='" +
scJsHost+
"statcounter.com/counter/counter.js'></"+"script>");
</script>
<noscript><div class="statcounter"><a title="web analytics"
href="http://statcounter.com/" target="_blank"><img
class="statcounter"
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
alt="web analytics"></a></div></noscript>
</body>
</html>

View file

@ -0,0 +1 @@
console.log('This would be the main JS file.');

View file

@ -0,0 +1,26 @@
(function() {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
}());

View file

@ -0,0 +1,3 @@
// Wait till the browser is ready to render the game (avoids glitches)
window.requestAnimationFrame(function () {
new GameManager(5, KeyboardInputManager, HTMLActuator, LocalScoreManager);});

328
sources/js/game_manager.js Normal file
View file

@ -0,0 +1,328 @@
function GameManager(size, InputManager, Actuator, ScoreManager) {
this.size = size; // Size of the grid
this.inputManager = new InputManager;
this.scoreManager = new ScoreManager;
this.actuator = new Actuator;
this.startTiles = 2;
this.inputManager.on("move", this.move.bind(this));
this.inputManager.on("restart", this.restart.bind(this));
this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
this.setup();
}
// Restart the game
GameManager.prototype.restart = function () {
this.actuator.
continue ();
this.setup();
};
// Keep playing after winning
GameManager.prototype.keepPlaying = function () {
this.keepPlaying = true;
this.actuator.
continue ();
};
GameManager.prototype.isGameTerminated = function () {
if (this.over || (this.won && !this.keepPlaying)) {
return true;
} else {
return false;
}
};
// Set up the game
GameManager.prototype.setup = function () {
this.grid = new Grid(this.size);
this.score = 0;
this.highestTile = 5;
this.over = false;
this.won = false;
this.keepPlaying = false;
// Add the initial tiles
this.addStartTiles();
// Update the actuator
this.actuate();
};
// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
for (var i = 0; i < this.startTiles; i++) {
this.addRandomTile();
}
};
// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
if (this.grid.cellsAvailable()) {
var value = Math.random() < 0.9 ? 1 : 5;
var tile = new Tile(this.grid.randomAvailableCell(), value);
this.grid.insertTile(tile);
}
};
// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
if (this.scoreManager.get() < this.score) {
this.scoreManager.set(this.score);
}
this.actuator.actuate(this.grid, {
score: this.score,
highest: this.highestTile,
over: this.over,
won: this.won,
bestScore: this.scoreManager.get(),
terminated: this.isGameTerminated()
});
};
// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
this.grid.eachCell(function (x, y, tile) {
if (tile) {
tile.mergedFrom = null;
tile.savePosition();
}
});
};
// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
this.grid.cells[tile.x][tile.y] = null;
this.grid.cells[cell.x][cell.y] = tile;
tile.updatePosition(cell);
};
// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
// 0: up, 1: right, 2:down, 3: left
var self = this;
if (this.isGameTerminated()) return; // Don't do anything if the game's over
var cell, tile;
var vector = this.getVector(direction);
var traversals = this.buildTraversals(vector);
var moved = false;
// Save the current tile positions and remove merger information
this.prepareTiles();
// Traverse the grid in the right direction and move tiles
traversals.x.forEach(function (x) {
traversals.y.forEach(function (y) {
cell = {
x: x,
y: y
};
tile = self.grid.cellContent(cell);
if (tile && tile.merged) {
self.grid.removeTile(tile);
} else if (tile) {
var positions = self.findFarthestPosition(cell, vector);
var next = self.grid.cellContent(positions.next);
var pos2 = null;
var next2 = null;
if (next) {
pos2 = self.findFarthestPosition({
x: next.x,
y: next.y
}, vector);
next2 = self.grid.cellContent(pos2.next);
}
// Only one merger per row traversal?
if (next && next2 && !next.mergedFrom && next != next2 && (((tile.value == 1) && (next.value == 2) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 1) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 2) && (next2.value == 1)) || ((tile.value == 10) && (next.value == 20) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 10) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 20) && (next2.value == 10)) || ((tile.value == 100) && (next.value == 200) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 100) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 200) && (next2.value == 100)) || ((tile.value == 1000) && (next.value == 2000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 1000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 2000) && (next2.value == 1000)) || ((tile.value == 10000) && (next.value == 20000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 10000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 20000) && (next2.value == 10000)) || ((tile.value == 5) && (next.value == 10) && (next2.value == 5)) || ((tile.value == 50) && (next.value == 100) && (next2.value == 50)) || ((tile.value == 500) && (next.value == 1000) && (next2.value == 500)) || ((tile.value == 5000) && (next.value == 10000) && (next2.value == 5000)))) {
var merged = new Tile(pos2.next, tile.value + next.value + next2.value);
merged.mergedFrom = [next2, next, tile];
tile.merged = true;
next.merged = true;
next2.merged = true;
self.grid.removeTile(tile);
self.grid.removeTile(next);
self.grid.removeTile(next2);
self.grid.insertTile(merged);
// Converge the two tiles' positions
tile.updatePosition(pos2.next);
next.updatePosition(pos2.next);
// Update the score
self.score += merged.value;
if (merged.value > self.highestTile) self.highestTile = merged.value;
// The mighty 20 Euro tile
if (merged.value === 2000) self.won = true;
} else if (next && next.value === tile.value && !next.mergedFrom && next.value != 2 && next.value != 20 && next.value != 200 && next.value != 2000 && next.value != 20000 && next.value != 50000) {
var merged = new Tile(positions.next, tile.value * 2);
merged.mergedFrom = [tile, next];
tile.merged = true;
next.merged = true;
self.grid.insertTile(merged);
self.grid.removeTile(tile);
// Converge the two tiles' positions
tile.updatePosition(positions.next);
// Update the score
self.score += merged.value;
if (merged.value > self.highestTile) self.highestTile = merged.value;
// The mighty 20 Euro tile
if (merged.value === 2000) self.won = true;
} else if (!tile.merged) {
self.moveTile(tile, positions.farthest);
}
if (tile && !self.positionsEqual(cell, tile)) {
moved = true; // The tile moved from its original cell!
}
}
});
});
if (moved) {
this.addRandomTile();
if (!this.movesAvailable()) {
this.over = true; // Game over!
}
this.actuate();
}
};
// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
// Vectors representing tile movement
var map = {
0: {
x: 0,
y: -1
},
// up
1: {
x: 1,
y: 0
},
// right
2: {
x: 0,
y: 1
},
// down
3: {
x: -1,
y: 0
} // left
};
return map[direction];
};
// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
var traversals = {
x: [],
y: []
};
for (var pos = 0; pos < this.size; pos++) {
traversals.x.push(pos);
traversals.y.push(pos);
}
// Always traverse from the farthest cell in the chosen direction
if (vector.x === 1) traversals.x = traversals.x.reverse();
if (vector.y === 1) traversals.y = traversals.y.reverse();
return traversals;
};
GameManager.prototype.findFarthestPosition = function (cell, vector) {
var previous;
// Progress towards the vector direction until an obstacle is found
do {
previous = cell;
cell = {
x: previous.x + vector.x,
y: previous.y + vector.y
};
} while (this.grid.withinBounds(cell) && this.grid.cellAvailable(cell));
return {
farthest: previous,
next: cell // Used to check if a merge is required
};
};
GameManager.prototype.movesAvailable = function () {
return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};
// Check for available matches between tiles(more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
var self = this;
var tile;
var i = 0;
while (i < 4) {
for (var x = 0; x < this.size; x++) {
for (var y = 0; y < this.size; y++) {
var vector = this.getVector(i);
tile = this.grid.cellContent({
x: x,
y: y
});
cell = {
x: x,
y: y
};
tile = self.grid.cellContent(cell);
if (tile) {
var positions = self.findFarthestPosition(cell, vector);
var next = self.grid.cellContent(positions.next);
var pos2 = self.findFarthestPosition({
x: cell.x + vector.x,
y: cell.y + vector.y
}, vector);
var next2 = self.grid.cellContent(pos2.next);
// Only one merger per row traversal?
if (next && next2 && next != next2 && (((tile.value == 1) && (next.value == 2) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 1) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 2) && (next2.value == 1)) || ((tile.value == 10) && (next.value == 20) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 10) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 20) && (next2.value == 10)) || ((tile.value == 100) && (next.value == 200) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 100) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 200) && (next2.value == 100)) || ((tile.value == 1000) && (next.value == 2000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 1000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 2000) && (next2.value == 1000)) || ((tile.value == 10000) && (next.value == 20000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 10000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 20000) && (next2.value == 10000)) || ((tile.value == 5) && (next.value == 10) && (next2.value == 5)) || ((tile.value == 50) && (next.value == 100) && (next2.value == 50)) || ((tile.value == 500) && (next.value == 1000) && (next2.value == 500)) || ((tile.value == 5000) && (next.value == 10000) && (next2.value == 5000)))) {
return true;
}
if (next && next.value === tile.value && next.value != 2 && next.value != 20 && next.value != 200 && next.value != 2000 && next.value != 20000 && next.value != 50000) {
return true;
}
}
}
}
i += 1;
}
return false;
};
GameManager.prototype.positionsEqual = function (first, second) {
return first.x === second.x && first.y === second.y;
};

84
sources/js/grid.js Normal file
View file

@ -0,0 +1,84 @@
function Grid(size) {
this.size = size;
this.cells = [];
this.build();
}
// Build a grid of the specified size
Grid.prototype.build = function () {
for (var x = 0; x < this.size; x++) {
var row = this.cells[x] = [];
for (var y = 0; y < this.size; y++) {
row.push(null);
}
}
};
// Find the first available random position
Grid.prototype.randomAvailableCell = function () {
var cells = this.availableCells();
if (cells.length) {
return cells[Math.floor(Math.random() * cells.length)];
}
};
Grid.prototype.availableCells = function () {
var cells = [];
this.eachCell(function (x, y, tile) {
if (!tile) {
cells.push({ x: x, y: y });
}
});
return cells;
};
// Call callback for every cell
Grid.prototype.eachCell = function (callback) {
for (var x = 0; x < this.size; x++) {
for (var y = 0; y < this.size; y++) {
callback(x, y, this.cells[x][y]);
}
}
};
// Check if there are any cells available
Grid.prototype.cellsAvailable = function () {
return !!this.availableCells().length;
};
// Check if the specified cell is taken
Grid.prototype.cellAvailable = function (cell) {
return !this.cellOccupied(cell);
};
Grid.prototype.cellOccupied = function (cell) {
return !!this.cellContent(cell);
};
Grid.prototype.cellContent = function (cell) {
if (this.withinBounds(cell)) {
return this.cells[cell.x][cell.y];
} else {
return null;
}
};
// Inserts a tile at its position
Grid.prototype.insertTile = function (tile) {
this.cells[tile.x][tile.y] = tile;
};
Grid.prototype.removeTile = function (tile) {
this.cells[tile.x][tile.y] = null;
};
Grid.prototype.withinBounds = function (position) {
return position.x >= 0 && position.x < this.size &&
position.y >= 0 && position.y < this.size;
};

337
sources/js/html_actuator.js Normal file
View file

@ -0,0 +1,337 @@
function HTMLActuator() {
this.tileContainer = document.querySelector(".tile-container");
this.scoreContainer = document.querySelector(".score-container");
this.bestContainer = document.querySelector(".best-container");
this.messageContainer = document.querySelector(".game-message");
this.sharingContainer = document.querySelector(".score-sharing");
this.score = 0;
this.highestTile = 1;
}
HTMLActuator.prototype.actuate = function (grid, metadata) {
var self = this;
window.requestAnimationFrame(function () {
self.clearContainer(self.tileContainer);
grid.cells.forEach(function (column) {
column.forEach(function (cell) {
if (cell) {
self.addTile(cell);
}
});
});
self.updateScore(metadata.score);
self.updateBestScore(metadata.bestScore);
self.highestTile = metadata.highest;
if (metadata.terminated) {
if (metadata.over) {
self.message(false); // You lose
} else if (metadata.won) {
self.message(true); // You win!
}
}
});
};
// Continues the game (both restart and keep playing)
HTMLActuator.prototype.continue = function () {
if (typeof ga !== "undefined") {
ga("send", "event", "game", "restart");
}
this.clearMessage();
};
HTMLActuator.prototype.clearContainer = function (container) {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
};
HTMLActuator.prototype.addTile = function (tile) {
var self = this;
var wrapper = document.createElement("div");
var inner = document.createElement("div");
var position = tile.previousPosition || { x: tile.x, y: tile.y };
var positionClass = this.positionClass(position);
// We can't use classlist because it somehow glitches when replacing classes
var classes = ["tile", "tile-" + tile.value, positionClass];
if (tile.value > 50000) classes.push("tile-super");
this.applyClasses(wrapper, classes);
inner.classList.add("tile-inner");
inner.textContent = tile.value;
if (tile.previousPosition) {
// Make sure that the tile gets rendered in the previous position first
window.requestAnimationFrame(function () {
classes[2] = self.positionClass({ x: tile.x, y: tile.y });
self.applyClasses(wrapper, classes); // Update the position
});
} else if (tile.mergedFrom) {
classes.push("tile-merged");
this.applyClasses(wrapper, classes);
// Render the tiles that merged
tile.mergedFrom.forEach(function (merged) {
self.addTile(merged);
});
} else {
classes.push("tile-new");
this.applyClasses(wrapper, classes);
}
// Add the inner part of the tile to the wrapper
wrapper.appendChild(inner);
// Put the tile on the board
this.tileContainer.appendChild(wrapper);
};
HTMLActuator.prototype.applyClasses = function (element, classes) {
element.setAttribute("class", classes.join(" "));
};
HTMLActuator.prototype.normalizePosition = function (position) {
return { x: position.x + 1, y: position.y + 1 };
};
HTMLActuator.prototype.positionClass = function (position) {
position = this.normalizePosition(position);
return "tile-position-" + position.x + "-" + position.y;
};
HTMLActuator.prototype.updateScore = function (score) {
this.clearContainer(this.scoreContainer);
var difference = score - this.score;
this.score = score;
this.scoreContainer.textContent = this.score;
if (difference > 0) {
var addition = document.createElement("div");
addition.classList.add("score-addition");
addition.textContent = "+" + difference;
this.scoreContainer.appendChild(addition);
}
};
HTMLActuator.prototype.updateBestScore = function (bestScore) {
this.bestContainer.textContent = bestScore;
};
HTMLActuator.prototype.message = function (won) {
var type = won ? "game-won" : "game-over";
var message = won ? "You won!" : "No more moves. Game over.";
// Build some firebase references.
var rootRef = new Firebase('https://20-euros.firebaseio.com');
var scoreListRef = rootRef.child("scoreList");
var highestScoreRef = rootRef.child("highestScore");
var RefPlays = rootRef.child("plays");
var Ref50 = rootRef.child("reached_50c");
var Ref100 = rootRef.child("reached_1e");
var Ref200 = rootRef.child("reached_2e");
var Ref500 = rootRef.child("reached_5e");
var Ref1000 = rootRef.child("reached_10e");
var Ref2000 = rootRef.child("reached_20e");
var Ref5000 = rootRef.child("reached_50e");
var Ref10000 = rootRef.child("reached_100e");
var Ref20000 = rootRef.child("reached_200e");
var Ref50000 = rootRef.child("reached_500e");
// Keep a mapping of firebase locations to HTML elements, so we can move / remove elements as necessary.
var htmlForPath = {};
// Helper function that takes a new score snapshot and adds an appropriate row to our leaderboard table.
function handleScoreAdded(scoreSnapshot, prevScoreName) {
var newScoreRow = $("<tr/>");
newScoreRow.append($("<td/>").append($("<em/>").text(scoreSnapshot.val().name)));
newScoreRow.append($("<td/>").text(scoreSnapshot.val().score));
// Store a reference to the table row so we can get it again later.
htmlForPath[scoreSnapshot.name()] = newScoreRow;
// Insert the new score in the appropriate place in the table.
if (prevScoreName === null) {
$("#leaderboardTable").append(newScoreRow);
}
else {
var lowerScoreRow = htmlForPath[prevScoreName];
lowerScoreRow.before(newScoreRow);
}
}
// Helper function to handle a score object being removed; just removes the corresponding table row.
function handleScoreRemoved(scoreSnapshot) {
var removedScoreRow = htmlForPath[scoreSnapshot.name()];
removedScoreRow.remove();
delete htmlForPath[scoreSnapshot.name()];
}
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 8; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
// Create a view to only receive callbacks for the last LEADERBOARD_SIZE scores
var scoreListView = scoreListRef.limit(10);
// Add a callback to handle when a new score is added.
scoreListView.on('child_added', function (newScoreSnapshot, prevScoreName) {
handleScoreAdded(newScoreSnapshot, prevScoreName);
});
// Add a callback to handle when a score is removed
scoreListView.on('child_removed', function (oldScoreSnapshot) {
handleScoreRemoved(oldScoreSnapshot);
});
// Add a callback to handle when a score changes or moves positions.
var changedCallback = function (scoreSnapshot, prevScoreName) {
handleScoreRemoved(scoreSnapshot);
handleScoreAdded(scoreSnapshot, prevScoreName);
};
scoreListView.on('child_moved', changedCallback);
scoreListView.on('child_changed', changedCallback);
var newScore = this.score;
var name = makeid();
$("#scoreInput").val("");
var userScoreRef = scoreListRef.child(name);
// Use setWithPriority to put the name / score in Firebase, and set the priority to be the score.
if ((newScore <= 500)||(this.highestTile <= 20)||(this.highestTile >= 2000)){
userScoreRef.setWithPriority({ name:name, score:newScore, highest:this.highestTile }, newScore);}
// Track the highest score using a transaction. A transaction guarantees that the code inside the block is
// executed on the latest data from the server, so transactions should be used if you have multiple
// clients writing to the same data and you want to avoid conflicting changes.
highestScoreRef.transaction(function (currentHighestScore) {
if (currentHighestScore === null || newScore > currentHighestScore) {
// The return value of this function gets saved to the server as the new highest score.
return newScore;
}
// if we return with no arguments, it cancels the transaction.
return;
});
RefPlays.transaction(function(current_value) {
return current_value + 1;
});
if (this.highestTile >= 50){
Ref50.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 100){
Ref100.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 200){
Ref200.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 500){
Ref500.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 1000){
Ref1000.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 2000){
Ref2000.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 5000){
Ref5000.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 10000){
Ref10000.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 20000){
Ref20000.transaction(function(current_value) {
return current_value + 1;
});
}
if (this.highestTile >= 50000){
Ref50000.transaction(function(current_value) {
return current_value + 1;
});
}
// Add a callback to the highest score in Firebase so we can update the GUI any time it changes.
highestScoreRef.on('value', function (newHighestScore) {
$("#highestScoreDiv").text(newHighestScore.val());
});
if (typeof ga !== "undefined") {
ga("send", "event", "game", "end", type, this.score);
}
this.messageContainer.classList.add(type);
this.messageContainer.getElementsByTagName("p")[0].textContent = message;
this.clearContainer(this.sharingContainer);
this.sharingContainer.appendChild(this.scoreTweetButton());
twttr.widgets.load();
};
HTMLActuator.prototype.clearMessage = function () {
// IE only takes one value to remove at a time.
this.messageContainer.classList.remove("game-won");
this.messageContainer.classList.remove("game-over");
};
HTMLActuator.prototype.scoreTweetButton = function () {
var tweet = document.createElement("a");
tweet.classList.add("twitter-share-button");
tweet.setAttribute("href", "https://twitter.com/share");
tweet.setAttribute("data-via", "gabrielecirulli");
tweet.setAttribute("data-url", "http://git.io/2048");
tweet.setAttribute("data-counturl", "http://gabrielecirulli.github.io/2048/");
tweet.textContent = "Tweet";
var text = "I got " + this.score + " points in 20 Euro, a game where you " +
"join numbers to score high! #20eurogame";
tweet.setAttribute("data-text", text);
return tweet;
};

View file

@ -0,0 +1,130 @@
function KeyboardInputManager() {
this.events = {};
if (window.navigator.msPointerEnabled) {
//Internet Explorer 10 style
this.eventTouchstart = "MSPointerDown";
this.eventTouchmove = "MSPointerMove";
this.eventTouchend = "MSPointerUp";
} else {
this.eventTouchstart = "touchstart";
this.eventTouchmove = "touchmove";
this.eventTouchend = "touchend";
}
this.listen();
}
KeyboardInputManager.prototype.on = function (event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
};
KeyboardInputManager.prototype.emit = function (event, data) {
var callbacks = this.events[event];
if (callbacks) {
callbacks.forEach(function (callback) {
callback(data);
});
}
};
KeyboardInputManager.prototype.listen = function () {
var self = this;
var map = {
38: 0, // Up
39: 1, // Right
40: 2, // Down
37: 3, // Left
75: 0, // vim keybindings
76: 1,
74: 2,
72: 3,
87: 0, // W
68: 1, // D
83: 2, // S
65: 3 // A
};
document.addEventListener("keydown", function (event) {
var modifiers = event.altKey || event.ctrlKey || event.metaKey ||
event.shiftKey;
var mapped = map[event.which];
if (!modifiers) {
if (mapped !== undefined) {
event.preventDefault();
self.emit("move", mapped);
}
if (event.which === 32) self.restart.bind(self)(event);
}
});
var retry = document.querySelector(".retry-button");
retry.addEventListener("click", this.restart.bind(this));
retry.addEventListener(this.eventTouchend, this.restart.bind(this));
var keepPlaying = document.querySelector(".keep-playing-button");
keepPlaying.addEventListener("click", this.keepPlaying.bind(this));
keepPlaying.addEventListener("touchend", this.keepPlaying.bind(this));
// Listen to swipe events
var touchStartClientX, touchStartClientY;
var gameContainer = document.getElementsByClassName("game-container")[0];
gameContainer.addEventListener(this.eventTouchstart, function (event) {
if (( !window.navigator.msPointerEnabled && event.touches.length > 1) || event.targetTouches > 1) return;
if(window.navigator.msPointerEnabled){
touchStartClientX = event.pageX;
touchStartClientY = event.pageY;
} else {
touchStartClientX = event.touches[0].clientX;
touchStartClientY = event.touches[0].clientY;
}
event.preventDefault();
});
gameContainer.addEventListener(this.eventTouchmove, function (event) {
event.preventDefault();
});
gameContainer.addEventListener(this.eventTouchend, function (event) {
if (( !window.navigator.msPointerEnabled && event.touches.length > 0) || event.targetTouches > 0) return;
var touchEndClientX, touchEndClientY;
if(window.navigator.msPointerEnabled){
touchEndClientX = event.pageX;
touchEndClientY = event.pageY;
} else {
touchEndClientX = event.changedTouches[0].clientX;
touchEndClientY = event.changedTouches[0].clientY;
}
var dx = touchEndClientX - touchStartClientX;
var absDx = Math.abs(dx);
var dy = touchEndClientY - touchStartClientY;
var absDy = Math.abs(dy);
if (Math.max(absDx, absDy) > 10) {
// (right : left) : (down : up)
self.emit("move", absDx > absDy ? (dx > 0 ? 1 : 3) : (dy > 0 ? 2 : 0));
}
});
};
KeyboardInputManager.prototype.restart = function (event) {
event.preventDefault();
this.emit("restart");
};
KeyboardInputManager.prototype.keepPlaying = function (event) {
event.preventDefault();
this.emit("keepPlaying");
};

View file

@ -0,0 +1,48 @@
window.fakeStorage = {
_data: {},
setItem: function (id, val) {
return this._data[id] = String(val);
},
getItem: function (id) {
return this._data.hasOwnProperty(id) ? this._data[id] : undefined;
},
removeItem: function (id) {
return delete this._data[id];
},
clear: function () {
return this._data = {};
}
};
function LocalScoreManager() {
this.key = "bestScore";
var supported = this.localStorageSupported();
this.storage = supported ? window.localStorage : window.fakeStorage;
}
LocalScoreManager.prototype.localStorageSupported = function () {
var testKey = "test";
var storage = window.localStorage;
try {
storage.setItem(testKey, "1");
storage.removeItem(testKey);
return true;
} catch (error) {
return false;
}
};
LocalScoreManager.prototype.get = function () {
return this.storage.getItem(this.key) || 0;
};
LocalScoreManager.prototype.set = function (score) {
this.storage.setItem(this.key, score);
};

17
sources/js/tile.js Normal file
View file

@ -0,0 +1,17 @@
function Tile(position, value) {
this.x = position.x;
this.y = position.y;
this.value = value || 2;
this.previousPosition = null;
this.mergedFrom = null; // Tracks tiles that merged together
}
Tile.prototype.savePosition = function () {
this.previousPosition = { x: this.x, y: this.y };
};
Tile.prototype.updatePosition = function (position) {
this.x = position.x;
this.y = position.y;
};

122
sources/statistics.html Normal file
View file

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="en" manifest="cache.appcache">
<head>
<meta charset="utf-8">
<title>20 Euros Statistics</title>
<link href="style/main.css" rel="stylesheet" type="text/css">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta property="og:title" content="20euro game"/>
<meta property="og:site_name" content="20euro game"/>
<meta property="og:description" content="Join the coins and get the 20 Euro tile!"/>
<meta property="og:image" content="http://gabrielecirulli.github.io/2048/meta/og_image.png"/>
<script src='https://cdn.firebase.com/js/client/1.0.11/firebase.js'></script>
</head>
<body>
<script language="JavaScript">
var rootRef = new Firebase('https://20-euros.firebaseio.com/');
var highestScoreRef = rootRef.child("highestScore");
var RefPlays = rootRef.child("plays");
var Ref50 = rootRef.child("reached_50c");
var Ref100 = rootRef.child("reached_1e");
var Ref200 = rootRef.child("reached_2e");
var Ref500 = rootRef.child("reached_5e");
var Ref1000 = rootRef.child("reached_10e");
var Ref2000 = rootRef.child("reached_20e");
var Ref5000 = rootRef.child("reached_50e");
var Ref10000 = rootRef.child("reached_100e");
var Ref20000 = rootRef.child("reached_200e");
var Ref50000 = rootRef.child("reached_500e");
highestScoreRef.on('value', function(newHighestScore) {
document.getElementById("highestScoreDiv").innerHTML=newHighestScore.val();
});
RefPlays.on('value', function(newPlays) {
document.getElementById("DivPlays").innerHTML=newPlays.val();
});
Ref50.on('value', function(newPlays) {
document.getElementById("Div50").innerHTML=newPlays.val();
});
Ref100.on('value', function(newPlays) {
document.getElementById("Div100").innerHTML=newPlays.val();
});
Ref200.on('value', function(newPlays) {
document.getElementById("Div200").innerHTML=newPlays.val();
});
Ref500.on('value', function(newPlays) {
document.getElementById("Div500").innerHTML=newPlays.val();
});
Ref1000.on('value', function(newPlays) {
document.getElementById("Div1000").innerHTML=newPlays.val();
});
Ref2000.on('value', function(newPlays) {
document.getElementById("Div2000").innerHTML=newPlays.val();
});
Ref5000.on('value', function(newPlays) {
document.getElementById("Div5000").innerHTML=newPlays.val();
});
Ref10000.on('value', function(newPlays) {
document.getElementById("Div10000").innerHTML=newPlays.val();
});
Ref20000.on('value', function(newPlays) {
document.getElementById("Div20000").innerHTML=newPlays.val();
});
Ref50000.on('value', function(newPlays) {
document.getElementById("Div50000").innerHTML=newPlays.val();
});
</script>
<div class="container">
<div class="heading">
<h1 class="title">Statistics</h1>
</div>
<p class="game-intro">Statistics of my game <a href="http://jatekos101.github.io/20euros">20 Euros</a>.</p>
<hr>
<p>
Statistics since 2014-04-06.
</p>
Out of the <b><span id="DivPlays"></span></b> plays, <br>
<b><span id="Div50"></span></b> reached the 50 cent coin, <br>
<b><span id="Div100"></span></b> reached the 1 euro coin, <br>
<b><span id="Div200"></span></b> reached the 2 euro coin, <br>
<b><span id="Div500"></span></b> reached the 5 euro note, <br>
<b><span id="Div1000"></span></b> reached the 10 euro note, <br>
and <b><span id="Div2000"></span></b> won the game! <br>
</p>
<p>
The highest score achieved was <b><span id="highestScoreDiv"></span></b>.
</p>
</div>
<script type="text/javascript">
var sc_project=9719822;
var sc_invisible=1;
var sc_security="bccc6417";
var scJsHost = (("https:" == document.location.protocol) ?
"https://secure." : "http://www.");
document.write("<sc"+"ript type='text/javascript' src='" +
scJsHost+
"statcounter.com/counter/counter.js'></"+"script>");
</script>
<noscript><div class="statcounter"><a title="web analytics"
href="http://statcounter.com/" target="_blank"><img
class="statcounter"
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
alt="web analytics"></a></div></noscript>
</body>
</html>

50
sources/style/example.css Normal file
View file

@ -0,0 +1,50 @@
/* Global */
#leaderboardTable {
background-color: white;
overflow: auto;
width: 100%;
padding: 10px;
border: 8px solid #424547;
margin-bottom: 5px;
}
#scoreInput {
width: 68%;
}
#highestscore {
margin-top: 20px;
font-size: 14px;
}
/* Presence */
#presenceDiv {
text-align: center;
}
/* Tetris */
.tetris-body {
width: 600px;
}
#canvas0, #canvas1 {
display: inline-block;
border: 4px solid #424547;
}
#restartButton {
margin-top: 5px;
}
#gameInProgress {
font-size: 14px;
}
.hide {
display: none;
}

869
sources/style/main.css Normal file
View file

@ -0,0 +1,869 @@
@import url(fonts/clear-sans.css);
html, body {
margin: 0;
padding: 0;
background: #faf8ef;
color: #776e65;
font-family: "Clear Sans", "Helvetica Neue", Arial, sans-serif;
font-size: 18px; }
body {
margin: 80px 0; }
.heading:after {
content: "";
display: block;
clear: both; }
h1.title {
font-size: 80px;
font-weight: bold;
margin: 0;
display: block;
float: left; }
@-webkit-keyframes move-up {
0% {
top: 25px;
opacity: 1; }
100% {
top: -50px;
opacity: 0; } }
@-moz-keyframes move-up {
0% {
top: 25px;
opacity: 1; }
100% {
top: -50px;
opacity: 0; } }
@keyframes move-up {
0% {
top: 25px;
opacity: 1; }
100% {
top: -50px;
opacity: 0; } }
.scores-container {
float: right;
text-align: right; }
.score-container, .best-container {
position: relative;
display: inline-block;
background: #bbada0;
padding: 15px 25px;
font-size: 25px;
height: 25px;
line-height: 47px;
font-weight: bold;
border-radius: 3px;
color: white;
margin-top: 8px;
text-align: center; }
.score-container:after, .best-container:after {
position: absolute;
width: 100%;
top: 10px;
left: 0;
text-transform: uppercase;
font-size: 13px;
line-height: 13px;
text-align: center;
color: #eee4da; }
.score-container .score-addition, .best-container .score-addition {
position: absolute;
right: 30px;
color: red;
font-size: 25px;
line-height: 25px;
font-weight: bold;
color: rgba(119, 110, 101, 0.9);
z-index: 100;
-webkit-animation: move-up 600ms ease-in;
-moz-animation: move-up 600ms ease-in;
animation: move-up 600ms ease-in;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
animation-fill-mode: both; }
.score-container:after {
content: "Score"; }
.best-container:after {
content: "My best"; }
p {
margin-top: 0;
margin-bottom: 10px;
line-height: 1.65; }
a {
color: #776e65;
font-weight: bold;
text-decoration: underline;
cursor: pointer; }
strong.important {
text-transform: uppercase; }
hr {
border: none;
border-bottom: 1px solid #d8d4d0;
margin-top: 20px;
margin-bottom: 30px; }
.container {
width: 640px;
margin: 0 auto; }
@-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
@-moz-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
@keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
.game-container {
margin-top: 40px;
position: relative;
padding: 15px;
cursor: default;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
background: #bbada0;
border-radius: 6px;
width: 640px;
height: 640px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.game-container .game-message {
display: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(238, 228, 218, 0.5);
z-index: 100;
text-align: center;
-webkit-animation: fade-in 800ms ease 1200ms;
-moz-animation: fade-in 800ms ease 1200ms;
animation: fade-in 800ms ease 1200ms;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
animation-fill-mode: both;
}
.game-container .game-message p {
font-size: 60px;
font-weight: bold;
height: 60px;
line-height: 60px;
margin-top: 222px; }
.game-container .game-message .lower {
display: block;
margin-top: 59px; }
.game-container .game-message a {
display: inline-block;
background: #8f7a66;
border-radius: 3px;
padding: 0 20px;
text-decoration: none;
color: #f9f6f2;
height: 40px;
line-height: 42px;
margin-left: 9px; }
.game-container .game-message a.keep-playing-button {
display: none; }
.game-container .game-message.game-won {
background: rgba(237, 194, 46, 0.5);
color: #f9f6f2; }
.game-container .game-message.game-won a.keep-playing-button {
display: inline-block; }
.game-container .game-message.game-won, .game-container .game-message.game-over {
display: block; }
.grid-container {
position: absolute;
z-index: 1; }
.grid-row {
margin-bottom: 15px; }
.grid-row:last-child {
margin-bottom: 0; }
.grid-row:after {
content: "";
display: block;
clear: both; }
.grid-cell {
width: 110px;
height: 110px;
margin-right: 15px;
float: left;
border-radius: 3px;
background: rgba(238, 228, 218, 0.35); }
.grid-cell:last-child {
margin-right: 0; }
.tile-container {
position: absolute;
z-index: 2; }
.tile, .tile .tile-inner {
width: 110px;
height: 110px;
line-height: 116.25px; }
.tile.tile-position-1-1 {
-webkit-transform: translate(0px, 0px);
-moz-transform: translate(0px, 0px);
transform: translate(0px, 0px); }
.tile.tile-position-1-2 {
-webkit-transform: translate(0px, 125px);
-moz-transform: translate(0px, 125px);
transform: translate(0px, 125px); }
.tile.tile-position-1-3 {
-webkit-transform: translate(0px, 250px);
-moz-transform: translate(0px, 250px);
transform: translate(0px, 250px); }
.tile.tile-position-1-4 {
-webkit-transform: translate(0px, 375px);
-moz-transform: translate(0px, 375px);
transform: translate(0px, 375px); }
.tile.tile-position-1-5 {
-webkit-transform: translate(0px, 500px);
-moz-transform: translate(0px, 500px);
transform: translate(0px, 500px); }
.tile.tile-position-2-1 {
-webkit-transform: translate(125px, 0px);
-moz-transform: translate(125px, 0px);
transform: translate(125px, 0px); }
.tile.tile-position-2-2 {
-webkit-transform: translate(125px, 125px);
-moz-transform: translate(125px, 125px);
transform: translate(125px, 125px); }
.tile.tile-position-2-3 {
-webkit-transform: translate(125px, 250px);
-moz-transform: translate(125px, 250px);
transform: translate(125px, 250px); }
.tile.tile-position-2-4 {
-webkit-transform: translate(125px, 375px);
-moz-transform: translate(125px, 375px);
transform: translate(125px, 375px); }
.tile.tile-position-2-5 {
-webkit-transform: translate(125px, 500px);
-moz-transform: translate(125px, 500px);
transform: translate(125px, 500px); }
.tile.tile-position-3-1 {
-webkit-transform: translate(250px, 0px);
-moz-transform: translate(250px, 0px);
transform: translate(250px, 0px); }
.tile.tile-position-3-2 {
-webkit-transform: translate(250px, 125px);
-moz-transform: translate(250px, 125px);
transform: translate(250px, 125px); }
.tile.tile-position-3-3 {
-webkit-transform: translate(250px, 250px);
-moz-transform: translate(250px, 250px);
transform: translate(250px, 250px); }
.tile.tile-position-3-4 {
-webkit-transform: translate(250px, 375px);
-moz-transform: translate(250px, 375px);
transform: translate(250px, 375px); }
.tile.tile-position-3-5 {
-webkit-transform: translate(250px, 500px);
-moz-transform: translate(250px, 500x);
transform: translate(250px, 500px); }
.tile.tile-position-4-1 {
-webkit-transform: translate(375px, 0px);
-moz-transform: translate(375px, 0px);
transform: translate(375px, 0px); }
.tile.tile-position-4-2 {
-webkit-transform: translate(375px, 125px);
-moz-transform: translate(375px, 125px);
transform: translate(375px, 125px); }
.tile.tile-position-4-3 {
-webkit-transform: translate(375px, 250px);
-moz-transform: translate(375px, 250px);
transform: translate(375px, 250px); }
.tile.tile-position-4-4 {
-webkit-transform: translate(375px, 375px);
-moz-transform: translate(375px, 375px);
transform: translate(375px, 375px); }
.tile.tile-position-4-5 {
-webkit-transform: translate(375px, 500px);
-moz-transform: translate(375px, 500px);
transform: translate(375px, 500px); }
.tile.tile-position-5-1 {
-webkit-transform: translate(500px, 0px);
-moz-transform: translate(500px, 0px);
transform: translate(500px, 0px); }
.tile.tile-position-5-2 {
-webkit-transform: translate(500px, 125px);
-moz-transform: translate(500px, 125px);
transform: translate(500px, 125px); }
.tile.tile-position-5-3 {
-webkit-transform: translate(500px, 250px);
-moz-transform: translate(500px, 250px);
transform: translate(500px, 250px); }
.tile.tile-position-5-4 {
-webkit-transform: translate(500px, 375px);
-moz-transform: translate(500px, 375px);
transform: translate(500px, 375px); }
.tile.tile-position-5-5 {
-webkit-transform: translate(500px, 500px);
-moz-transform: translate(500px, 500px);
transform: translate(500px, 500px); }
.tile {
position: absolute;
-webkit-transition: 100ms ease-in-out;
-moz-transition: 100ms ease-in-out;
transition: 100ms ease-in-out;
-webkit-transition-property: -webkit-transform;
-moz-transition-property: -moz-transform;
transition-property: transform; }
.tile .tile-inner {
border-radius: 3px;
background: #eee4da;
text-align: center;
font-weight: bold;
z-index: 10;
font-size: 0px; }
.tile.tile-1 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_1cent.gif');
background-size: cover;
box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
.tile.tile-2 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_2cent.gif');
background-size: cover;
box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
.tile.tile-5 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_5cent.gif');
background-size: cover;
box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
.tile.tile-10 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_10cent.gif');
background-size: cover;}
.tile.tile-20 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_20cent.gif');
background-size: cover;}
.tile.tile-50 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_50cent.gif');
background-size: cover;}
.tile.tile-100 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_1euro.gif');
background-size: cover;}
.tile.tile-200 .tile-inner {
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_2euro.gif');
background-size: cover;
}
.tile.tile-500 .tile-inner {
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/5%20Euro%202002%20-%20F.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-1000 .tile-inner {
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/10%20Euro%202002%20-%20F.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-2000 .tile-inner {
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/20%20Euro%202002%20-%20F.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-5000 .tile-inner {
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/50%20Euro%202002%20-%20F.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-10000 .tile-inner {
background: #ffffff url('http://www.blogger42.com/wp-content/uploads/100euro.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-20000 .tile-inner {
background: #ffffff url('http://www.blogger42.com/wp-content/uploads/e.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-50000 .tile-inner {
background: #ffffff url('http://www.rivistastudio.com/wp-content/uploads/2014/03/500euro.jpg');
background-size: contain; background-repeat: no-repeat;}
.tile.tile-super .tile-inner {
background: #ffffff url('http://upload.wikimedia.org/wikipedia/commons/c/c3/Euro_symbol_gold.svg');
background-size: cover;
font-size: 30px; }
@media screen and (max-width: 520px) {
.tile.tile-super .tile-inner {
font-size: 10px; } }
@-webkit-keyframes appear {
0% {
opacity: 0;
-webkit-transform: scale(0);
-moz-transform: scale(0);
transform: scale(0); }
100% {
opacity: 1;
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1); } }
@-moz-keyframes appear {
0% {
opacity: 0;
-webkit-transform: scale(0);
-moz-transform: scale(0);
transform: scale(0); }
100% {
opacity: 1;
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1); } }
@keyframes appear {
0% {
opacity: 0;
-webkit-transform: scale(0);
-moz-transform: scale(0);
transform: scale(0); }
100% {
opacity: 1;
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1); } }
.tile-new .tile-inner {
-webkit-animation: appear 200ms ease 100ms;
-moz-animation: appear 200ms ease 100ms;
animation: appear 200ms ease 100ms;
-webkit-animation-fill-mode: backwards;
-moz-animation-fill-mode: backwards;
animation-fill-mode: backwards; }
@-webkit-keyframes pop {
0% {
-webkit-transform: scale(0);
-moz-transform: scale(0);
transform: scale(0); }
50% {
-webkit-transform: scale(1.2);
-moz-transform: scale(1.2);
transform: scale(1.2); }
100% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1); } }
@-moz-keyframes pop {
0% {
-webkit-transform: scale(0);
-moz-transform: scale(0);
transform: scale(0); }
50% {
-webkit-transform: scale(1.2);
-moz-transform: scale(1.2);
transform: scale(1.2); }
100% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1); } }
@keyframes pop {
0% {
-webkit-transform: scale(0);
-moz-transform: scale(0);
transform: scale(0); }
50% {
-webkit-transform: scale(1.2);
-moz-transform: scale(1.2);
transform: scale(1.2); }
100% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1); } }
.tile-merged .tile-inner {
z-index: 20;
-webkit-animation: pop 200ms ease 100ms;
-moz-animation: pop 200ms ease 100ms;
animation: pop 200ms ease 100ms;
-webkit-animation-fill-mode: backwards;
-moz-animation-fill-mode: backwards;
animation-fill-mode: backwards; }
.game-intro {
margin-bottom: 0; }
.game-explanation {
margin-top: 50px; }
.sharing {
margin-top: 20px;
text-align: center; }
.sharing > iframe, .sharing > span, .sharing > form {
display: inline-block;
vertical-align: middle; }
@media screen and (max-width: 520px) {
html, body {
font-size: 15px; }
body {
margin: 20px 0;
padding: 0 20px; }
h1.title {
font-size: 27px;
margin-top: 15px; }
.container {
width: 280px;
margin: 0 auto; }
.score-container, .best-container {
margin-top: 0;
padding: 15px 10px;
min-width: 40px; }
.heading {
margin-bottom: 10px; }
.game-container {
margin-top: 40px;
position: relative;
padding: 10px;
cursor: default;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
background: #bbada0;
border-radius: 6px;
width: 280px;
height: 280px;
-ms-touch-action: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.game-container .game-message {
display: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(238, 228, 218, 0.5);
z-index: 100;
text-align: center;
-webkit-animation: fade-in 800ms ease 1200ms;
-moz-animation: fade-in 800ms ease 1200ms;
animation: fade-in 800ms ease 1200ms;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
animation-fill-mode: both; }
.game-container .game-message p {
font-size: 60px;
font-weight: bold;
height: 60px;
line-height: 60px;
margin-top: 222px; }
.game-container .game-message .lower {
display: block;
margin-top: 59px; }
.game-container .game-message a {
display: inline-block;
background: #8f7a66;
border-radius: 3px;
padding: 0 20px;
text-decoration: none;
color: #f9f6f2;
height: 40px;
line-height: 42px;
margin-left: 9px; }
.game-container .game-message a.keep-playing-button {
display: none; }
.game-container .game-message .score-sharing {
display: inline-block;
vertical-align: middle;
margin-left: 10px; }
.game-container .game-message.game-won {
background: rgba(237, 194, 46, 0.5);
color: #f9f6f2; }
.game-container .game-message.game-won a.keep-playing-button {
display: inline-block; }
.game-container .game-message.game-won, .game-container .game-message.game-over {
display: block; }
.grid-container {
position: absolute;
z-index: 1; }
.grid-row {
margin-bottom: 10px; }
.grid-row:last-child {
margin-bottom: 0; }
.grid-row:after {
content: "";
display: block;
clear: both; }
.grid-cell {
width: 57.5px;
height: 57.5px;
margin-right: 10px;
float: left;
border-radius: 3px;
background: rgba(238, 228, 218, 0.35); }
.grid-cell:last-child {
margin-right: 0; }
.tile-container {
position: absolute;
z-index: 2; }
.tile, .tile .tile-inner {
width: 58px;
height: 58px;
line-height: 67.5px; }
.tile.tile-position-1-1 {
-webkit-transform: translate(0px, 0px);
-moz-transform: translate(0px, 0px);
transform: translate(0px, 0px); }
.tile.tile-position-1-2 {
-webkit-transform: translate(0px, 67px);
-moz-transform: translate(0px, 67px);
transform: translate(0px, 67px); }
.tile.tile-position-1-3 {
-webkit-transform: translate(0px, 135px);
-moz-transform: translate(0px, 135px);
transform: translate(0px, 135px); }
.tile.tile-position-1-4 {
-webkit-transform: translate(0px, 202px);
-moz-transform: translate(0px, 202px);
transform: translate(0px, 202px); }
.tile.tile-position-2-1 {
-webkit-transform: translate(67px, 0px);
-moz-transform: translate(67px, 0px);
transform: translate(67px, 0px); }
.tile.tile-position-2-2 {
-webkit-transform: translate(67px, 67px);
-moz-transform: translate(67px, 67px);
transform: translate(67px, 67px); }
.tile.tile-position-2-3 {
-webkit-transform: translate(67px, 135px);
-moz-transform: translate(67px, 135px);
transform: translate(67px, 135px); }
.tile.tile-position-2-4 {
-webkit-transform: translate(67px, 202px);
-moz-transform: translate(67px, 202px);
transform: translate(67px, 202px); }
.tile.tile-position-3-1 {
-webkit-transform: translate(135px, 0px);
-moz-transform: translate(135px, 0px);
transform: translate(135px, 0px); }
.tile.tile-position-3-2 {
-webkit-transform: translate(135px, 67px);
-moz-transform: translate(135px, 67px);
transform: translate(135px, 67px); }
.tile.tile-position-3-3 {
-webkit-transform: translate(135px, 135px);
-moz-transform: translate(135px, 135px);
transform: translate(135px, 135px); }
.tile.tile-position-3-4 {
-webkit-transform: translate(135px, 202px);
-moz-transform: translate(135px, 202px);
transform: translate(135px, 202px); }
.tile.tile-position-4-1 {
-webkit-transform: translate(202px, 0px);
-moz-transform: translate(202px, 0px);
transform: translate(202px, 0px); }
.tile.tile-position-4-2 {
-webkit-transform: translate(202px, 67px);
-moz-transform: translate(202px, 67px);
transform: translate(202px, 67px); }
.tile.tile-position-4-3 {
-webkit-transform: translate(202px, 135px);
-moz-transform: translate(202px, 135px);
transform: translate(202px, 135px); }
.tile.tile-position-4-4 {
-webkit-transform: translate(202px, 202px);
-moz-transform: translate(202px, 202px);
transform: translate(202px, 202px); }
.game-container {
margin-top: 20px; }
.tile .tile-inner {
font-size: 35px; }
.game-message p {
font-size: 30px !important;
height: 30px !important;
line-height: 30px !important;
margin-top: 90px !important; }
.game-message .lower {
margin-top: 30px !important; }
.sharing > iframe, .sharing > span, .sharing > form {
display: block;
margin: 0 auto;
margin-bottom: 20px; } }
.pp-donate button {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
font: inherit;
color: inherit;
cursor: pointer;
display: inline-block;
background: #8f7a66;
border-radius: 3px;
padding: 0 20px;
text-decoration: none;
color: #f9f6f2;
height: 40px;
line-height: 42px; }
.pp-donate button img {
vertical-align: -4px;
margin-right: 8px; }
.btc-donate {
position: relative;
margin-left: 10px;
display: inline-block;
background: #8f7a66;
border-radius: 3px;
padding: 0 20px;
text-decoration: none;
color: #f9f6f2;
height: 40px;
line-height: 42px;
cursor: pointer; }
.btc-donate img {
vertical-align: -4px;
margin-right: 8px; }
.btc-donate a {
color: #f9f6f2;
text-decoration: none;
font-weight: normal; }
.btc-donate .address {
cursor: auto;
position: absolute;
width: 340px;
right: 50%;
margin-right: -170px;
padding-bottom: 7px;
top: -30px;
opacity: 0;
pointer-events: none;
-webkit-transition: 400ms ease;
-moz-transition: 400ms ease;
transition: 400ms ease;
-webkit-transition-property: top, opacity;
-moz-transition-property: top, opacity;
transition-property: top, opacity; }
.btc-donate .address:after {
position: absolute;
border-top: 10px solid #bbada0;
border-right: 7px solid transparent;
border-left: 7px solid transparent;
content: "";
bottom: 0px;
left: 50%;
margin-left: -7px; }
.btc-donate .address code {
background-color: #bbada0;
padding: 10px 15px;
width: 100%;
border-radius: 3px;
line-height: 1;
font-weight: normal;
font-size: 15px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
text-align: center; }
.btc-donate:hover .address, .btc-donate .address:hover .address {
opacity: 1;
top: -45px;
pointer-events: auto; }
@media screen and (max-width: 480px) {
.btc-donate {
width: 120px; }
.btc-donate .address {
margin-right: -150px;
width: 300px; }
.btc-donate .address code {
font-size: 13px; }
.btc-donate .address:after {
left: 50%;
bottom: 2px; } }

View file

@ -0,0 +1,70 @@
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f0f3f3; }
.highlight .c { color: #0099FF; font-style: italic } /* Comment */
.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */
.highlight .k { color: #006699; font-weight: bold } /* Keyword */
.highlight .o { color: #555555 } /* Operator */
.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #009999 } /* Comment.Preproc */
.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */
.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */
.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
.highlight .go { color: #AAAAAA } /* Generic.Output */
.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #99CC66 } /* Generic.Traceback */
.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #006699 } /* Keyword.Pseudo */
.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #FF6600 } /* Literal.Number */
.highlight .s { color: #CC3300 } /* Literal.String */
.highlight .na { color: #330099 } /* Name.Attribute */
.highlight .nb { color: #336666 } /* Name.Builtin */
.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */
.highlight .no { color: #336600 } /* Name.Constant */
.highlight .nd { color: #9999FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #CC00FF } /* Name.Function */
.highlight .nl { color: #9999FF } /* Name.Label */
.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #003333 } /* Name.Variable */
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #FF6600 } /* Literal.Number.Float */
.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */
.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */
.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */
.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */
.highlight .sc { color: #CC3300 } /* Literal.String.Char */
.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #CC3300 } /* Literal.String.Double */
.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */
.highlight .si { color: #AA0000 } /* Literal.String.Interpol */
.highlight .sx { color: #CC3300 } /* Literal.String.Other */
.highlight .sr { color: #33AAAA } /* Literal.String.Regex */
.highlight .s1 { color: #CC3300 } /* Literal.String.Single */
.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */
.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #003333 } /* Name.Variable.Class */
.highlight .vg { color: #003333 } /* Name.Variable.Global */
.highlight .vi { color: #003333 } /* Name.Variable.Instance */
.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */
.type-csharp .highlight .k { color: #0000FF }
.type-csharp .highlight .kt { color: #0000FF }
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
.type-csharp .highlight .nc { color: #2B91AF }
.type-csharp .highlight .nn { color: #000000 }
.type-csharp .highlight .s { color: #A31515 }
.type-csharp .highlight .sc { color: #A31515 }

View file

@ -0,0 +1,423 @@
/*******************************************************************************
Slate Theme for GitHub Pages
by Jason Costello, @jsncostello
*******************************************************************************/
@import url(pygment_trac.css);
/*******************************************************************************
MeyerWeb Reset
*******************************************************************************/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
ol, ul {
list-style: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/*******************************************************************************
Theme Styles
*******************************************************************************/
body {
box-sizing: border-box;
color:#373737;
background: #212121;
font-size: 16px;
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6 {
margin: 10px 0;
font-weight: 700;
color:#222222;
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
letter-spacing: -1px;
}
h1 {
font-size: 36px;
font-weight: 700;
}
h2 {
padding-bottom: 10px;
font-size: 32px;
background: url('../images/bg_hr.png') repeat-x bottom;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 21px;
}
h5 {
font-size: 18px;
}
h6 {
font-size: 16px;
}
p {
margin: 10px 0 15px 0;
}
footer p {
color: #f2f2f2;
}
a {
text-decoration: none;
color: #007edf;
text-shadow: none;
transition: color 0.5s ease;
transition: text-shadow 0.5s ease;
-webkit-transition: color 0.5s ease;
-webkit-transition: text-shadow 0.5s ease;
-moz-transition: color 0.5s ease;
-moz-transition: text-shadow 0.5s ease;
-o-transition: color 0.5s ease;
-o-transition: text-shadow 0.5s ease;
-ms-transition: color 0.5s ease;
-ms-transition: text-shadow 0.5s ease;
}
a:hover, a:focus {text-decoration: underline;}
footer a {
color: #F2F2F2;
text-decoration: underline;
}
em {
font-style: italic;
}
strong {
font-weight: bold;
}
img {
position: relative;
margin: 0 auto;
max-width: 739px;
padding: 5px;
margin: 10px 0 10px 0;
border: 1px solid #ebebeb;
box-shadow: 0 0 5px #ebebeb;
-webkit-box-shadow: 0 0 5px #ebebeb;
-moz-box-shadow: 0 0 5px #ebebeb;
-o-box-shadow: 0 0 5px #ebebeb;
-ms-box-shadow: 0 0 5px #ebebeb;
}
p img {
display: inline;
margin: 0;
padding: 0;
vertical-align: middle;
text-align: center;
border: none;
}
pre, code {
width: 100%;
color: #222;
background-color: #fff;
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
font-size: 14px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
pre {
width: 100%;
padding: 10px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
overflow: auto;
}
code {
padding: 3px;
margin: 0 3px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
pre code {
display: block;
box-shadow: none;
}
blockquote {
color: #666;
margin-bottom: 20px;
padding: 0 0 0 20px;
border-left: 3px solid #bbb;
}
ul, ol, dl {
margin-bottom: 15px
}
ul {
list-style: inside;
padding-left: 20px;
}
ol {
list-style: decimal inside;
padding-left: 20px;
}
dl dt {
font-weight: bold;
}
dl dd {
padding-left: 20px;
font-style: italic;
}
dl p {
padding-left: 20px;
font-style: italic;
}
hr {
height: 1px;
margin-bottom: 5px;
border: none;
background: url('../images/bg_hr.png') repeat-x center;
}
table {
border: 1px solid #373737;
margin-bottom: 20px;
text-align: left;
}
th {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 10px;
background: #373737;
color: #fff;
}
td {
padding: 10px;
border: 1px solid #373737;
}
form {
background: #f2f2f2;
padding: 20px;
}
/*******************************************************************************
Full-Width Styles
*******************************************************************************/
.outer {
width: 100%;
}
.inner {
position: relative;
max-width: 640px;
padding: 20px 10px;
margin: 0 auto;
}
#forkme_banner {
display: block;
position: absolute;
top:0;
right: 10px;
z-index: 10;
padding: 10px 50px 10px 10px;
color: #fff;
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0,0,0,.5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
#header_wrap {
background: #212121;
background: -moz-linear-gradient(top, #373737, #212121);
background: -webkit-linear-gradient(top, #373737, #212121);
background: -ms-linear-gradient(top, #373737, #212121);
background: -o-linear-gradient(top, #373737, #212121);
background: linear-gradient(top, #373737, #212121);
}
#header_wrap .inner {
padding: 50px 10px 30px 10px;
}
#project_title {
margin: 0;
color: #fff;
font-size: 42px;
font-weight: 700;
text-shadow: #111 0px 0px 10px;
}
#project_tagline {
color: #fff;
font-size: 24px;
font-weight: 300;
background: none;
text-shadow: #111 0px 0px 10px;
}
#downloads {
position: absolute;
width: 210px;
z-index: 10;
bottom: -40px;
right: 0;
height: 70px;
background: url('../images/icon_download.png') no-repeat 0% 90%;
}
.zip_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom left;
}
.tar_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom right;
margin-left: 10px;
}
.zip_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top left;
}
.tar_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top right;
}
#main_content_wrap {
background: #f2f2f2;
border-top: 1px solid #111;
border-bottom: 1px solid #111;
}
#main_content {
padding-top: 40px;
}
#footer_wrap {
background: #212121;
}
/*******************************************************************************
Small Device Styles
*******************************************************************************/
@media screen and (max-width: 480px) {
body {
font-size:14px;
}
#downloads {
display: none;
}
.inner {
min-width: 320px;
max-width: 480px;
}
#project_title {
font-size: 32px;
}
h1 {
font-size: 28px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 21px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 12px;
}
code, pre {
min-width: 320px;
max-width: 480px;
font-size: 11px;
}
}