add other pati.to services, upgrade gts
8
.gitignore
vendored
@ -1,3 +1,7 @@
|
||||
.terraform.lock.hcl
|
||||
private/*
|
||||
dist/*
|
||||
node_modules
|
||||
.terraform
|
||||
*.vars
|
||||
.terraform.lock.hcl
|
||||
*.tfstate
|
||||
.jekyll-cache/*
|
||||
|
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# pati.to
|
||||
|
||||
The best domain name on the whole internet.
|
2
services/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.terraform
|
||||
.terraform.lock.hcl
|
2
services/.joao.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
vault: nidito
|
||||
nameTemplate: pati.to:{{ DirName }}
|
@ -1,12 +1,8 @@
|
||||
_config: !!joao
|
||||
vault: nidito
|
||||
name: pati.to:club
|
||||
smtp:
|
||||
host: smtp.mailgun.org
|
||||
port: 587
|
||||
username: no-reply@mail.club.pati.to
|
||||
password: !!secret
|
||||
do_token: !!secret
|
||||
cdn:
|
||||
bucket: club-patito
|
||||
endpoint: sjc1.vultrobjects.com
|
@ -1,6 +1,3 @@
|
||||
_config: !!joao
|
||||
vault: none
|
||||
name: none
|
||||
description: activitypub server
|
||||
docs:
|
||||
- https://docs.gotosocial.org/en/latest/
|
||||
@ -9,7 +6,7 @@ packages:
|
||||
self:
|
||||
image: superseriousbusiness/gotosocial
|
||||
source: https://github.com/superseriousbusiness/gotosocial
|
||||
version: "0.15.0"
|
||||
version: "0.17.3"
|
||||
check: github-releases
|
||||
comparison: suffix
|
||||
litestream:
|
@ -4,11 +4,6 @@ terraform {
|
||||
}
|
||||
|
||||
required_providers {
|
||||
acme = {
|
||||
source = "vancluever/acme"
|
||||
version = "~> 2.15.1"
|
||||
}
|
||||
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.29.0"
|
||||
@ -39,10 +34,6 @@ locals {
|
||||
}
|
||||
}
|
||||
|
||||
provider "acme" {
|
||||
server_url = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
// DO tokens for compute resources
|
||||
data "vault_generic_secret" "DO" {
|
||||
path = "cfg/infra/tree/provider:digitalocean"
|
6
services/cnriv/cnriv.spec.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
description: Comisión nacional para el reconocimiento de imbéciles al volante
|
||||
packages: {}
|
||||
build: echo "build tbd"
|
||||
deploy:
|
||||
credentials: vault://nidito/deploy/cnriv.pati.to
|
||||
src: ./src
|
73
services/cnriv/cnriv.tf
Normal file
@ -0,0 +1,73 @@
|
||||
terraform {
|
||||
backend "consul" {
|
||||
path = "nidito/state/service/cnriv.pati.to"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
consul = {
|
||||
source = "hashicorp/consul"
|
||||
version = "~> 2.21.0"
|
||||
}
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.4.0"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.29.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.0.0"
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "DO" {
|
||||
path = "cfg/infra/tree/provider:digitalocean"
|
||||
}
|
||||
|
||||
provider "digitalocean" {
|
||||
token = data.vault_generic_secret.DO.data.patito
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "backblaze" {
|
||||
path = "cfg/infra/tree/provider:backblaze"
|
||||
}
|
||||
|
||||
data "terraform_remote_state" "rob_mx" {
|
||||
backend = "consul"
|
||||
workspace = "default"
|
||||
config = {
|
||||
datacenter = "casa"
|
||||
path = "nidito/state/rob.mx"
|
||||
}
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "to_pati_club" {
|
||||
domain = "pati.to"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
name = "cnriv"
|
||||
value = data.terraform_remote_state.rob_mx.outputs.bernal.ip
|
||||
}
|
||||
|
||||
resource "consul_keys" "cdn-config" {
|
||||
datacenter = "qro0"
|
||||
key {
|
||||
path = "cdn/cnriv.pati.to"
|
||||
value = jsonencode({
|
||||
cert = "pati.to"
|
||||
folder = "cnriv.pati.to"
|
||||
nginx_config = file("${abspath(path.root)}/nginx.conf")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_kv_secret" "deploy-config" {
|
||||
path = "nidito/deploy/cnriv.pati.to"
|
||||
data_json = jsonencode({
|
||||
type = "ssh"
|
||||
host = "bernal"
|
||||
domain = "cnriv.pati.to"
|
||||
})
|
||||
}
|
||||
|
3
services/cnriv/nginx.conf
Normal file
@ -0,0 +1,3 @@
|
||||
location / {
|
||||
index index.html;
|
||||
}
|
178
services/cnriv/src/css/main.css
Normal file
@ -0,0 +1,178 @@
|
||||
body {
|
||||
font: 16px/1em Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#main {
|
||||
max-width: 900px;
|
||||
padding: 20px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#principal {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#logo {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0;
|
||||
font-size: 18px;
|
||||
font-family: 'georgia';
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
.dl {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dl img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
#stickers {
|
||||
background: #e25826;
|
||||
}
|
||||
|
||||
#stickers img {
|
||||
border: 10px solid #eee;
|
||||
box-shadow: 0px 0px 5px rgba(0,0,0,.5);
|
||||
-webkit-transform: rotate(-5deg);
|
||||
}
|
||||
|
||||
#stencil {
|
||||
background: url(../img/bg-stencil.jpg);
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: block;
|
||||
background: #999;
|
||||
border-radius:5px;
|
||||
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
|
||||
-border: 1px solid #000;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
|
||||
color: #ddd;
|
||||
cursor: pointer;
|
||||
|
||||
display: block;
|
||||
line-height: 1.714285714;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 #333;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#33000000', EndColorStr='#00000000'), glow(color=black,strength=2);
|
||||
|
||||
background-image: linear-gradient(bottom, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.0) 100%);
|
||||
background-image: -o-linear-gradient(bottom, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.0) 100%);
|
||||
background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.0) 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,.2) 0%, rgba(0,0,0,0.0) 100%);
|
||||
background-image: -ms-linear-gradient(bottom, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.0) 100%);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#33000000', EndColorStr='#00000000')";
|
||||
|
||||
-webkit-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .5),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
0 1px 3px rgba(0,0,0, 0.1);
|
||||
-moz-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .5),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
0 1px 3px rgba(0,0,0, 0.1);
|
||||
-ms-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .5),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
0 1px 3px rgba(0,0,0, 0.1);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .5),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
inset 0 0 2px rgba(0,0,0,.4),
|
||||
0 1px 3px rgba(0,0,0, 0.5);
|
||||
-webkit-transition: all 0.2s ease-in;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: #fff;
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.button:active {
|
||||
background-image: linear-gradient(bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.2) 100%);
|
||||
background-image: -o-linear-gradient(bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.2) 100%);
|
||||
background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.2) 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.2) 100%);
|
||||
background-image: -ms-linear-gradient(bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.2) 100%);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#bbbbbb')";
|
||||
|
||||
-webkit-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .2),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
inset 0 1px 3px rgba(0,0,0, 0.4);
|
||||
-moz-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .2),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
inset 0 1px 3px rgba(0,0,0, 0.4);
|
||||
-ms-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .2),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
inset 0 1px 3px rgba(0,0,0, 0.4);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, .2),
|
||||
inset 0 -2px 8px rgba(0,0,0, 0.1),
|
||||
inset 0 1px 3px rgba(0,0,0, 0.4);
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
background: #333;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
border-top: 1px solid #555;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
@media (max-width:600px) {
|
||||
#main {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
#main section {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#stickers img {
|
||||
border: 10px solid #eee;
|
||||
box-shadow: 0px 0px 5px rgba(0,0,0,.5);
|
||||
width: 80%;
|
||||
-webkit-transform: rotate(-5deg);
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
109
services/cnriv/src/css/reset.css
Normal file
@ -0,0 +1,109 @@
|
||||
html, body, div, span, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
abbr, address, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, samp,
|
||||
small, strong, sub, sup, var,
|
||||
b, i,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:0;
|
||||
outline:0;
|
||||
font-size:100%;
|
||||
vertical-align:baseline;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height:1;
|
||||
}
|
||||
|
||||
article,aside,details,figcaption,figure,
|
||||
footer,header,hgroup,menu,nav,section,
|
||||
div,h1,h2,h3,h4,h5,h6,p,blockquote,pre {
|
||||
display:block;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style:none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes:none;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content:'';
|
||||
content:none;
|
||||
}
|
||||
|
||||
a {
|
||||
margin:0;
|
||||
padding:0;
|
||||
font-size:100%;
|
||||
vertical-align:baseline;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
/* change colours to suit your needs */
|
||||
ins {
|
||||
background-color:#ff9;
|
||||
color:#000;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
/* change colours to suit your needs */
|
||||
mark {
|
||||
background-color:#ff9;
|
||||
color:#000;
|
||||
font-style:italic;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
abbr[title], dfn[title] {
|
||||
border-bottom:1px dotted;
|
||||
cursor:help;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse:collapse;
|
||||
border-spacing:0;
|
||||
}
|
||||
|
||||
/* change border colour to suit your needs */
|
||||
hr {
|
||||
display:block;
|
||||
height:1px;
|
||||
border:0;
|
||||
border-top:1px solid #cccccc;
|
||||
margin:1em 0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
input, select {
|
||||
vertical-align:middle;
|
||||
}
|
||||
:focus {
|
||||
outline: none;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
.clear { clear: both; float: none; }
|
||||
.clearfix::after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
1303
services/cnriv/src/etiquetas.pdf
Normal file
BIN
services/cnriv/src/img/bg-stencil.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
services/cnriv/src/img/etiqueta.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
services/cnriv/src/img/logo.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
services/cnriv/src/img/og-icon.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
services/cnriv/src/img/stencil.png
Normal file
After Width: | Height: | Size: 50 KiB |
61
services/cnriv/src/index.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width" />
|
||||
<title>Campaña Nacional para el Reconocimiento de Imbéciles al Volante</title>
|
||||
|
||||
<meta property="og:description" content="Súmate la campaña de reconocimiento de imbéciles al volante!" />
|
||||
<meta property="og:title" content="Campaña Nacional para el Reconocimiento de Imbéciles al Volante" />
|
||||
<meta property="fb:admins" content="792675081" />
|
||||
<meta property="og:image" content="http://cnriv.pati.to/img/og-icon.png" />
|
||||
<meta property="og:url" content="http://cnriv.pati.to" />
|
||||
<meta itemprop="name" content="Campaña Nacional para el Reconocimiento de Imbéciles al Volante" />
|
||||
<meta itemprop="description" content="Súmate la campaña de reconocimiento de imbéciles al volante!" />
|
||||
<meta itemprop="image" content="http://cnriv.pati.to/img/og-icon.png" />
|
||||
|
||||
<link rel="stylesheet" href="./css/reset.css" />
|
||||
<link rel="stylesheet" href="./css/main.css" />
|
||||
<link rel="shortcut icon" href="./favicon.png" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<section id="principal">
|
||||
<div id="logo">
|
||||
<img src="img/logo.png" width="100%" alt="Campaña Nacional para el Reconocimiento de Imbéciles al Volante"/>
|
||||
</div>
|
||||
<p>Se nos cierran a diario, tocan el claxon como maniáticos, se estacionan ejemplificando los daños de una lobotomía e ignoran al resto de los seres que no conducen toneladas de acero por las calles de tu ciudad.</p>
|
||||
<p>Es nuestro deber civil reconocerlos por sus acciones, súmate a la campaña descargando los stickers y el stencil, y comienza a reconocer la descerebrada labor del imbécil al volante que tienes en tu vida.</p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<section id="stickers" class="dl clearfix">
|
||||
<img src="img/etiqueta.png" alt="descarga las etiquetas" />
|
||||
<a href="etiquetas.pdf" class="button">Descarga los stickers</a>
|
||||
</section>
|
||||
|
||||
<section id="stencil" class="dl clearfix">
|
||||
<img src="img/stencil.png" alt="descarga el stencil" />
|
||||
<a href="stencil.pdf" class="button">Descarga el stencil</a>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<a href="http://rob.mx">Cortesía de un Rob</a>
|
||||
</footer>
|
||||
|
||||
<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-37922009-2', 'cnriv.pati.to');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
754
services/cnriv/src/stencil.pdf
Normal file
107
services/fichitas/compile.rb
Executable file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'sass'
|
||||
require 'sprockets'
|
||||
require 'listen'
|
||||
|
||||
absPath = File.expand_path File.dirname(__FILE__)
|
||||
$root = "#{absPath}/assets/src"
|
||||
$dst = "#{absPath}/assets"
|
||||
$sprockets = Sprockets::Environment.new($root)
|
||||
$sprockets.append_path("#{$root}/scripts")
|
||||
$sprockets.append_path("#{$root}/scss")
|
||||
$sprockets.css_compressor = :scss
|
||||
|
||||
def type path
|
||||
return :js if path =~ /(js|coffee)/
|
||||
return :css
|
||||
end
|
||||
|
||||
def pathFor str
|
||||
folder = type(str) == :js ? 'scripts' : 'css';
|
||||
return str.gsub("#{$root}/#{folder}/", '')
|
||||
end
|
||||
|
||||
#str = '/Users/rob/Sites/fichitas/assets/src/scss/_buttons.scss'
|
||||
|
||||
#p pathFor str
|
||||
#assets = $sprockets.find_asset(pathFor str)
|
||||
#puts "#{$dst}/#{type str}/"
|
||||
#p assets
|
||||
#File.open("")
|
||||
#assets.write_to "#{$dst}/#{type str}/"
|
||||
#=begin
|
||||
begin
|
||||
listener = Listen.to("#{$root}", debug: true) do |mod, add, del|
|
||||
del.each do |d|
|
||||
File.unlink "#{$dst}/#{type del}/#{pathFor del}"
|
||||
end
|
||||
|
||||
mod.each do |f|
|
||||
folder = type f
|
||||
err = nil
|
||||
if folder==:js
|
||||
dest = "#{$dst}/js/main.js"
|
||||
begin
|
||||
asset = $sprockets.find_asset("main.coffee")
|
||||
rescue Exception => e
|
||||
err = e
|
||||
end
|
||||
else
|
||||
dest = "#{$dst}/css/main.css"
|
||||
begin
|
||||
asset = $sprockets.find_asset("main.css")
|
||||
rescue Exception => e
|
||||
err = e
|
||||
end
|
||||
end
|
||||
puts dest
|
||||
|
||||
if err
|
||||
puts err
|
||||
else
|
||||
File.open(dest, 'w+') do |file|
|
||||
file << asset.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
add.each do |f|
|
||||
folder = type f
|
||||
err = nil
|
||||
if folder==:js
|
||||
dest = "#{$dst}/js/main.js"
|
||||
begin
|
||||
asset = $sprockets.find_asset("main.coffee")
|
||||
rescue Exception => e
|
||||
err = e
|
||||
end
|
||||
else
|
||||
dest = "#{$dst}/css/main.css"
|
||||
begin
|
||||
asset = $sprockets.find_asset("main.css")
|
||||
rescue Exception => e
|
||||
err = e
|
||||
end
|
||||
end
|
||||
puts dest
|
||||
|
||||
if err
|
||||
puts err
|
||||
else
|
||||
File.open(dest, 'w+') do |file|
|
||||
file << asset.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
listener.start
|
||||
|
||||
|
||||
sleep
|
||||
rescue Exception
|
||||
exit
|
||||
end
|
||||
#=end
|
9
services/fichitas/fichitas.spec.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
description: para el dominó
|
||||
packages:
|
||||
self:
|
||||
version: 0.0.0
|
||||
source: https://github.com/unRob/fichitas
|
||||
build: echo "build tbd"
|
||||
deploy:
|
||||
credentials: vault://nidito/deploy/fichitas.pati.to
|
||||
src: ./src
|
69
services/fichitas/fichitas.tf
Normal file
@ -0,0 +1,69 @@
|
||||
terraform {
|
||||
backend "consul" {
|
||||
path = "nidito/state/service/fichitas.pati.to"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
consul = {
|
||||
source = "hashicorp/consul"
|
||||
version = "~> 2.21.0"
|
||||
}
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.4.0"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.29.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.0.0"
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "DO" {
|
||||
path = "cfg/infra/tree/provider:digitalocean"
|
||||
}
|
||||
|
||||
provider "digitalocean" {
|
||||
token = data.vault_generic_secret.DO.data.patito
|
||||
}
|
||||
|
||||
data "terraform_remote_state" "rob_mx" {
|
||||
backend = "consul"
|
||||
workspace = "default"
|
||||
config = {
|
||||
datacenter = "casa"
|
||||
path = "nidito/state/rob.mx"
|
||||
}
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "service" {
|
||||
domain = "pati.to"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
name = "fichitas"
|
||||
value = data.terraform_remote_state.rob_mx.outputs.bernal.ip
|
||||
}
|
||||
|
||||
resource "consul_keys" "cdn-config" {
|
||||
datacenter = "qro0"
|
||||
key {
|
||||
path = "cdn/fichitas.pati.to"
|
||||
value = jsonencode({
|
||||
cert = "pati.to"
|
||||
folder = "fichitas.pati.to"
|
||||
nginx_config = file("${abspath(path.root)}/nginx.conf")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_kv_secret" "deploy-config" {
|
||||
path = "nidito/deploy/fichitas.pati.to"
|
||||
data_json = jsonencode({
|
||||
type = "ssh"
|
||||
host = "bernal"
|
||||
domain = "fichitas.pati.to"
|
||||
})
|
||||
}
|
||||
|
3
services/fichitas/nginx.conf
Normal file
@ -0,0 +1,3 @@
|
||||
location / {
|
||||
index index.html;
|
||||
}
|
1
services/fichitas/src/assets/css/main.css
Normal file
326
services/fichitas/src/assets/css/main.v1.css
Normal file
@ -0,0 +1,326 @@
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font: bold 16px/1em 'Futura Std', Futura, sans-serif;
|
||||
background: #0d0d0d -webkit-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.7));
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
text-shadow: 1px 1px 0px #fff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
line-height: 2em;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #666;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
#max-puntos {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#container {
|
||||
padding: 1%;
|
||||
height: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
max-width: 480px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.separador {
|
||||
background: url(/assets/img/separador.png) center center no-repeat;
|
||||
width: 170px;
|
||||
height: 20px;
|
||||
margin: 0 auto;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.separador-large {
|
||||
background: url(/assets/img/separador-large.png) center center no-repeat;
|
||||
min-width: 300px;
|
||||
max-height: 35px;
|
||||
display: table;
|
||||
position: relative;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.separador-large p {
|
||||
vertical-align: middle;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.patote {
|
||||
background: url(/assets/img/patote.png) no-repeat;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.action-small {
|
||||
font-size: 12px;
|
||||
letter-spacing: 1%;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jugadores {
|
||||
color: #ccc;
|
||||
font-size:24px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.card {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
height: 100%;
|
||||
-webkit-transition: all .5s ease-in;
|
||||
-webkit-backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.card-part {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-box-pack: center;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-box-pack: center;
|
||||
}
|
||||
|
||||
.top {
|
||||
-webkit-box-pack: start;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
-webkit-box-pack: end;
|
||||
}
|
||||
|
||||
.card-upper {
|
||||
-webkit-box-pack: end;
|
||||
}
|
||||
.card-bottom {
|
||||
padding-top: 1%;
|
||||
-webkit-box-pack: start;
|
||||
}
|
||||
|
||||
.first-h2 {
|
||||
margin-top: 2%;
|
||||
}
|
||||
|
||||
.score {
|
||||
font-size:60px;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
#resultado {
|
||||
position:absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background: #222;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
#resultado h1, #resultado h2 {
|
||||
color: #fff;
|
||||
text-shadow: -1px -1px 0px #000;
|
||||
}
|
||||
|
||||
.flip {
|
||||
-webkit-transform: rotateX(180deg);
|
||||
-webkit-transition: all .5s ease-in;
|
||||
}
|
||||
|
||||
#resultado .score {
|
||||
text-align: center;
|
||||
background: rgba(255,255,255,.5);
|
||||
border: none;
|
||||
font: inherit;
|
||||
color: #fff;
|
||||
font-size: 60px;
|
||||
font-family: inherit;
|
||||
width: 3em;
|
||||
border-radius: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-input-placeholder {
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
button {
|
||||
color: #393B47;
|
||||
font-family: inherit;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
-ms-border-radius: 2px;
|
||||
-o-border-radius: 2px;
|
||||
border-radius: 5px;
|
||||
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px;
|
||||
|
||||
background: #5499CE;
|
||||
border-color: #2F6893;
|
||||
|
||||
color: #fff;
|
||||
font-size: 1em;
|
||||
text-shadow: 0 1px 2px #2f6893;
|
||||
|
||||
-webkit-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
-moz-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
-ms-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
-o-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
-webkit-transition: 0.25s ease all;
|
||||
-moz-transition: 0.25s ease all;
|
||||
-ms-transition: 0.25s ease all;
|
||||
-o-transition: 0.25s ease all;
|
||||
transition: 0.25s ease all;
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
-o-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button:hover, .boton:hover {
|
||||
border-color: #aaa;
|
||||
}
|
||||
|
||||
button:active,
|
||||
.boton:active,
|
||||
button.guardar:active,
|
||||
.boton.guardar:active,
|
||||
button.borrar:active,
|
||||
.boton.borrar:active {
|
||||
-webkit-box-shadow:
|
||||
inset 0 2px 5px rgba(0,0,0, 0.5),
|
||||
0 1px 0 #fff;
|
||||
-moz-box-shadow:
|
||||
inset 0 2px 5px rgba(0,0,0, 0.5),
|
||||
0 1px 0 #fff;
|
||||
-ms-box-shadow:
|
||||
inset 0 2px 5px rgba(0,0,0, 0.5),
|
||||
0 1px 0 #fff;
|
||||
-o-box-shadow:
|
||||
inset 0 2px 5px rgba(0,0,0, 0.5),
|
||||
0 1px 0 #fff;
|
||||
box-shadow:
|
||||
inset 0 2px 5px rgba(0,0,0, 0.5),
|
||||
0 1px 0 #fff;
|
||||
}
|
||||
|
||||
button,
|
||||
.boton {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px;
|
||||
|
||||
background: #5499CE;
|
||||
border-color: #2F6893;
|
||||
|
||||
color: #fff;
|
||||
font-size: 1em;
|
||||
text-shadow: 0 1px 2px #2f6893;
|
||||
|
||||
-webkit-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
-moz-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
-ms-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
-o-box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255, 0.2),
|
||||
inset 0 -2px 10px rgba(0,0,0, 0.05),
|
||||
0 1px 0 #fff;
|
||||
}
|
||||
button.guardar:hover,
|
||||
.boton.guardar:hover {
|
||||
background: #2379B9;
|
||||
border-color: #2F6893;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.scores-list { text-align: left; max-width: 300px; margin: 0 auto;}
|
||||
.scores-list li {
|
||||
display: inline-block;
|
||||
color: #aaa;
|
||||
text-align: center;
|
||||
min-width: 10%;
|
||||
font-weight: normal;
|
||||
border-right: 1px solid rgba(255,255,255,.1);
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input.hidden {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -999em;
|
||||
}
|
BIN
services/fichitas/src/assets/fonts/ss-pika.eot
Executable file
1338
services/fichitas/src/assets/fonts/ss-pika.svg
Normal file
After Width: | Height: | Size: 277 KiB |
BIN
services/fichitas/src/assets/fonts/ss-pika.ttf
Normal file
BIN
services/fichitas/src/assets/fonts/ss-pika.woff
Normal file
BIN
services/fichitas/src/assets/img/icons/icon.png
Normal file
After Width: | Height: | Size: 994 B |
BIN
services/fichitas/src/assets/img/icons/icon@2x.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
services/fichitas/src/assets/img/startup/1004x768.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
services/fichitas/src/assets/img/startup/1496x2048.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
services/fichitas/src/assets/img/startup/2008x1536.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
services/fichitas/src/assets/img/startup/320x460.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
services/fichitas/src/assets/img/startup/640x1096.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
services/fichitas/src/assets/img/startup/640x920.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
services/fichitas/src/assets/img/startup/748x1024.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
1001
services/fichitas/src/assets/js/main.js
Normal file
170
services/fichitas/src/assets/js/main.v1.js
Normal file
@ -0,0 +1,170 @@
|
||||
/*global $,jQuery,window,console,confirm,alert*/
|
||||
var storage = {
|
||||
ls: window.localStorage,
|
||||
callback: null,
|
||||
set: function(k,v) {
|
||||
var ahora = JSON.stringify(v);
|
||||
this.ls[k]=ahora;
|
||||
if (storage.callback) {
|
||||
storage.callback({key:k,newValue:v});
|
||||
}
|
||||
return v;
|
||||
},
|
||||
get: function(k) {
|
||||
var v = null;
|
||||
try {
|
||||
v = JSON.parse(this.ls[k]);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
return v;
|
||||
},
|
||||
change: function(cb) {
|
||||
storage.callback = cb;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
$(function(){
|
||||
$('#no-webapp').hide();
|
||||
var juegos_numerados = ['primer', 'segundo', 'tercer', 'cuarto', 'quinto', 'sexto', 'séptimo', 'octavo', 'noveno'];
|
||||
var cb = {
|
||||
juego: function(actual) {
|
||||
var t = '';
|
||||
if (juegos_numerados[actual]) {
|
||||
t = juegos_numerados[actual]+' juego';
|
||||
} else {
|
||||
t = actual+1;
|
||||
t = "juego "+t;
|
||||
}
|
||||
$('#numero-juego').text(t);
|
||||
},
|
||||
score: function(id, score) {
|
||||
var newScore = score < 9? '0'+score : score;
|
||||
$('#'+id).text(newScore);
|
||||
},
|
||||
table: function(id, scores) {
|
||||
if (scores.length === 0) {
|
||||
$('#'+id).html('');
|
||||
} else {
|
||||
var html = "";
|
||||
scores.forEach(function(i){
|
||||
html += "<li>"+i+"</li>";
|
||||
});
|
||||
$('#'+id).html(html);
|
||||
}
|
||||
}
|
||||
};
|
||||
var setupGame = function(){
|
||||
storage.set('numero-juego', 0);
|
||||
};
|
||||
|
||||
if (!storage.get('setup')) {
|
||||
storage.set('numero-juego', null);
|
||||
storage.set('player-1', null);
|
||||
storage.set('player-2', null);
|
||||
storage.set('scores-player-1', []);
|
||||
storage.set('scores-player-2', []);
|
||||
storage.set('setup', true);
|
||||
}
|
||||
|
||||
if (storage.get('numero-juego') > 0){
|
||||
cb.juego(storage.get('numero-juego'));
|
||||
cb.score('player-1', storage.get('player-1'));
|
||||
cb.score('player-2', storage.get('player-2'));
|
||||
cb.table('scores-player-1', storage.get('scores-player-1'));
|
||||
cb.table('scores-player-2', storage.get('scores-player-2'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
storage.change(function(evt){
|
||||
var key = evt.key;
|
||||
var ahora = evt.newValue;
|
||||
//var antes = evt.oldValue;
|
||||
switch (key) {
|
||||
case 'numero-juego':
|
||||
cb.juego(ahora);
|
||||
|
||||
if (ahora === 0) {
|
||||
storage.set('player-1', 0);
|
||||
storage.set('player-2', 0);
|
||||
storage.set('scores-player-1', []);
|
||||
storage.set('scores-player-2', []);
|
||||
}
|
||||
break;
|
||||
case 'player-1':
|
||||
case 'player-2':
|
||||
cb.score(key, ahora);
|
||||
if (ahora >= 100) {
|
||||
var mensaje = key==='player-1' ? 'Perdimos :(' : 'Ganamos!';
|
||||
mensaje += ' Jugamos otra vez?';
|
||||
if (confirm(mensaje)) {
|
||||
setupGame();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'scores-player-1':
|
||||
case 'scores-player-2':
|
||||
cb.table(key, ahora);
|
||||
break;
|
||||
}
|
||||
}, false);
|
||||
|
||||
|
||||
|
||||
|
||||
$('#activa-resultados').click(function(evt){
|
||||
$('#juego').addClass('flip');
|
||||
$('#resultado').removeClass('flip');
|
||||
});
|
||||
|
||||
$('#guardar').click(function(evt){
|
||||
evt.preventDefault();
|
||||
var p1 = Number($('#score-player-1').val());
|
||||
var p2 = Number($('#score-player-2').val());
|
||||
|
||||
if (p1 === p2 && p1 === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var tp1 = storage.get('player-1');
|
||||
var tp2 = storage.get('player-2');
|
||||
var sp1 = storage.get('scores-player-1');
|
||||
var sp2 = storage.get('scores-player-2');
|
||||
|
||||
sp1.push(p1);
|
||||
sp2.push(p2);
|
||||
storage.set('scores-player-1', sp1);
|
||||
storage.set('scores-player-2', sp2);
|
||||
storage.set('player-1', tp1+p1);
|
||||
storage.set('player-2', tp2+p2);
|
||||
storage.set('numero-juego', storage.get('numero-juego')+1);
|
||||
$('#juego').removeClass('flip');
|
||||
$('#resultado').addClass('flip');
|
||||
$('#score-player-1').val('');
|
||||
$('#score-player-2').val('');
|
||||
});
|
||||
|
||||
$('#cancelar').click(function(evt){
|
||||
evt.preventDefault();
|
||||
$('#juego').removeClass('flip');
|
||||
$('#resultado').addClass('flip');
|
||||
});
|
||||
|
||||
$('.activa-input').click(function(evt){
|
||||
evt.preventDefault();
|
||||
var id = $(this).data('input');
|
||||
console.log(id);
|
||||
$(id).focus();
|
||||
$(id).click();
|
||||
});
|
||||
|
||||
$('#terminar').click(function(evt){
|
||||
evt.preventDefault();
|
||||
if (confirm('Seguro?')) {
|
||||
setupGame();
|
||||
}
|
||||
});
|
||||
});
|
30
services/fichitas/src/assets/src/scripts/config.coffee
Normal file
@ -0,0 +1,30 @@
|
||||
Config = ()->
|
||||
@ds = window.localStorage;
|
||||
@callbacks = {}
|
||||
Config.instance = this
|
||||
this
|
||||
|
||||
Config.instance = null
|
||||
|
||||
Config::on = (key, cb)->
|
||||
@callbacks[key] = @callbacks[key] || [cb]
|
||||
true
|
||||
|
||||
Config::set = (key, value)->
|
||||
@ds.setItem(key, value);
|
||||
evt_cbs = @callbacks[key] || []
|
||||
for cb in evt_cbs
|
||||
cb(value)
|
||||
value
|
||||
|
||||
Config::unset = (key)->
|
||||
@ds.removeItem(key)
|
||||
evt_cbs = @callbacks[key] || []
|
||||
for cb in evt_cbs
|
||||
cb(key)
|
||||
key
|
||||
|
||||
Config::get = (key)->
|
||||
@ds.getItem(key);
|
||||
|
||||
window.Config = Config;
|
3
services/fichitas/src/assets/src/scripts/jquery.js
vendored
Normal file
129
services/fichitas/src/assets/src/scripts/juego.coffee
Normal file
@ -0,0 +1,129 @@
|
||||
Game = (config)->
|
||||
@players = {}
|
||||
$('#players').empty();
|
||||
playerCount = (config.get('players.qty') || 2)
|
||||
console.log playerCount
|
||||
@playerCount = parseInt(playerCount)
|
||||
for id in [1..@playerCount]
|
||||
id = id
|
||||
p = new Player(id)
|
||||
p.name = config.get("players.player.#{id}.name") || @defaultName(id, @playerCount)
|
||||
p.scores = JSON.parse(config.get("players.player.#{id}.scores")) || []
|
||||
|
||||
@players[id] = p
|
||||
$('#players').append(p.dom())
|
||||
|
||||
@maxPoints = ()->
|
||||
parseInt config.get('game.maxPoints'), 10
|
||||
|
||||
$('#players').attr('class', '').addClass("player-count-#{@playerCount}")
|
||||
window.refreshPlayersUI()
|
||||
@started = config.get('game.started') || false
|
||||
@gameNo = config.get('game.number') || 0
|
||||
@gameNo = parseInt(@gameNo)
|
||||
Game.instance = this
|
||||
this
|
||||
|
||||
Game.numbers = ['primer', 'segundo', 'tercer', 'cuarto', 'quinto', 'sexto', 'séptimo', 'octavo', 'noveno'];
|
||||
|
||||
Game.instance = null
|
||||
|
||||
Game::restart = ()->
|
||||
Config.instance.unset('game.started')
|
||||
Config.instance.set('game.number', '0')
|
||||
@gameNo = 0 #porque se caga muy duro si no
|
||||
for id, player of @players
|
||||
Config.instance.unset("players.player.#{id}.scores")
|
||||
game = new Game(Config.instance)
|
||||
Game.instance = game
|
||||
game
|
||||
|
||||
Game::player = (id)->
|
||||
@players[id]
|
||||
|
||||
Game::addPoints = (id, points)->
|
||||
if !@started
|
||||
@started = true
|
||||
Config.instance.set('game.started', true)
|
||||
|
||||
player = @player(id)
|
||||
player.addPoints(points)
|
||||
if player.score() >= @maxPoints()
|
||||
console.log("lost", player.score(), @maxPoints())
|
||||
@started = false
|
||||
name = "#{player.name} "
|
||||
verbo = 'perdió'
|
||||
verbo = 'perdimos' if player.name.match(/nosotros/i)
|
||||
if player.name.match(/ustedes/i)
|
||||
verbo = 'Ganamos'
|
||||
name = ""
|
||||
|
||||
return @ended("#{name}#{verbo}")
|
||||
|
||||
if @playerCount == 2
|
||||
oid = if id == 1 then 2 else 1
|
||||
other = @player(oid);
|
||||
other.addPoints(0)
|
||||
@next()
|
||||
|
||||
return this
|
||||
|
||||
Game::ended = (phrase)->
|
||||
if (confirm("¡#{phrase}! ¿Volvemos a jugar?"))
|
||||
return @restart()
|
||||
this
|
||||
|
||||
Game::defaultName = (id, count)->
|
||||
if (count == 2)
|
||||
return "Nosotros" if id==1
|
||||
return "Ustedes" if id==2
|
||||
else
|
||||
return "Jugador #{id}"
|
||||
|
||||
Game::next = ()->
|
||||
@gameNo += 1
|
||||
config = Config.instance
|
||||
config.set('game.number', @gameNo)
|
||||
for id, player of @players
|
||||
config.set("players.player.#{player.id}.scores", JSON.stringify(player.scores))
|
||||
return this
|
||||
|
||||
Game::name = ()->
|
||||
if str = Game.numbers[@gameNo]
|
||||
return "#{str} juego"
|
||||
else
|
||||
return "Juego #{@gameNo+1}"
|
||||
|
||||
window.Game = Game;
|
||||
|
||||
##########
|
||||
# Player #
|
||||
##########
|
||||
|
||||
Player = (id)->
|
||||
@id = id;
|
||||
@name = "Jugador #{@id}"
|
||||
@scores = []
|
||||
this
|
||||
|
||||
Player.template = Mustache.compile($('#player-tpl').get(0).innerText);
|
||||
|
||||
Player::addPoints = (points)->
|
||||
@scores.push(points)
|
||||
|
||||
Player::score = ()->
|
||||
s = 0;
|
||||
for score in @scores
|
||||
s+=score
|
||||
str = s.toString()
|
||||
str = "0#{str}" while (str.length < 2)
|
||||
str
|
||||
|
||||
Player::renderScore = ()->
|
||||
(nil, r)=>
|
||||
r(@score())
|
||||
|
||||
Player::lost = (qty)->
|
||||
|
||||
Player::dom = ()->
|
||||
Player.template(this)
|
98
services/fichitas/src/assets/src/scripts/juego.ui.coffee
Normal file
@ -0,0 +1,98 @@
|
||||
$ ()->
|
||||
scrollTO = null
|
||||
config = Config.instance
|
||||
|
||||
isNumber = (n)->
|
||||
!isNaN(parseInt(n)) && isFinite(n);
|
||||
|
||||
finishScroll = (el)->
|
||||
return false if el.hasClass('animating')
|
||||
clearTimeout scrollTO
|
||||
sl = el.scrollLeft()
|
||||
w = el.width()
|
||||
pc = Math.round sl/w*100;
|
||||
if pc >= 50
|
||||
to = w
|
||||
fn = 'focus'
|
||||
else
|
||||
to = 0
|
||||
fn = 'blur'
|
||||
|
||||
falta = (100-pc)/100;
|
||||
el.addClass('animating');
|
||||
el.animate({scrollLeft: to}, (300*falta), ()->
|
||||
el.removeClass('active animating')
|
||||
el.find('input')[fn]();
|
||||
)
|
||||
|
||||
scrollFn = (evt)->
|
||||
el = $(this)
|
||||
el.addClass('active')
|
||||
clearTimeout scrollTO
|
||||
pc = Math.round el.scrollLeft()/el.width()*100;
|
||||
el.css('background', "rgba(242,242,242,#{pc/100})")
|
||||
fs = ()->
|
||||
finishScroll(el)
|
||||
scrollTO = setTimeout fs, 100
|
||||
true
|
||||
|
||||
changeName = (evt)->
|
||||
el = $(this)
|
||||
newName = prompt("¿Cómo se llama este jugador?", el.text())
|
||||
newName = $.trim(newName)
|
||||
id = el.parent().attr('id').replace('player-', '');
|
||||
if newName==''
|
||||
newName = Game.instance.defaultName(id, Game.instance.playerCount)
|
||||
config.unset("players.player.#{id}.name");
|
||||
else
|
||||
config.set("players.player.#{id}.name", newName);
|
||||
el.text(newName);
|
||||
|
||||
|
||||
sumaPlayer = (evt)->
|
||||
evt.preventDefault()
|
||||
target = $($(this).data('modifies'))
|
||||
val = target.val()
|
||||
return false if !isNumber(val)
|
||||
target.siblings('.suma').append("<li>#{val}</li>")
|
||||
target.val('').focus();
|
||||
|
||||
guardaPlayer = (evt)->
|
||||
evt.preventDefault()
|
||||
target = $($(this).data('modifies'))
|
||||
id = parseInt(target.attr('id').replace(/\D+/, ''), 10);
|
||||
el = $(this).parents('.player')
|
||||
val = parseInt(target.val(), 10);
|
||||
fichas = el.find('.suma li')
|
||||
if (fichas.length > 0)
|
||||
fichas.each (i, ficha)->
|
||||
val += parseInt(ficha.innerText, 10)
|
||||
el.find('.suma').remove()
|
||||
|
||||
target.blur();
|
||||
el.addClass('active animating').animate({scrollLeft: 0}, 300, ()->
|
||||
setTimeout(()->
|
||||
el.removeClass('active animating')
|
||||
, 500)
|
||||
|
||||
)
|
||||
target.val('');
|
||||
window.addScore id, (val||0)
|
||||
|
||||
window.refreshPlayersUI = ()->
|
||||
$('.player:not(.animating)').off 'scroll'
|
||||
$('.player-name').off 'click'
|
||||
$('.player:not(.animating)').on 'scroll', scrollFn
|
||||
$('.player-name').on 'click', changeName
|
||||
$('.player-add').on 'click', sumaPlayer
|
||||
$('.player-save').on 'click', guardaPlayer
|
||||
$('.suma').on 'click', 'li', ()->
|
||||
$(this).remove();
|
||||
|
||||
$('#players').on 'click', '.score', (evt)->
|
||||
evt.preventDefault();
|
||||
el = $(this).parents('.player')
|
||||
el.addClass('active animating').animate({scrollLeft: el.width()}, 300, ()->
|
||||
el.removeClass('active animating')
|
||||
)
|
||||
|
102
services/fichitas/src/assets/src/scripts/main.coffee
Normal file
@ -0,0 +1,102 @@
|
||||
#= require jquery
|
||||
#= require mustache
|
||||
#= require config
|
||||
#= require juego
|
||||
#= require juego.ui
|
||||
|
||||
config = new Config
|
||||
$ ()->
|
||||
screens =
|
||||
config: $('#config')
|
||||
game: $('#game')
|
||||
|
||||
cfg =
|
||||
jugadores: $('#jugadores'),
|
||||
puntos: $('#puntos')
|
||||
|
||||
game = new Game(config)
|
||||
$('#game-name').text(game.name())
|
||||
config.on 'game.number', ()->
|
||||
$('#game-name').text(game.name())
|
||||
|
||||
window.saveConfig = (check=true)->
|
||||
console.log "saving config"
|
||||
if (check && (parseInt(cfg.jugadores.val(),10) != game.playerCount) && game.started)
|
||||
console.log "checking"
|
||||
if (!confirm('Hay un juego en curso, deseas comenzar uno nuevo?'))
|
||||
cfg.jugadores.val(config.get('players.qty'));
|
||||
return false;
|
||||
console.log "changing player qty"
|
||||
config.set 'players.qty', parseInt(cfg.jugadores.val(), 10)
|
||||
|
||||
console.log "config saved"
|
||||
config.set 'game.maxPoints', parseInt(cfg.puntos.val(), 10)
|
||||
|
||||
window.addScore = (player, points)->
|
||||
game = game.addPoints(player, points);
|
||||
if game.started
|
||||
$("#player-#{player} .score").text(game.player(player).score());
|
||||
|
||||
cfg.jugadores.val(config.get('players.qty')||2);
|
||||
cfg.puntos.val(config.get('game.maxPoints')||100);
|
||||
config.on 'players.qty', (ahora, antes)->
|
||||
game = game.restart()
|
||||
$('#game-name').text(game.name())
|
||||
|
||||
|
||||
|
||||
$('[role=action-button]').on 'click', (evt)->
|
||||
evt.preventDefault();
|
||||
el = $(this)
|
||||
target = $(el.data('modifies'))
|
||||
action = el.data('action')
|
||||
val = target.attr('step') || target.val();
|
||||
val = parseInt(val, 10)
|
||||
newVal = parseInt(target.val(), 10)
|
||||
max = target.attr('max') && parseInt(target.attr('max'), 10) || false
|
||||
min = target.attr('min') && parseInt(target.attr('min'), 10) || false
|
||||
|
||||
switch action
|
||||
when 'plus'
|
||||
newVal += val
|
||||
return false if max && newVal > max
|
||||
when 'minus'
|
||||
newVal -= parseInt(val, 10)
|
||||
return false if min && newVal < min
|
||||
when 'ok'
|
||||
return false;
|
||||
|
||||
target.val(newVal);
|
||||
|
||||
$('#restart-game').on 'click', (evt)->
|
||||
evt.preventDefault();
|
||||
if (confirm "Seguro que deseas volver a empezar?")
|
||||
window.saveConfig(false)
|
||||
game = game.restart()
|
||||
$('#game-name').text(game.name())
|
||||
screens.config.removeClass('shown')
|
||||
screens.game.addClass('shown')
|
||||
|
||||
$('#finish-game').on 'click', (evt)->
|
||||
evt.preventDefault();
|
||||
max = 0
|
||||
for id, player of game.players
|
||||
count = player.scores.length
|
||||
max = count if max < count
|
||||
|
||||
for id, player of game.players
|
||||
if player.scores.length < max
|
||||
player.addPoints(0)
|
||||
|
||||
game = game.next()
|
||||
|
||||
|
||||
$('.nav-icon').on 'click', (evt)->
|
||||
evt.preventDefault();
|
||||
visible = $('.screen.shown')
|
||||
invisible = $('.screen:not(.shown)')
|
||||
visible.removeClass('shown');
|
||||
invisible.addClass('shown');
|
||||
if (cb = $(this).data('action'))
|
||||
window[cb]();
|
||||
return false
|
537
services/fichitas/src/assets/src/scripts/mustache.js
Normal file
@ -0,0 +1,537 @@
|
||||
|
||||
/*
|
||||
* mustache.js - Logic-less {{mustache}} templates with JavaScript
|
||||
* http://github.com/janl/mustache.js
|
||||
*/
|
||||
|
||||
/*global define: false*/
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof exports === "object" && exports) {
|
||||
factory(exports); // CommonJS
|
||||
} else {
|
||||
var mustache = {};
|
||||
factory(mustache);
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(mustache); // AMD
|
||||
} else {
|
||||
root.Mustache = mustache; // <script>
|
||||
}
|
||||
}
|
||||
}(this, function (mustache) {
|
||||
|
||||
var whiteRe = /\s*/;
|
||||
var spaceRe = /\s+/;
|
||||
var nonSpaceRe = /\S/;
|
||||
var eqRe = /\s*=/;
|
||||
var curlyRe = /\s*\}/;
|
||||
var tagRe = /#|\^|\/|>|\{|&|=|!/;
|
||||
|
||||
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
|
||||
// See https://github.com/janl/mustache.js/issues/189
|
||||
var RegExp_test = RegExp.prototype.test;
|
||||
function testRegExp(re, string) {
|
||||
return RegExp_test.call(re, string);
|
||||
}
|
||||
|
||||
function isWhitespace(string) {
|
||||
return !testRegExp(nonSpaceRe, string);
|
||||
}
|
||||
|
||||
var Object_toString = Object.prototype.toString;
|
||||
var isArray = Array.isArray || function (obj) {
|
||||
return Object_toString.call(obj) === '[object Array]';
|
||||
};
|
||||
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
|
||||
}
|
||||
|
||||
var entityMap = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
"/": '/'
|
||||
};
|
||||
|
||||
function escapeHtml(string) {
|
||||
return String(string).replace(/[&<>"'\/]/g, function (s) {
|
||||
return entityMap[s];
|
||||
});
|
||||
}
|
||||
|
||||
function Scanner(string) {
|
||||
this.string = string;
|
||||
this.tail = string;
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the tail is empty (end of string).
|
||||
*/
|
||||
Scanner.prototype.eos = function () {
|
||||
return this.tail === "";
|
||||
};
|
||||
|
||||
/**
|
||||
* Tries to match the given regular expression at the current position.
|
||||
* Returns the matched text if it can match, the empty string otherwise.
|
||||
*/
|
||||
Scanner.prototype.scan = function (re) {
|
||||
var match = this.tail.match(re);
|
||||
|
||||
if (match && match.index === 0) {
|
||||
this.tail = this.tail.substring(match[0].length);
|
||||
this.pos += match[0].length;
|
||||
return match[0];
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
/**
|
||||
* Skips all text until the given regular expression can be matched. Returns
|
||||
* the skipped string, which is the entire tail if no match can be made.
|
||||
*/
|
||||
Scanner.prototype.scanUntil = function (re) {
|
||||
var match, pos = this.tail.search(re);
|
||||
|
||||
switch (pos) {
|
||||
case -1:
|
||||
match = this.tail;
|
||||
this.pos += this.tail.length;
|
||||
this.tail = "";
|
||||
break;
|
||||
case 0:
|
||||
match = "";
|
||||
break;
|
||||
default:
|
||||
match = this.tail.substring(0, pos);
|
||||
this.tail = this.tail.substring(pos);
|
||||
this.pos += pos;
|
||||
}
|
||||
|
||||
return match;
|
||||
};
|
||||
|
||||
function Context(view, parent) {
|
||||
this.view = view || {};
|
||||
this.parent = parent;
|
||||
this._cache = {};
|
||||
}
|
||||
|
||||
Context.make = function (view) {
|
||||
return (view instanceof Context) ? view : new Context(view);
|
||||
};
|
||||
|
||||
Context.prototype.push = function (view) {
|
||||
return new Context(view, this);
|
||||
};
|
||||
|
||||
Context.prototype.lookup = function (name) {
|
||||
var value = this._cache[name];
|
||||
|
||||
if (!value) {
|
||||
if (name == '.') {
|
||||
value = this.view;
|
||||
} else {
|
||||
var context = this;
|
||||
|
||||
while (context) {
|
||||
if (name.indexOf('.') > 0) {
|
||||
value = context.view;
|
||||
var names = name.split('.'), i = 0;
|
||||
while (value && i < names.length) {
|
||||
value = value[names[i++]];
|
||||
}
|
||||
} else {
|
||||
value = context.view[name];
|
||||
}
|
||||
|
||||
if (value != null) break;
|
||||
|
||||
context = context.parent;
|
||||
}
|
||||
}
|
||||
|
||||
this._cache[name] = value;
|
||||
}
|
||||
|
||||
if (typeof value === 'function') value = value.call(this.view);
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
function Writer() {
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
Writer.prototype.clearCache = function () {
|
||||
this._cache = {};
|
||||
this._partialCache = {};
|
||||
};
|
||||
|
||||
Writer.prototype.compile = function (template, tags) {
|
||||
var fn = this._cache[template];
|
||||
|
||||
if (!fn) {
|
||||
var tokens = mustache.parse(template, tags);
|
||||
fn = this._cache[template] = this.compileTokens(tokens, template);
|
||||
}
|
||||
|
||||
return fn;
|
||||
};
|
||||
|
||||
Writer.prototype.compilePartial = function (name, template, tags) {
|
||||
var fn = this.compile(template, tags);
|
||||
this._partialCache[name] = fn;
|
||||
return fn;
|
||||
};
|
||||
|
||||
Writer.prototype.getPartial = function (name) {
|
||||
if (!(name in this._partialCache) && this._loadPartial) {
|
||||
this.compilePartial(name, this._loadPartial(name));
|
||||
}
|
||||
|
||||
return this._partialCache[name];
|
||||
};
|
||||
|
||||
Writer.prototype.compileTokens = function (tokens, template) {
|
||||
var self = this;
|
||||
return function (view, partials) {
|
||||
if (partials) {
|
||||
if (typeof partials === 'function') {
|
||||
self._loadPartial = partials;
|
||||
} else {
|
||||
for (var name in partials) {
|
||||
self.compilePartial(name, partials[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return renderTokens(tokens, self, Context.make(view), template);
|
||||
};
|
||||
};
|
||||
|
||||
Writer.prototype.render = function (template, view, partials) {
|
||||
return this.compile(template)(view, partials);
|
||||
};
|
||||
|
||||
/**
|
||||
* Low-level function that renders the given `tokens` using the given `writer`
|
||||
* and `context`. The `template` string is only needed for templates that use
|
||||
* higher-order sections to extract the portion of the original template that
|
||||
* was contained in that section.
|
||||
*/
|
||||
function renderTokens(tokens, writer, context, template) {
|
||||
var buffer = '';
|
||||
|
||||
var token, tokenValue, value;
|
||||
for (var i = 0, len = tokens.length; i < len; ++i) {
|
||||
token = tokens[i];
|
||||
tokenValue = token[1];
|
||||
|
||||
switch (token[0]) {
|
||||
case '#':
|
||||
value = context.lookup(tokenValue);
|
||||
|
||||
if (typeof value === 'object') {
|
||||
if (isArray(value)) {
|
||||
for (var j = 0, jlen = value.length; j < jlen; ++j) {
|
||||
buffer += renderTokens(token[4], writer, context.push(value[j]), template);
|
||||
}
|
||||
} else if (value) {
|
||||
buffer += renderTokens(token[4], writer, context.push(value), template);
|
||||
}
|
||||
} else if (typeof value === 'function') {
|
||||
var text = template == null ? null : template.slice(token[3], token[5]);
|
||||
value = value.call(context.view, text, function (template) {
|
||||
return writer.render(template, context);
|
||||
});
|
||||
if (value != null) buffer += value;
|
||||
} else if (value) {
|
||||
buffer += renderTokens(token[4], writer, context, template);
|
||||
}
|
||||
|
||||
break;
|
||||
case '^':
|
||||
value = context.lookup(tokenValue);
|
||||
|
||||
// Use JavaScript's definition of falsy. Include empty arrays.
|
||||
// See https://github.com/janl/mustache.js/issues/186
|
||||
if (!value || (isArray(value) && value.length === 0)) {
|
||||
buffer += renderTokens(token[4], writer, context, template);
|
||||
}
|
||||
|
||||
break;
|
||||
case '>':
|
||||
value = writer.getPartial(tokenValue);
|
||||
if (typeof value === 'function') buffer += value(context);
|
||||
break;
|
||||
case '&':
|
||||
value = context.lookup(tokenValue);
|
||||
if (value != null) buffer += value;
|
||||
break;
|
||||
case 'name':
|
||||
value = context.lookup(tokenValue);
|
||||
if (value != null) buffer += mustache.escape(value);
|
||||
break;
|
||||
case 'text':
|
||||
buffer += tokenValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms the given array of `tokens` into a nested tree structure where
|
||||
* tokens that represent a section have two additional items: 1) an array of
|
||||
* all tokens that appear in that section and 2) the index in the original
|
||||
* template that represents the end of that section.
|
||||
*/
|
||||
function nestTokens(tokens) {
|
||||
var tree = [];
|
||||
var collector = tree;
|
||||
var sections = [];
|
||||
|
||||
var token;
|
||||
for (var i = 0, len = tokens.length; i < len; ++i) {
|
||||
token = tokens[i];
|
||||
switch (token[0]) {
|
||||
case '#':
|
||||
case '^':
|
||||
sections.push(token);
|
||||
collector.push(token);
|
||||
collector = token[4] = [];
|
||||
break;
|
||||
case '/':
|
||||
var section = sections.pop();
|
||||
section[5] = token[2];
|
||||
collector = sections.length > 0 ? sections[sections.length - 1][4] : tree;
|
||||
break;
|
||||
default:
|
||||
collector.push(token);
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the values of consecutive text tokens in the given `tokens` array
|
||||
* to a single token.
|
||||
*/
|
||||
function squashTokens(tokens) {
|
||||
var squashedTokens = [];
|
||||
|
||||
var token, lastToken;
|
||||
for (var i = 0, len = tokens.length; i < len; ++i) {
|
||||
token = tokens[i];
|
||||
if (token) {
|
||||
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
|
||||
lastToken[1] += token[1];
|
||||
lastToken[3] = token[3];
|
||||
} else {
|
||||
lastToken = token;
|
||||
squashedTokens.push(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return squashedTokens;
|
||||
}
|
||||
|
||||
function escapeTags(tags) {
|
||||
return [
|
||||
new RegExp(escapeRegExp(tags[0]) + "\\s*"),
|
||||
new RegExp("\\s*" + escapeRegExp(tags[1]))
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Breaks up the given `template` string into a tree of token objects. If
|
||||
* `tags` is given here it must be an array with two string values: the
|
||||
* opening and closing tags used in the template (e.g. ["<%", "%>"]). Of
|
||||
* course, the default is to use mustaches (i.e. Mustache.tags).
|
||||
*/
|
||||
function parseTemplate(template, tags) {
|
||||
template = template || '';
|
||||
tags = tags || mustache.tags;
|
||||
|
||||
if (typeof tags === 'string') tags = tags.split(spaceRe);
|
||||
if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', '));
|
||||
|
||||
var tagRes = escapeTags(tags);
|
||||
var scanner = new Scanner(template);
|
||||
|
||||
var sections = []; // Stack to hold section tokens
|
||||
var tokens = []; // Buffer to hold the tokens
|
||||
var spaces = []; // Indices of whitespace tokens on the current line
|
||||
var hasTag = false; // Is there a {{tag}} on the current line?
|
||||
var nonSpace = false; // Is there a non-space char on the current line?
|
||||
|
||||
// Strips all whitespace tokens array for the current line
|
||||
// if there was a {{#tag}} on it and otherwise only space.
|
||||
function stripSpace() {
|
||||
if (hasTag && !nonSpace) {
|
||||
while (spaces.length) {
|
||||
delete tokens[spaces.pop()];
|
||||
}
|
||||
} else {
|
||||
spaces = [];
|
||||
}
|
||||
|
||||
hasTag = false;
|
||||
nonSpace = false;
|
||||
}
|
||||
|
||||
var start, type, value, chr, token;
|
||||
while (!scanner.eos()) {
|
||||
start = scanner.pos;
|
||||
|
||||
// Match any text between tags.
|
||||
value = scanner.scanUntil(tagRes[0]);
|
||||
if (value) {
|
||||
for (var i = 0, len = value.length; i < len; ++i) {
|
||||
chr = value.charAt(i);
|
||||
|
||||
if (isWhitespace(chr)) {
|
||||
spaces.push(tokens.length);
|
||||
} else {
|
||||
nonSpace = true;
|
||||
}
|
||||
|
||||
tokens.push(['text', chr, start, start + 1]);
|
||||
start += 1;
|
||||
|
||||
// Check for whitespace on the current line.
|
||||
if (chr == '\n') stripSpace();
|
||||
}
|
||||
}
|
||||
|
||||
// Match the opening tag.
|
||||
if (!scanner.scan(tagRes[0])) break;
|
||||
hasTag = true;
|
||||
|
||||
// Get the tag type.
|
||||
type = scanner.scan(tagRe) || 'name';
|
||||
scanner.scan(whiteRe);
|
||||
|
||||
// Get the tag value.
|
||||
if (type === '=') {
|
||||
value = scanner.scanUntil(eqRe);
|
||||
scanner.scan(eqRe);
|
||||
scanner.scanUntil(tagRes[1]);
|
||||
} else if (type === '{') {
|
||||
value = scanner.scanUntil(new RegExp('\\s*' + escapeRegExp('}' + tags[1])));
|
||||
scanner.scan(curlyRe);
|
||||
scanner.scanUntil(tagRes[1]);
|
||||
type = '&';
|
||||
} else {
|
||||
value = scanner.scanUntil(tagRes[1]);
|
||||
}
|
||||
|
||||
// Match the closing tag.
|
||||
if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos);
|
||||
|
||||
token = [type, value, start, scanner.pos];
|
||||
tokens.push(token);
|
||||
|
||||
if (type === '#' || type === '^') {
|
||||
sections.push(token);
|
||||
} else if (type === '/') {
|
||||
// Check section nesting.
|
||||
if (sections.length === 0) throw new Error('Unopened section "' + value + '" at ' + start);
|
||||
var openSection = sections.pop();
|
||||
if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
|
||||
} else if (type === 'name' || type === '{' || type === '&') {
|
||||
nonSpace = true;
|
||||
} else if (type === '=') {
|
||||
// Set the tags for the next time around.
|
||||
tags = value.split(spaceRe);
|
||||
if (tags.length !== 2) throw new Error('Invalid tags at ' + start + ': ' + tags.join(', '));
|
||||
tagRes = escapeTags(tags);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there are no open sections when we're done.
|
||||
var openSection = sections.pop();
|
||||
if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
|
||||
|
||||
tokens = squashTokens(tokens);
|
||||
|
||||
return nestTokens(tokens);
|
||||
}
|
||||
|
||||
mustache.name = "mustache.js";
|
||||
mustache.version = "0.7.2";
|
||||
mustache.tags = ["{{", "}}"];
|
||||
|
||||
mustache.Scanner = Scanner;
|
||||
mustache.Context = Context;
|
||||
mustache.Writer = Writer;
|
||||
|
||||
mustache.parse = parseTemplate;
|
||||
|
||||
// Export the escaping function so that the user may override it.
|
||||
// See https://github.com/janl/mustache.js/issues/244
|
||||
mustache.escape = escapeHtml;
|
||||
|
||||
// All Mustache.* functions use this writer.
|
||||
var defaultWriter = new Writer();
|
||||
|
||||
/**
|
||||
* Clears all cached templates and partials in the default writer.
|
||||
*/
|
||||
mustache.clearCache = function () {
|
||||
return defaultWriter.clearCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* Compiles the given `template` to a reusable function using the default
|
||||
* writer.
|
||||
*/
|
||||
mustache.compile = function (template, tags) {
|
||||
return defaultWriter.compile(template, tags);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compiles the partial with the given `name` and `template` to a reusable
|
||||
* function using the default writer.
|
||||
*/
|
||||
mustache.compilePartial = function (name, template, tags) {
|
||||
return defaultWriter.compilePartial(name, template, tags);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compiles the given array of tokens (the output of a parse) to a reusable
|
||||
* function using the default writer.
|
||||
*/
|
||||
mustache.compileTokens = function (tokens, template) {
|
||||
return defaultWriter.compileTokens(tokens, template);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the `template` with the given `view` and `partials` using the
|
||||
* default writer.
|
||||
*/
|
||||
mustache.render = function (template, view, partials) {
|
||||
return defaultWriter.render(template, view, partials);
|
||||
};
|
||||
|
||||
// This is here for backwards compatibility with 0.4.x.
|
||||
mustache.to_html = function (template, view, partials, send) {
|
||||
var result = mustache.render(template, view, partials);
|
||||
|
||||
if (typeof send === "function") {
|
||||
send(result);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}));
|
64
services/fichitas/src/assets/src/scss/_buttons.scss
Normal file
@ -0,0 +1,64 @@
|
||||
@import "_variables";
|
||||
|
||||
.icono {
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 100%;
|
||||
background: lighten($grisObscuro, 10%);
|
||||
text-decoration: none;
|
||||
color: $grisClaro;
|
||||
display: block;
|
||||
padding: 0px;
|
||||
font-weight: bold;
|
||||
font-size: 26px;
|
||||
line-height: 1.5em;
|
||||
position: absolute;
|
||||
bottom: 1em;
|
||||
font-weight: 600;
|
||||
padding-top: .1em;
|
||||
|
||||
&:hover, {
|
||||
background: $grisObscuro
|
||||
}
|
||||
}
|
||||
|
||||
.round-icon {
|
||||
font-size: 50px;
|
||||
line-height: 85px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 60px;
|
||||
background: #D9D9D9;
|
||||
color: #A8A8A8;
|
||||
display: block;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
background: $grisObscuro;
|
||||
color: $grisClaro;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.nav-icon {
|
||||
opacity: .5;
|
||||
color: #fff;
|
||||
font-size: 30px;
|
||||
line-height: 70px;
|
||||
background-color: transparent;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
|
||||
&:hover, &:active {
|
||||
opacity: 1;
|
||||
background-color: #D9D9D9;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
#config-button {
|
||||
float: right;
|
||||
}
|
109
services/fichitas/src/assets/src/scss/_reset.scss
Normal file
@ -0,0 +1,109 @@
|
||||
html, body, div, span, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
abbr, address, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, samp,
|
||||
small, strong, sub, sup, var,
|
||||
b, i,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:0;
|
||||
outline:0;
|
||||
font-size:100%;
|
||||
vertical-align:baseline;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height:1;
|
||||
}
|
||||
|
||||
article,aside,details,figcaption,figure,
|
||||
footer,header,hgroup,menu,nav,section,
|
||||
div,h1,h2,h3,h4,h5,h6,p,blockquote,pre {
|
||||
display:block;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style:none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes:none;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content:'';
|
||||
content:none;
|
||||
}
|
||||
|
||||
a {
|
||||
margin:0;
|
||||
padding:0;
|
||||
font-size:100%;
|
||||
vertical-align:baseline;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
/* change colours to suit your needs */
|
||||
ins {
|
||||
background-color:#ff9;
|
||||
color:#000;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
/* change colours to suit your needs */
|
||||
mark {
|
||||
background-color:#ff9;
|
||||
color:#000;
|
||||
font-style:italic;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
abbr[title], dfn[title] {
|
||||
border-bottom:1px dotted;
|
||||
cursor:help;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse:collapse;
|
||||
border-spacing:0;
|
||||
}
|
||||
|
||||
/* change border colour to suit your needs */
|
||||
hr {
|
||||
display:block;
|
||||
height:1px;
|
||||
border:0;
|
||||
border-top:1px solid #cccccc;
|
||||
margin:1em 0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
input, select {
|
||||
vertical-align:middle;
|
||||
}
|
||||
:focus {
|
||||
outline: none;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
.clear { clear: both; float: none; }
|
||||
.clearfix::after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
32
services/fichitas/src/assets/src/scss/_symbols.scss
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// Symbols con Pika
|
||||
//
|
||||
|
||||
@charset "UTF-8";
|
||||
|
||||
@font-face {
|
||||
font-family: "SSPika";
|
||||
src: url('/assets/fonts/ss-pika.eot');
|
||||
src: url('/assets/fonts/ss-pika.eot?#iefix') format('embedded-opentype'),
|
||||
url('/assets/fonts/ss-pika.woff') format('woff'),
|
||||
url('/assets/fonts/ss-pika.ttf') format('truetype'),
|
||||
url('/assets/fonts/ss-pika.svg#SSPika') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.icono {
|
||||
font-family: "SSPika";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
white-space: nowrap;
|
||||
-webkit-font-feature-settings: "liga";
|
||||
-moz-font-feature-settings: "liga=1";
|
||||
-moz-font-feature-settings: "liga";
|
||||
-ms-font-feature-settings: "liga" 1;
|
||||
-o-font-feature-settings: "liga";
|
||||
font-feature-settings: "liga";
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
4
services/fichitas/src/assets/src/scss/_variables.scss
Normal file
@ -0,0 +1,4 @@
|
||||
$grisObscuro: #171717;
|
||||
$grisClaro: #E6E6E6;
|
||||
$grisMedio: #6E6E6E;
|
||||
$bigNumber: 140px;
|
57
services/fichitas/src/assets/src/scss/config.scss
Normal file
@ -0,0 +1,57 @@
|
||||
@import "_variables";
|
||||
|
||||
#config {
|
||||
background-color: darken($grisMedio, 20%);
|
||||
color: $grisClaro;
|
||||
|
||||
& h1 {
|
||||
color: darken($grisMedio, 40%);
|
||||
}
|
||||
|
||||
& input {
|
||||
width: 50%;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
font:inherit;
|
||||
font-size: 90px;
|
||||
padding: 0 5px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: $grisClaro;
|
||||
-webkit-appearance: none;
|
||||
font-weight: 800;
|
||||
font-family: "Avenir Next Condensed", "Avenir Next", "Avenir";
|
||||
}
|
||||
|
||||
& [role=action-button] {
|
||||
display: inline-block;
|
||||
background-color: $grisObscuro;
|
||||
color: $grisClaro;
|
||||
}
|
||||
|
||||
& [role=action-button]:hover {
|
||||
color: $grisObscuro;
|
||||
background-color: $grisClaro;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.config-element {
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: row;
|
||||
vertical-align: middle;
|
||||
-webkit-align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& .cell {
|
||||
text-align: center;
|
||||
-webkit-flex: 1 1 auto;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
#restart-game {
|
||||
&:active {
|
||||
background: rgb(180,0,0)
|
||||
}
|
||||
}
|
219
services/fichitas/src/assets/src/scss/main.scss
Normal file
@ -0,0 +1,219 @@
|
||||
@import "_reset";
|
||||
@import "_variables";
|
||||
@import "_symbols";
|
||||
@import "_buttons";
|
||||
@import "config";
|
||||
|
||||
@mixin clearfix() {
|
||||
*zoom: 1;
|
||||
&:before,
|
||||
&:after {
|
||||
content: ' ';
|
||||
display: table;
|
||||
}
|
||||
|
||||
&:after {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #000;
|
||||
font: 16px/1em "Avenir Next", "Avenir", sans-serif;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
color: #ededed;
|
||||
|
||||
}
|
||||
|
||||
.screen {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
top: 0px;
|
||||
-webkit-transition: all .5s ease-in;
|
||||
-webkit-backface-visibility: hidden;
|
||||
|
||||
-webkit-transform: perspective( 500px ) rotateY(180deg);
|
||||
-webkit-transition: all .5s ease-in;
|
||||
background-color: $grisObscuro;
|
||||
&.shown {
|
||||
-webkit-transform: rotateY(0deg);
|
||||
-webkit-transition: all .5s ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #E6E6E6;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#game-name {
|
||||
color: darken($grisMedio, 20%);
|
||||
padding-top: 5px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
font-weight:300;
|
||||
}
|
||||
|
||||
#players {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.player {
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
@include clearfix;
|
||||
|
||||
&:active, &.active {
|
||||
box-shadow: inset 0px 0px 6px #000;
|
||||
}
|
||||
|
||||
h1 {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
margin-top: -15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.player-name {
|
||||
z-index: 100;
|
||||
color: $grisMedio;
|
||||
}
|
||||
|
||||
.score-box {
|
||||
display: -webkit-box;
|
||||
width: 200%;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.score, .score-input {
|
||||
font: inherit;
|
||||
font-size:$bigNumber;
|
||||
line-height: 1em;
|
||||
font-weight: 800;
|
||||
font-family: "Avenir Next Condensed", "Avenir Next", "Avenir";
|
||||
height: 100%;
|
||||
padding-top: 16px;
|
||||
font-style: normal;
|
||||
//background-color: $grisObscuro;
|
||||
}
|
||||
.score-input {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border:none;
|
||||
text-align:center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
|
||||
::-webkit-input-placeholder {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
.score, .loss {
|
||||
width: 50%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.score-action-buttons {
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
width: 25%;
|
||||
text-align: center;
|
||||
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: column;
|
||||
vertical-align: middle;
|
||||
-webkit-align-items: center;
|
||||
-webkit-justify-content: center;
|
||||
|
||||
& .cell {
|
||||
-webkit-flex: 1 1 auto;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.icono {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.suma {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
text-align: center;
|
||||
color: $grisMedio;
|
||||
width:100%;
|
||||
font-weight: 600;
|
||||
font-size: 30px;
|
||||
line-height: 36px;
|
||||
|
||||
& li {display: inline-block;}
|
||||
& li:after {
|
||||
content: '+';
|
||||
}
|
||||
|
||||
& li:last-child:after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
.for-more-players {
|
||||
display:none;
|
||||
position:relative;
|
||||
position: relative;
|
||||
top: .35em;
|
||||
left: .15em
|
||||
}
|
||||
|
||||
.player-count-3 {
|
||||
|
||||
& .for-more-players, &+.for-more-players {
|
||||
display: block;
|
||||
}
|
||||
|
||||
& .for-more-players.icono {
|
||||
float: left;
|
||||
}
|
||||
|
||||
& .for-2-players {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
& .score {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
& .player-name {
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
& .score-action-buttons {
|
||||
top: 1em;
|
||||
right: .2em
|
||||
}
|
||||
|
||||
& .score-input {
|
||||
font-size: 80px;
|
||||
width: 55%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
& .suma {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
126
services/fichitas/src/index-v1.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html manifest="manifest.appcache">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Fichitas</title>
|
||||
|
||||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/assets/icons/icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/assets/icons/icon@2x.png" />
|
||||
|
||||
<link href="/assets/css/reset.css" rel="stylesheet" />
|
||||
<link href="/assets/css/main.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="no-webapp">
|
||||
<h1>Poop</h1>
|
||||
</div>
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div id="nuevo-juego" class="card hidden">
|
||||
<div class="card-upper card-part">
|
||||
<h1>Nuevo Juego</h1>
|
||||
<ul id="jugadores">
|
||||
<li data-jugadores="2" data-equipos="2">2 vs 2</li>
|
||||
<li data-jugadores="4">4 jugadores</li>
|
||||
<li data-jugadores="4">3 jugadores</li>
|
||||
<li data-jugadores="4">2 jugadores</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="separador card-part"></div>
|
||||
<div class="card-bottom card-part">
|
||||
<div class="patote"></div>
|
||||
<a href="#regresar" class="action-small">regresar</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="setup-juego" class="card hidden">
|
||||
<div class="card-upper card-part">
|
||||
<div class="flex top">
|
||||
<h1 id="tipo-juego">2 vs 2</h1>
|
||||
<h2>A <input type="number" min="0" range="1" value="100" id="max-puntos"/><span id="max-puntos-target">100</span> puntos</h2>
|
||||
</div>
|
||||
<div class="flex bottom">
|
||||
<h1>Nosotros</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separador separador-large card-part"><p>VS</p></div>
|
||||
<div class="card-bottom card-part">
|
||||
<div class="flex top">
|
||||
<h1>Ellos</h1>
|
||||
</div>
|
||||
|
||||
<div class="flex bottom">
|
||||
<a href="#regresar" class="action-small">comenzar</a>
|
||||
<a href="#comenzar" class="action-small">regresar</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="juego" class="card">
|
||||
<div class="card-upper card-part">
|
||||
<div class="flex top">
|
||||
<h2 id="numero-juego" class="first-h2">Primer juego</h2>
|
||||
</div>
|
||||
|
||||
<div class="flex bottom">
|
||||
<p id="player-1" class="score">00</p>
|
||||
<h1>Nosotros</h1>
|
||||
<ul id="scores-player-1" class="scores-list">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separador separador-large card-part">
|
||||
<p id="activa-resultados">VS</p>
|
||||
</div>
|
||||
<div class="card-bottom card-part">
|
||||
<div class="flex top">
|
||||
<ul id="scores-player-2" class="scores-list">
|
||||
</ul>
|
||||
<h1>Ellos</h1>
|
||||
<p class="score" id="player-2">00</p>
|
||||
</div>
|
||||
|
||||
<div class="flex bottom">
|
||||
<a id="terminar" href="#terminar" class="action-small">empezar de nuevo</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="resultado" class="card flip">
|
||||
<div class="card-part card-upper">
|
||||
<div class="flex top">
|
||||
<h2 class="first-h2">Resultados</h2>
|
||||
</div>
|
||||
<div class="flex bottom">
|
||||
<input type="tel" class="score" min="0" placeholder="0" id="score-player-1" />
|
||||
<h1>Nosotros</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separador separador-large card-part"><p>VS</p></div>
|
||||
<div class="card-part card-bottom">
|
||||
<div class="flex top">
|
||||
<h1>Ellos</h1>
|
||||
<input type="tel" class="score" min="0" placeholder="0" id="score-player-2" />
|
||||
</div>
|
||||
<div class="flex bottom">
|
||||
<button id="guardar">Guardar</button>
|
||||
<a id="cancelar" class="action-small">cancelar</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="/assets/js/jquery.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
97
services/fichitas/src/index.html
Normal file
@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html manifest="manifest.appcache">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Fichitas</title>
|
||||
|
||||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/assets/img/icons/icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/assets/img/icons/icon@2x.png" />
|
||||
|
||||
<link rel="apple-touch-startup-image" href="/assets/img/startup/320x460.png" media="screen and (max-device-width : 320px)">
|
||||
<link rel="apple-touch-startup-image" href="/assets/img/startup/640x920.png" media="(max-device-width : 480px) and (-webkit-min-device-pixel-ratio : 2)">
|
||||
<link rel="apple-touch-startup-image" href="/assets/img/startup/640x1096.png" media="(max-device-width : 548px) and (-webkit-min-device-pixel-ratio : 2)">
|
||||
<link rel="apple-touch-startup-image" sizes="1024x748" href="/assets/img/startup/1024x748.png" media="screen and (min-device-width : 481px) and (max-device-width : 1024px) and (orientation : landscape)">
|
||||
<link rel="apple-touch-startup-image" sizes="768x1004" href="/assets/img/startup/768x1004.png" media="screen and (min-device-width : 481px) and (max-device-width : 1024px) and (orientation : portrait)">
|
||||
<link rel="apple-touch-startup-image" sizes="2048x1496" href="/assets/img/startup/2048x1496.png" media="screen and (-webkit-min-device-pixel-ratio : 2) and (min-device-width : 481px) and (max-device-width : 2048px) and (orientation : landscape)">
|
||||
<link rel="apple-touch-startup-image" sizes="1536x2008" href="/assets/img/startup/1536x2008.png" media="screen and (-webkit-min-device-pixel-ratio : 2) and (min-device-width : 481px) and (max-device-width : 2048px) and (orientation : portrait)">
|
||||
|
||||
<link href="/assets/css/main.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section id="game" class="screen shown">
|
||||
<div class="nav">
|
||||
<h1 id="game-name">Primer Juego</h1>
|
||||
<a class="nav-icon icono round-icon" id="config-button" href="#config">settings</a>
|
||||
</div>
|
||||
|
||||
<section id="players">
|
||||
<script type="text/html" id="player-tpl">
|
||||
<div id="player-{{id}}" class="player">
|
||||
<h1 class="player-name">{{name}}</h1>
|
||||
<div class="score-box">
|
||||
<div class="score">{{#renderScore}}{{a}}{{/renderScore}}</div>
|
||||
<div class="loss">
|
||||
<a class="for-more-players player-save plus icono round-icon" data-modifies="#player-{{id}}-score">check</a>
|
||||
<input type="number" id="player-{{id}}-score" class="score-input" placeholder="0" min="0" max="99" pattern="\d*" />
|
||||
<div class="score-action-buttons">
|
||||
<span class="cell">
|
||||
<a class="player-add plus icono round-icon" data-modifies="#player-{{id}}-score">plus</a>
|
||||
</span>
|
||||
<span class="cell">
|
||||
<a class="for-2-players player-save plus icono round-icon" data-modifies="#player-{{id}}-score">check</a>
|
||||
</span>
|
||||
</div>
|
||||
<ul class="suma">
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</section>
|
||||
<a role="navigation-button" class="for-more-players button" id="finish-game" href="#juego">Terminar partida</a>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="config" class="screen 2-boxes ashown">
|
||||
<a class="nav-icon icono round-icon" id="back" href="#game" data-action="saveConfig">back</a>
|
||||
|
||||
<div class="box">
|
||||
<h1>Jugadores</h1>
|
||||
<div class="config-element">
|
||||
<span class="cell">
|
||||
<a role="action-button" class="minus icono round-icon" data-modifies="#jugadores" data-action="minus">minus</a>
|
||||
</span>
|
||||
<input class="cell" type="number" id="jugadores" value="2" min="2" max="4" step="1" pattern="\d*" />
|
||||
<span class="cell">
|
||||
<a role="action-button" class="plus icono round-icon" data-modifies="#jugadores" data-action="plus">plus</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h1>Puntos</h1>
|
||||
<div class="config-element">
|
||||
<span class="cell">
|
||||
<a role="action-button" class="minus round-icon icono" data-modifies="#puntos" data-action="minus">minus</a>
|
||||
</span>
|
||||
<input class="cell" type="number" id="puntos" value="100" min="2" max="950" step="50" pattern="\d*" />
|
||||
<span class="cell">
|
||||
<a role="action-button" class="plus round-icon icono" data-modifies="#puntos" data-action="plus">plus</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a role="navigation-button" class="button" id="restart-game" href="#juego">Empezar de nuevo</a>
|
||||
|
||||
</section>
|
||||
|
||||
<script src="/assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
10
services/fichitas/src/manifest.appcache
Normal file
@ -0,0 +1,10 @@
|
||||
CACHE MANIFEST
|
||||
#v0.0.9
|
||||
|
||||
CACHE:
|
||||
/assets/css/main.css
|
||||
/assets/js/main.js
|
||||
/assets/fonts/ss-pika.woff
|
||||
/assets/fonts/ss-pika.svg
|
||||
/assets/fonts/ss-pika.ttf
|
||||
/assets/fonts/ss-pika.eot
|
6
services/hoynocircula/hoynocircula.spec.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
description: Se me olvidaba qué día circulaba cuando tenía auto
|
||||
packages: {}
|
||||
build: exit
|
||||
deploy:
|
||||
credentials: vault://nidito/deploy/hoynocircula.pati.to
|
||||
src: ./src
|
73
services/hoynocircula/hoynocircula.tf
Normal file
@ -0,0 +1,73 @@
|
||||
terraform {
|
||||
backend "consul" {
|
||||
path = "nidito/state/service/hoynocircula.pati.to"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
consul = {
|
||||
source = "hashicorp/consul"
|
||||
version = "~> 2.21.0"
|
||||
}
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.4.0"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.29.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.0.0"
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "DO" {
|
||||
path = "cfg/infra/tree/provider:digitalocean"
|
||||
}
|
||||
|
||||
provider "digitalocean" {
|
||||
token = data.vault_generic_secret.DO.data.patito
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "backblaze" {
|
||||
path = "cfg/infra/tree/provider:backblaze"
|
||||
}
|
||||
|
||||
data "terraform_remote_state" "rob_mx" {
|
||||
backend = "consul"
|
||||
workspace = "default"
|
||||
config = {
|
||||
datacenter = "casa"
|
||||
path = "nidito/state/rob.mx"
|
||||
}
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "service" {
|
||||
domain = "pati.to"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
name = "hoynocircula"
|
||||
value = data.terraform_remote_state.rob_mx.outputs.bernal.ip
|
||||
}
|
||||
|
||||
resource "consul_keys" "cdn-config" {
|
||||
datacenter = "qro0"
|
||||
key {
|
||||
path = "cdn/hoynocircula.pati.to"
|
||||
value = jsonencode({
|
||||
cert = "pati.to"
|
||||
folder = "hoynocircula.pati.to"
|
||||
nginx_config = file("${abspath(path.root)}/nginx.conf")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_kv_secret" "deploy-config" {
|
||||
path = "nidito/deploy/hoynocircula.pati.to"
|
||||
data_json = jsonencode({
|
||||
type = "ssh"
|
||||
host = "bernal"
|
||||
domain = "hoynocircula.pati.to"
|
||||
})
|
||||
}
|
||||
|
3
services/hoynocircula/nginx.conf
Normal file
@ -0,0 +1,3 @@
|
||||
location / {
|
||||
index index.html;
|
||||
}
|
BIN
services/hoynocircula/src/img/bg.jpg
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
services/hoynocircula/src/img/icons/icon-ipad.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
services/hoynocircula/src/img/icons/icon-ipad@2x.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
services/hoynocircula/src/img/icons/icon-iphone.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
services/hoynocircula/src/img/icons/icon-iphone@2x.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
3053
services/hoynocircula/src/img/icons/icons.ai
Normal file
BIN
services/hoynocircula/src/img/og-icon.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
12
services/hoynocircula/src/img/pato.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
|
||||
<path fill="#D91C5C" d="M69.111,23.025c0,0-3.731-7.188-9.167-7.987c-5.415-0.799-14.494,0.518-19.736,4.978
|
||||
c-5.242,4.443-5.611,16.807-2.31,19.558c3.28,2.756,3.47,4.366,2.5,5.176c-0.984,0.782-3.219,3.814-14.164-2.15
|
||||
c-10.92-5.959-13.508-8.098-15.544-2.668c-2.056,5.43-1.337,41.716,28.636,44.732c29.956,3.031,38.979-14.949,31.742-28.637
|
||||
c-4.371-8.257-8.274-9.321-5.33-15.478c0,0,3.163,0.733,6.003-2.464c2.85-3.186,8.737-0.821,11.681-1.615
|
||||
c2.942-0.821,6.769-1.968,5.793-5.7l0.717-0.893c0,0,0.165-1.417-0.017-2.48c-0.165-1.07-1.422-2.045-2.491-1.869
|
||||
c-1.06,0.176-6.482,2.034-9.956,1.334c-3.461-0.717-6.135-3.732-7.38-3.473C70.088,23.389,68.936,23.742,69.111,23.025z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
128
services/hoynocircula/src/index.html
Normal file
@ -0,0 +1,128 @@
|
||||
<!DOCTYPE html>
|
||||
<html manifest="manifest.appcache">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Hoy chance circulo</title>
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width" />
|
||||
|
||||
<!-- Web app -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-title" content="¿Circulo?">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
|
||||
<!-- iOS icons -->
|
||||
<link rel="apple-touch-icon" href="img/icons/icon-iphone.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="img/icons/icon-ipad.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="img/icons/icon-iphone@2x.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="img/icons/icon-ipad@2x.png">
|
||||
|
||||
<!-- open graph -->
|
||||
<meta property="og:description" content="Usa este app para saber cuándo y porqué circulas en la megalópolis" />
|
||||
<meta property="og:title" content="Hoy (chance) circulo" />
|
||||
<meta property="fb:admins" content="792675081" />
|
||||
<meta property="og:image" content="http://hoynocircula.pati.to/img/og-icon.png" />
|
||||
<meta property="og:url" content="http://hoynocircula.pati.to" />
|
||||
<meta itemprop="name" content="¿Sabes si circula tu vehículo hoy en DF?" />
|
||||
<meta itemprop="description" content="Usa este app para saber cuándo y porqué circulas en la megalópolis" />
|
||||
<meta itemprop="image" content="http://hoynocircula.pati.to/img/share-icon.png" />
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@peeseeme">
|
||||
<meta name="twitter:title" content="Hoy (chance) circulo">
|
||||
<meta name="twitter:description" content="Usa este app para saber cuándo y porqué circulas en la megalópolis">
|
||||
<meta name="twitter:creator" content="@peeseeme">
|
||||
<meta name="twitter:image:src" content="http://hoynocircula.pati.to/img/share-icon.png">
|
||||
<meta name="twitter:domain" content="http://hoynocircula.pati.to">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Ubuntu:400,700,300italic' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="main.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>¿Circulo hoy en DF?</h1>
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div id="card">
|
||||
<main class="side front">
|
||||
<section id="setup" class="hidden">
|
||||
<p>¿Cuales son los dígitos de tu placa?</p>
|
||||
<input id="placa" type="number" min="0" max="9999" step="1" placeholder="4242" pattern="\d*"/>
|
||||
<p>¿Qué número de holograma tienes?</p>
|
||||
|
||||
<ul id="hologramas">
|
||||
<li class="holograma">
|
||||
<label>
|
||||
<input type="radio" name="holograma" value="0" />
|
||||
Cero
|
||||
</label>
|
||||
</li>
|
||||
<li class="holograma">
|
||||
<label>
|
||||
<input type="radio" name="holograma" value="1" />
|
||||
1
|
||||
</label>
|
||||
</li>
|
||||
<li class="holograma">
|
||||
<label>
|
||||
<input type="radio" name="holograma" value="2" />
|
||||
2
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button id="guardar-datos">Listo</button>
|
||||
</section>
|
||||
|
||||
<section id="result" class="hidden">
|
||||
<h2 id="hoy-circulo"></h2>
|
||||
<span id="warn"></span>
|
||||
<p id="razon"></p>
|
||||
|
||||
<div class="actions">
|
||||
<a id="reset" href="#setup">Cambiar datos</a>
|
||||
</section>
|
||||
<a href="#switch" class="flippy">ayuda</a>
|
||||
</main>
|
||||
|
||||
<div id="info" class="side back">
|
||||
<a href="#switch" class="flippy">regresar</a>
|
||||
<h2>¿Cómo funciona esto?</h2>
|
||||
<p>Usamos la información de <a href="http://www.sedema.df.gob.mx" title="Secretaría del Medio Ambiente">SEDEMA</a> para calcular los días en los que tu automovil no circula, en función de la placa y holograma del mismo.</p>
|
||||
<p>Todo el código vive en <a href="https://github.com/unRob/cuando-circulo" title="Repo en github">github</a>.</p>
|
||||
|
||||
<h2>¿Guardan los datos de mi auto?</h2>
|
||||
<p><strong>No</strong>, ni se transmiten ni almacenan por nuestra parte, simplemente se guardan dentro de tu computadora o teléfono, y nosotros no tenemos acceso a los mismos.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<a href="http://surrealista.mx" title="Partido Surrealista Mexicano">
|
||||
<img src="img/pato.svg" title="patito" alt="mooo" />
|
||||
Partido Surrealista Mexicano
|
||||
</a>
|
||||
</footer>
|
||||
|
||||
|
||||
<script src="lib/programa.js"></script>
|
||||
<script src="lib/auto.js"></script>
|
||||
<script src="lib/localizador.js"></script>
|
||||
<script src="lib/circula.js"></script>
|
||||
<script src="main.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-37922009-3', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
35
services/hoynocircula/src/lib/auto.js
Normal file
@ -0,0 +1,35 @@
|
||||
(function(){
|
||||
var Programa = (function(w){
|
||||
if (typeof module === 'undefined') {
|
||||
return window.Programa;
|
||||
} else {
|
||||
return require('./programa');
|
||||
}
|
||||
})();
|
||||
|
||||
var Auto = function(placa, holograma){
|
||||
this.placa = placa;
|
||||
this.holograma = parseInt(holograma, 10);
|
||||
|
||||
this.info = Programa.terminaciones[this.ultimo_digito()];
|
||||
return this;
|
||||
};
|
||||
|
||||
Auto.prototype.ultimo_digito = function(){
|
||||
return parseInt(this.placa.toString().match(/(\d)\b/)[0]);
|
||||
};
|
||||
|
||||
Auto.prototype.proxima_verificacion = function(fecha) {
|
||||
var fecha = fecha || new Date();
|
||||
var meses = this.info.verifica;
|
||||
var esteMes = fecha.getMonth();
|
||||
};
|
||||
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = Auto;
|
||||
} else {
|
||||
window.Auto = Auto;
|
||||
}
|
||||
|
||||
})();
|
130
services/hoynocircula/src/lib/circula.js
Normal file
@ -0,0 +1,130 @@
|
||||
(function(){
|
||||
|
||||
var entre_semana = function(auto, date) {
|
||||
if (auto.holograma === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return auto.info.descansa !== date.getDay();
|
||||
};
|
||||
var los_sabados = function(auto, date) {
|
||||
if (auto.holograma === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto.holograma === 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//es 1 entonces..
|
||||
|
||||
var sabados = (function(dia){
|
||||
dia = new Date(dia);
|
||||
var mes = dia.getMonth();
|
||||
var ret = [];
|
||||
while (dia.getMonth() === mes) {
|
||||
if (dia.getDay() === 6)
|
||||
ret.push(dia.getDate());
|
||||
dia = new Date(dia.setDate(dia.getDate()+1));
|
||||
}
|
||||
return ret;
|
||||
})(date.setDate(1));
|
||||
|
||||
var numSabado = sabados.indexOf(date.getDay())+1;
|
||||
if (numSabado === 5) {
|
||||
// Sólo holograma 2 deja de circular el quinto sábado del mes
|
||||
return true;
|
||||
}
|
||||
|
||||
var par = auto.ultimo_digito() % 2 === 0;
|
||||
return (numSabado%2===0) ? par : !par;
|
||||
|
||||
};
|
||||
|
||||
var sabados_descansa = function(auto, circula) {
|
||||
circula = circula || false;
|
||||
switch (auto.holograma) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
var placaPar = (auto.ultimo_digito() % 2 === 0);
|
||||
var impar = 'el primer y tercer sábado';
|
||||
var par = 'el segundo y cuarto sábado';
|
||||
return placaPar ? par : impar;
|
||||
case 2:
|
||||
return "todos los sábados";
|
||||
}
|
||||
};
|
||||
|
||||
var Circula = function(auto, fecha) {
|
||||
var r = {};
|
||||
if (auto.holograma === 0) {
|
||||
r.circula = true;
|
||||
r.razon = "Tú circulas todos los días, chatoa!";
|
||||
} else {
|
||||
fecha = fecha || new Date();
|
||||
var numDia = fecha.getDay();
|
||||
|
||||
var dia_descanso = Localizador(auto.info.descansa);
|
||||
|
||||
if (numDia === 0) {
|
||||
r.circula = true;
|
||||
r.razon = "Todos los vehículos circulan el día domingo. Tu vehículo descansa todos los "+dia_descanso;
|
||||
ds = sabados_descansa(auto);
|
||||
r.razon += ds && " y "+ds+" del mes";
|
||||
} else if (numDia <= 5) {
|
||||
r.circula = entre_semana(auto, fecha);
|
||||
info = auto.info;
|
||||
r.razon = r.circula ?
|
||||
"Los vehículos engomado color "+auto.info.nombre+" circulan hoy y descansan el "+dia_descanso :
|
||||
"Los vehículos con placa terminación "+auto.ultimo_digito()+" no circulan los días "+Localizador(numDia);
|
||||
} else {
|
||||
r.circula = los_sabados(auto, fecha);
|
||||
r.razon = "Tu vehículo holograma "+auto.holograma+" ";
|
||||
|
||||
if (auto.holograma == 2) {
|
||||
r.razon += "no circula ningún sábado del mes";
|
||||
} else {
|
||||
var placaPar = (auto.ultimo_digito() % 2);
|
||||
var numero = '';
|
||||
var impar = 'primer y tercer';
|
||||
var par = 'segundo y cuarto';
|
||||
if (r.circula) {
|
||||
r.razon += " circula el "+
|
||||
(placaPar ? impar : par)+
|
||||
" sábado del mes";
|
||||
} else {
|
||||
r.razon += " no circula el "+
|
||||
(placaPar ? par : impar)+
|
||||
" sábado del mes";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
r.razon += '.';
|
||||
|
||||
if (!r.circula) {
|
||||
antes5 = (fecha.getHours() < 5);
|
||||
despues10 = (fecha.getHours() > 21);
|
||||
|
||||
if (antes5 || despues10) {
|
||||
r.circula = true;
|
||||
r.warn = antes5 ? "No circulas de 5:00am a 10:00pm" : "Sólamente pasado de las 10:00pm";
|
||||
} else {
|
||||
r.warn = "Sólo circulas después de las 10:00pm";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = Circula;
|
||||
Localizador = require('./localizador');
|
||||
} else {
|
||||
window.Circula = Circula;
|
||||
}
|
||||
|
||||
})();
|
23
services/hoynocircula/src/lib/localizador.js
Normal file
@ -0,0 +1,23 @@
|
||||
(function(){
|
||||
|
||||
var Localizador = function(i, tipo) {
|
||||
tipo = tipo || 'dias';
|
||||
var type = (typeof i).toLowerCase();
|
||||
var opts = Localizador[tipo];
|
||||
if (type === 'string' || type === 'number') {
|
||||
return opts[i-1];
|
||||
} else {
|
||||
return i.map(function(periodo){ return opts[periodo-1]; });
|
||||
}
|
||||
};
|
||||
|
||||
Localizador.dias = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];
|
||||
Localizador.meses = ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'];
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = Localizador;
|
||||
} else {
|
||||
window.Localizador = Localizador;
|
||||
}
|
||||
|
||||
})();
|
30
services/hoynocircula/src/lib/programa.js
Normal file
@ -0,0 +1,30 @@
|
||||
(function(){
|
||||
var Programa = {
|
||||
engomado: {
|
||||
verde: {nombre: 'verde', color: "#339900", verifica: [3,4,9,10], descansa: 4},
|
||||
rojo: {nombre: 'rojo', color: "#ff3333", verifica: [2,3,8,9], descansa: 3},
|
||||
amarillo: {nombre: 'amarillo', color: "#ffff66", verifica: [0,1,6,7], descansa: 1},
|
||||
rosa: {nombre: 'rosa', color: "#ff99cc", verifica: [1,2,7,8], descansa: 2},
|
||||
azul: {nombre: 'azul', color: "#66ccff", verifica: [5,6,10,11],descansa: 5}
|
||||
}
|
||||
};
|
||||
Programa.terminaciones = {
|
||||
1: Programa.engomado.verde,
|
||||
2: Programa.engomado.verde,
|
||||
3: Programa.engomado.rojo,
|
||||
4: Programa.engomado.rojo,
|
||||
5: Programa.engomado.amarillo,
|
||||
6: Programa.engomado.amarillo,
|
||||
7: Programa.engomado.rosa,
|
||||
8: Programa.engomado.rosa,
|
||||
9: Programa.engomado.azul,
|
||||
0: Programa.engomado.azul
|
||||
};
|
||||
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = Programa;
|
||||
} else {
|
||||
window.Programa = Programa;
|
||||
}
|
||||
})();
|
279
services/hoynocircula/src/main.css
Normal file
@ -0,0 +1,279 @@
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #666 url('img/bg.jpg') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
font: 16px/20px 'Ubuntu', 'Futura', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
|
||||
#container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
margin-top: 1em;
|
||||
position: relative;
|
||||
-webkit-perspective: 800px;
|
||||
}
|
||||
|
||||
#container:after {
|
||||
content: ' ';
|
||||
display: table;
|
||||
}
|
||||
|
||||
#card {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transition: -webkit-transform 1s;
|
||||
-moz-transition: -moz-transform 1s;
|
||||
-o-transition: -o-transform 1s;
|
||||
transition: transform 1s;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
-moz-transform-style: preserve-3d;
|
||||
-ms-transform-style: preserve-3d;
|
||||
-o-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#card.flipped {
|
||||
-webkit-transform: rotateY( 180deg );
|
||||
-moz-transform: rotateY( 180deg );
|
||||
-ms-transform: rotateY( 180deg );
|
||||
-o-transform: rotateY( 180deg );
|
||||
transform: rotateY( 180deg );
|
||||
}
|
||||
|
||||
|
||||
.side {
|
||||
display: block;
|
||||
width: 100%;
|
||||
top: 0px;
|
||||
position: absolute;
|
||||
background: rgba(255,255,255,.9);
|
||||
padding: 1em;
|
||||
|
||||
box-shadow: 0px 0px 3px rgba(0,0,0,.4);
|
||||
box-sizing: border-box;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
-o-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.side.back {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
-webkit-transform: rotateY( 180deg );
|
||||
-moz-transform: rotateY( 180deg );
|
||||
-ms-transform: rotateY( 180deg );
|
||||
-o-transform: rotateY( 180deg );
|
||||
transform: rotateY( 180deg );
|
||||
}
|
||||
|
||||
.flippy {
|
||||
display: block;
|
||||
color: #777;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-size: .8em;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
-o-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.flippy:hover {
|
||||
color: #333;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
h1, h2 {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
line-height: 2em;
|
||||
color: #fff;
|
||||
text-shadow: 2px 2px 5px #000;
|
||||
}
|
||||
|
||||
@media all and (max-width: 600px) {
|
||||
#container {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.7em;
|
||||
line-height: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Setup */
|
||||
|
||||
input[type=number] {
|
||||
font: inherit;
|
||||
display: block;
|
||||
font-size: 2em;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
line-height: 1em;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#hologramas {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: -webkit-flex;
|
||||
display: -moz-flex;
|
||||
display: -ms-flex;
|
||||
display: -o-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: row;
|
||||
-moz-flex-direction: row;
|
||||
-ms-flex-direction: row;
|
||||
-o-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
||||
.holograma {
|
||||
display: block;
|
||||
list-style: none;
|
||||
-webkit-flex: 1 1 auto;
|
||||
-moz-flex: 1 1 auto;
|
||||
-o-flex: 1 1 auto;
|
||||
-ms-flex: 1 1 auto;
|
||||
flex: 1 1 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.holograma label {
|
||||
display: block;
|
||||
margin: 0 10px;
|
||||
background: #ddd;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.holograma input {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
background: #1FAD80;
|
||||
color: #116148;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
font: inherit;
|
||||
font-weight: bold;
|
||||
letter-spacing: .2em;
|
||||
text-transform: uppercase;
|
||||
margin: 1em 0 0;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
color: #fff;
|
||||
background: #116148;
|
||||
}
|
||||
|
||||
|
||||
/* Result */
|
||||
#hoy-circulo {
|
||||
font-size: 3em;
|
||||
color: #fff;
|
||||
line-height: 1.5em;
|
||||
width: 100%;
|
||||
box-sizing: padding-box;
|
||||
padding: 0 .5em;
|
||||
margin-left: -.5em;
|
||||
box-shadow: 0px 2px 3px rgba(0,0,0,.5);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#hoy-circulo.yay {
|
||||
background: #1FAD80;
|
||||
}
|
||||
|
||||
#hoy-circulo.nay {
|
||||
background: #9B0C0C;
|
||||
}
|
||||
|
||||
#hoy-circulo.warn {
|
||||
background: #E0A21C;
|
||||
}
|
||||
|
||||
#warn {
|
||||
text-align: center;
|
||||
display: block;
|
||||
color: #9B0C0C;
|
||||
font-size: 1.5em;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
#razon {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#result a {
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
font-weight: 200;
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#result a:hover {
|
||||
color: #666;
|
||||
text-decoration: underline;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
color: #fff;
|
||||
text-shadow: 0px 0px 4px #000;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer a {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
footer img {
|
||||
display: block;
|
||||
max-width: 45px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
117
services/hoynocircula/src/main.js
Normal file
@ -0,0 +1,117 @@
|
||||
/*jshint expr:true */
|
||||
var VERSION = '0.0.3';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function(){
|
||||
|
||||
var storage = window.localStorage;
|
||||
|
||||
var _show = function(el) {el = el.container || el; el.classList.remove('hidden');};
|
||||
var _hide = function(el) {el = el.container || el; el.classList.add('hidden');};
|
||||
var DOM = {
|
||||
setup: {
|
||||
container: document.querySelector('#setup'),
|
||||
placa: document.querySelector('#placa'),
|
||||
hologramas: document.getElementsByName('holograma'),
|
||||
valueFor: function(el) {
|
||||
if (el === 'placa') {
|
||||
return DOM.setup.placa.value.replace(/\D/g, '+');
|
||||
} else if (el === 'holograma') {
|
||||
return (function(els){
|
||||
var num;
|
||||
[].forEach.call(els, function(el){
|
||||
if (el.checked) {
|
||||
num = el.value;
|
||||
}
|
||||
});
|
||||
return parseInt(num, 10);
|
||||
})(DOM.setup.hologramas);
|
||||
}
|
||||
}
|
||||
},
|
||||
result: {
|
||||
container: document.querySelector('#result'),
|
||||
header: document.querySelector('#hoy-circulo'),
|
||||
razon: document.querySelector('#razon'),
|
||||
warn: document.querySelector('#warn')
|
||||
}
|
||||
};
|
||||
|
||||
var Actions = {
|
||||
Reset: function(evt) {
|
||||
evt && evt.preventDefault();
|
||||
_show(DOM.setup);
|
||||
_hide(DOM.result);
|
||||
},
|
||||
Setup: function(evt) {
|
||||
evt && evt.preventDefault();
|
||||
var placa = DOM.setup.valueFor('placa');
|
||||
var holograma = DOM.setup.valueFor('holograma');
|
||||
|
||||
if (!placa || placa.length < 3 || placa.length > 4) {
|
||||
|
||||
alert("Parece que no has introducido correctamente los datos de tu placa :(");
|
||||
DOM.setup.placa.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if ([0,1,2].indexOf(holograma) < 0) {
|
||||
alert("Es necesario que elijas el holograma de tu vehículo");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('storing...');
|
||||
storage.placa = placa;
|
||||
storage.holograma = holograma;
|
||||
Actions.Result();
|
||||
},
|
||||
Result: function(){
|
||||
_show(DOM.result);
|
||||
_hide(DOM.setup);
|
||||
var d = new Date();
|
||||
var mi_auto = new Auto(storage.placa, storage.holograma);
|
||||
var clase;
|
||||
|
||||
var res = Circula(mi_auto, d);
|
||||
|
||||
clase = res.circula ? 'yay' : 'nay';
|
||||
if (res.warn) {
|
||||
DOM.result.warn.innerText = res.warn;
|
||||
clase = 'warn';
|
||||
_show(DOM.result.warn);
|
||||
} else {
|
||||
_hide(DOM.result.warn);
|
||||
}
|
||||
DOM.result.header.className = clase;
|
||||
DOM.result.header.innerText = res.circula ? 'Sí' : 'No';
|
||||
DOM.result.razon.innerText = res.razon;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
if (storage.placa && storage.holograma) {
|
||||
DOM.setup.placa.value = storage.placa;
|
||||
DOM.setup.hologramas[parseInt(storage.holograma, 10)].checked = 'checked';
|
||||
Actions.Result();
|
||||
} else {
|
||||
Actions.Reset();
|
||||
}
|
||||
|
||||
document.querySelector('#guardar-datos').addEventListener('mouseup', Actions.Setup);
|
||||
document.querySelector('#guardar-datos').addEventListener('touchend', Actions.Setup);
|
||||
document.querySelector('#reset').addEventListener('mousedown', Actions.Reset);
|
||||
document.querySelector('#reset').addEventListener('touchend', Actions.Reset);
|
||||
|
||||
var doFlip = function(evt){
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
var card = document.querySelector('#card');
|
||||
card.classList.toggle('flipped');
|
||||
return false;
|
||||
};
|
||||
|
||||
[].forEach.call(document.querySelectorAll('.flippy'), function(el) {
|
||||
el.addEventListener('click', doFlip, false);
|
||||
});
|
||||
|
||||
});
|
23
services/hoynocircula/src/manifest.appcache
Normal file
@ -0,0 +1,23 @@
|
||||
CACHE MANIFEST
|
||||
# v0.0.3-sigh nightlies
|
||||
# neta no se porqué uso esta mierda
|
||||
|
||||
#JS
|
||||
lib/auto.js
|
||||
lib/circula.js
|
||||
lib/localizador.js
|
||||
lib/programa.js
|
||||
|
||||
#HTML
|
||||
#index.html
|
||||
|
||||
#CSS
|
||||
main.css
|
||||
http://fonts.googleapis.com/css?family=Ubuntu:400,700,300italic
|
||||
|
||||
#IMG
|
||||
img/bg.jpg
|
||||
img/pato.svg
|
||||
|
||||
NETWORK:
|
||||
*
|
30
services/hoynocircula/src/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "cuando-circulo",
|
||||
"version": "0.0.3",
|
||||
"description": "¿Cuándo circulo en DF?",
|
||||
"main": "main.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jasmine-node spec"
|
||||
},
|
||||
"devDependencies" : {
|
||||
"jasmine-node": "~> 1.14.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com:unrob/cuando-circulo.git"
|
||||
},
|
||||
"keywords": [
|
||||
"hoy no circula",
|
||||
"df",
|
||||
"mexico"
|
||||
],
|
||||
"author": "Roberto Hidalgo",
|
||||
"license": "WTFPL",
|
||||
"bugs": {
|
||||
"url": "https://github.com/unrob/cuando-circulo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/unrob/cuando-circulo"
|
||||
}
|
52
services/hoynocircula/src/spec/_autos.js
Normal file
@ -0,0 +1,52 @@
|
||||
module.exports = [
|
||||
{
|
||||
nombre: "Local,H0",
|
||||
placa: 666,
|
||||
holograma: 0,
|
||||
ultimo_digito: 6,
|
||||
results: {
|
||||
lunes: true,
|
||||
viernes: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
nombre: "Local,Par,H1",
|
||||
placa: 420,
|
||||
holograma: 1,
|
||||
ultimo_digito: 0,
|
||||
results: {
|
||||
lunes: true,
|
||||
viernes: false,
|
||||
}
|
||||
},
|
||||
{
|
||||
nombre: "Local,Par,H2",
|
||||
placa: 420,
|
||||
holograma: 2,
|
||||
ultimo_digito: 0,
|
||||
results: {
|
||||
lunes: true,
|
||||
viernes: false,
|
||||
}
|
||||
},
|
||||
{
|
||||
nombre: "Local,Impar,H1",
|
||||
placa: 555,
|
||||
holograma: 1,
|
||||
ultimo_digito: 5,
|
||||
results: {
|
||||
lunes: false,
|
||||
viernes: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
nombre: "Local,Impar,H2",
|
||||
placa: 555,
|
||||
holograma: 2,
|
||||
ultimo_digito: 5,
|
||||
results: {
|
||||
lunes: false,
|
||||
viernes: true,
|
||||
}
|
||||
}
|
||||
];
|
15
services/hoynocircula/src/spec/auto-spec.js
Normal file
@ -0,0 +1,15 @@
|
||||
var Auto = require('../lib/auto');
|
||||
var autos = require('./_autos');
|
||||
|
||||
|
||||
describe("Últimos dígitos de las placas", function(){
|
||||
|
||||
it("debería mostrar los últimos dígitos de las placas", function(){
|
||||
autos.forEach(function(auto){
|
||||
var a = new Auto(auto.placa, auto.holograma);
|
||||
//console.log(a);
|
||||
expect(a.ultimo_digito()).toBe(auto.ultimo_digito);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
53
services/hoynocircula/src/spec/circula-spec.js
Normal file
@ -0,0 +1,53 @@
|
||||
var Auto = require('../lib/auto')
|
||||
var Circula = require('../lib/circula');
|
||||
var autos = require('./_autos');
|
||||
|
||||
describe('Con Holograma Cero', function(){
|
||||
|
||||
it("Debe permitir todos los dias", function(){
|
||||
autos.forEach(function(auto){
|
||||
if (auto.holograma == 0) {
|
||||
a = new Auto(auto.placa, auto.holograma);
|
||||
expect(Circula(a, 0).circula).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('Los lunes', function(){
|
||||
|
||||
var lunes = new Date(1898,10,21,16); // René Magritte
|
||||
|
||||
autos.forEach(function autoLunes(auto){
|
||||
var puede = auto.results.lunes;
|
||||
var accion = puede ? 'permitir' : 'negar';
|
||||
it("Debe "+accion+" a "+auto.nombre+" circular", function(){
|
||||
var a = new Auto(auto.placa, auto.holograma);
|
||||
expect(Circula(a, lunes).circula).toBe(auto.results.lunes);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('Los viernes', function(){
|
||||
|
||||
|
||||
var viernes = new Date(1879,02,14,5); // Albert Einstein
|
||||
|
||||
autos.forEach(function autoViernes(auto){
|
||||
var puede = auto.results.viernes;
|
||||
var accion = puede ? 'permitir' : 'negar';
|
||||
var a = new Auto(auto.placa, auto.holograma);
|
||||
|
||||
it("Debe "+accion+" a "+auto.nombre+':'+a.info.descansa+" circular", function(){
|
||||
expect(auto.results.viernes)
|
||||
.toBe(Circula(a, viernes).circula);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
3
services/representantes/nginx.conf
Normal file
@ -0,0 +1,3 @@
|
||||
location / {
|
||||
return 301 https://github.com/unRob/representantes.pati.to;
|
||||
}
|
4
services/representantes/representantes.spec.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
description: Herramienta para encontrar tu representante (circa 2010)
|
||||
packages: {}
|
||||
build: exit
|
||||
deploy: {}
|
74
services/representantes/representantes.tf
Normal file
@ -0,0 +1,74 @@
|
||||
terraform {
|
||||
backend "consul" {
|
||||
path = "nidito/state/service/representantes.pati.to"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
consul = {
|
||||
source = "hashicorp/consul"
|
||||
version = "~> 2.21.0"
|
||||
}
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.4.0"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.29.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.0.0"
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "DO" {
|
||||
path = "cfg/infra/tree/provider:digitalocean"
|
||||
}
|
||||
|
||||
provider "digitalocean" {
|
||||
token = data.vault_generic_secret.DO.data.patito
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "backblaze" {
|
||||
path = "cfg/infra/tree/provider:backblaze"
|
||||
}
|
||||
|
||||
data "terraform_remote_state" "rob_mx" {
|
||||
backend = "consul"
|
||||
workspace = "default"
|
||||
config = {
|
||||
datacenter = "casa"
|
||||
path = "nidito/state/rob.mx"
|
||||
}
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "service" {
|
||||
domain = "pati.to"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
name = "representantes"
|
||||
value = data.terraform_remote_state.rob_mx.outputs.bernal.ip
|
||||
}
|
||||
|
||||
resource "consul_keys" "cdn-config" {
|
||||
datacenter = "qro0"
|
||||
key {
|
||||
path = "cdn/representantes.pati.to"
|
||||
value = jsonencode({
|
||||
cert = "pati.to"
|
||||
folder = "representantes.pati.to"
|
||||
nginx_config = file("${abspath(path.root)}/nginx.conf")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
# site disabled, redirects to github
|
||||
# resource "vault_kv_secret" "deploy-config" {
|
||||
# path = "nidito/deploy/representantes.pati.to"
|
||||
# data_json = jsonencode({
|
||||
# type = "ssh"
|
||||
# host = "bernal"
|
||||
# domain = "representantes.pati.to"
|
||||
# })
|
||||
# }
|
||||
|
26
terraform/main.tf
Normal file
@ -0,0 +1,26 @@
|
||||
terraform {
|
||||
backend "consul" {
|
||||
path = "nidito/state/pati.to"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.43.0"
|
||||
}
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.0.0"
|
||||
}
|
||||
|
||||
data "vault_generic_secret" "do_token" {
|
||||
path = "cfg/infra/tree/provider:digitalocean"
|
||||
}
|
||||
|
||||
provider "digitalocean" {
|
||||
token = data.vault_generic_secret.do_token.data.patito
|
||||
}
|
3
terraform/pati.to.tf
Normal file
@ -0,0 +1,3 @@
|
||||
resource "digitalocean_domain" "pati_to" {
|
||||
name = "pati.to"
|
||||
}
|