Marcos Dione: identity-countries-languages-and-currencies

I started watching PyCon's videos. One of the first ones I saw is Amber Brown's "How we do identity wrong". I think she[1] is right in raising not only the notion of not assuming things related to names, addresses and ID numbers, but also that you shouldn't be collecting information that you don't need; at some point, it becomes a liability.

In the same vein about assuming, I have more examples. One of them is deciding what language you show your site depending on what country the client connects form. I'm not a millennial (more like a transmillennial, if you push me to it), but I tend to go places. Every time I go to a new place, I get sites in new languages, but maps in US!

Today I wanted to book a hotel room. The hotel's site asked me where do I live, so I chose France. Fact is, for them country and language is the same thing (I wonder what would happen if I answer Schweiz/Suisse/Svizzera/Svizra), so I can't say that I live in France but prefer English, so I chose United Kingdom instead. Of course, this also meant that I got prices in GBP, not EUR, so I had to correct that one too. At least I could.

Later they asked me country of residence and nationality; when I chose italian, the country was set to Italia, even when I chose France first!

I leave you all with an anecdote. As I said, I lake to go places, most of the times with friends. Imagine the puzzled expression of the police officer that stopped us to find a car licensed in France, driven by an italian, with an argentinian, a spanish and a chilean passangers, crossing from Austria to Slovakia, listening to US music. I only forgot to put the GPS in japanese or something.

So, don't assume; if you assume, let the user change settings to their preferences, and don't ask for data you don't actually need. And please use the user's Accept-Language header; they have it for a reason.


[1] I think that's the pronoun she[1] said she[1] preferred. I'm sorry if I got that wrong.


python misc

Facundo Batista: Películas, con mejores trailers

La lista de películas vistas (y más abajo, las nuevas marcadas para ver), pero con novedad con respecto a los trailers.

Hace un tiempo les había comentado sobre un script para ver los trailers. Bueno, lo renové completamente: ahora usa como fuente a IMDb.

La gran ventaja es que dejó de mostrarme "los cinco tanques de hollywood más un puñado de otras cositas" y ahora veo trailers de esas películas más otras argentinas, españolas, francesas, italianas, alemanas, etc. Gané muchísimo en diversidad en ese sentido.

La primera o segunda vez que lo usen quizás les traiga demasiadas ofertas, pero luego se pasa. Es que cada tanto ofrece películas viejas o series, pero como el script se acuerda de lo que uno vio o no quiso ver, entonces si vuelven a aparecer ya las ignora.

En fin, las películas vistas...

  • ARQ: +0. Es un poco gastada la idea del loop de tiempo, y la base científica es fruta, pero toda la vuelta que le pegaron alrededor de eso está buena.
  • Approaching the Unknown: -0. Con muchas partes interesantes acerca de la psicología del viajar sólo al espacio... pero en general un embole.
  • Boyhood: +1. Arranca un poco lento, pero después te atrapa; es muy loco que sea una película filmada a lo largo de 12 años con todos creciendo/envejeciendo en la realidad.
  • Captain Fantastic: +1. Hermosa, por donde se la mire. Cuantas cosas que te hace replantear, repensar. De cabecera.
  • Colossal: +0. Muy linda película acerca de reencontrarse a uno mismo, pero desde un punto de vista totalmente extraño, inesperado y rarísimo.
  • Complete Unknown: +0. Podría ser más dinámica en algunas partes, pero la historia y el planteo general son muy buenos.
  • Embers: -0. Una buena idea, en una película que no tiene mucha historia, aunque muestra muy bien lo angustiante del asunto...
  • High-Rise: +0. Bastante bizarra, pero muestra de forma interesante cómo una sociedad se va al carajo (onda Lord of the Flies, pero en un rascacielos).
  • Kong: Skull Island: +1. Aunque la historia es obviamente conocida, la forma de contarla (especialmente la visión sobre los militares) está muy bien. Y la fotografía y la música son maravillosas.
  • Kóblic: +0. La historia está buena, la peli es un poco lenta pero zafa. La actuación de Oscar Martinez es genial.
  • Learning to Drive: +0. Una película chiquita sobre dos personas muy distintas y como terminan ayudándose tanto, muy linda historia.
  • Manhattan Night: -0. La historia es interesante, las actuaciones también... la cadencia de la película es medio insoportable... muy cansina, con una voz en off que explica todo el tiempo... no me gustó.
  • Marauders: +0. Parece ser la historia adaptada de un libro, por cómo condensa situaciones en pocos segundos, y está bastante bien a ese nivel, pero no me gustó como estaba armada la película en sí, no sé... "el ritmo"...
  • Miss Peregrine's Home for Peculiar Children: +0. Me gustó la eterna sucesión de cosas raras, por eso uno busca a Burton, no? Pero después no tuvo mucho más...
  • Star Wars: The Last Jedi: +0. No tan buena como la primera de la nueva saga, pero zafa y cuenta bastante.
  • The 9th Life of Louis Drax: +0. rara, arrancando mucho más lento de lo que debía, pero con una historia interesante de fondo.
  • The Accountant: +1. Me esperaba algo así como la clásica de peleas y tiros, pero me sorprendió mucho para bien (aunque sigue siendo una de peleas y tiros...).
  • The Dark Tower: -1. Estoy indignado, no la vean. Es como haber reducido los tres tomos del Señor de los Anillos a un cuento de siete páginas.
  • The Driftless Area: +0. Linda, muy rara, muchos detalles interesantes, pero un poco demasiado lenta...
  • The Lobster: -0. Demasiado absurda, demasiado volada, aunque no deja de tener partes bastante interesantes...
  • The Magnificent Seven: +0. Está buena, aunque es sólo una de pistoleros del "viejo oeste"... pero está buena... aunque es sólo (etc).
  • The Mummy: -0. Tiene un par de vueltas más que interesantes, pero resulta ser "otra peli de tom cruise", todas tan parecidas!
  • The Reality of Truth: -1. Me hartó en solo 10 minutos el chamuyo de contar medias experiencias saltando a "verdades absolutas" utilizando el camino de dos frases bien construidas. No vale la pena.
  • Urge: -0. La forma de eliminar la humanidad: dejando que se comporte como es. La idea está buena, pero la película es demasiado volada por un lado, y demasiado pacata por otro.
  • Welcome to Happiness: +0. Muy bizarra, simpática, y un poco rara con los ritmos. Pero bien.
  • Wonder Woman: +0. Entretenida, pero sólo una de superheroes...
  • Zipper: -0. Termina con algún giro interesante, pero es tan predecible todo que ni vale la pena.
El rey (not Elvis)

Las nuevas! Lo que decía arriba, no todos "tanques joliwudenses"...

  • 25 km/h: (2018; Comedy) - [D: Markus Goller; A: Franka Potente, Alexandra Maria Lara, Jördis Triebel]
  • 27: The Cursed Club: (2018; Action, Comedy, Crime, Fantasy, Mystery) At night in the hottest summer in 20 years, Leandro De La Torre, famous punk singer, shoots out of a window and hits the roof of a car. It is the day of his 27th birthday. Paula, a young fan of twenty-one years old, records everything with her cell phone. Far from knowing that in that video is the key behind the murder of the musician. Martín Lombardo, a staunch supporter of Racing, is the detective in charge of investigating the case. Along with Paula you will discover the conspiracy behind the deaths of all famous rockers at 27 years old. Jimi Hendrix, Janis Joplin, Amy Winehouse, Sid Vicious and Leandro De La Torre have a lot in common: in fact, they were all murdered. Paula and Lombardo can be the following. Persecutions, impossible action scenes and completely unexpected twists make up the plot of 27.::Sebastián Incaurgarat [D: Nicanor Loreti; A: Daniel Aráoz, Naiara Awada, Andres Bagg]
  • Annihilation: (2018; Adventure, Drama, Horror, Mystery, Sci-Fi, Thriller) A biologist's husband disappears. She puts her name forward for an expedition into an environmental disaster zone, but does not find what she's expecting. The expedition team is made up of the biologist, an anthropologist, a psychologist, a surveyor, and a linguist. [D: Alex Garland; A: Natalie Portman, Benedict Wong, Sonoya Mizuno]
  • Solo: A Star Wars Story: (2018; Action, Adventure, Fantasy, Sci-Fi) With the emerging demand of hyperfuel and other resources, Han Solo finds himself in the middle of a heist alongside other criminals, where they meet the likes of Chewbacca and Lando Calrissian in an adventurous situation exposing the criminal underworld of the Star Wars saga. [D: Ron Howard; A: Alden Ehrenreich, Joonas Suotamo, Woody Harrelson]
  • Ahora o nunca: (2015; Comedy) Narrates the preparation for a wedding of a Spanish couple in which everything goes wrong. [D: Maria Ripoll; A: Dani Rovira, María Valverde, Jordi Sánchez]
  • Alanis: (2017; Drama) A young Buenos Aires mother finds employment as a sex worker and struggles to live under the same laws that are supposed to protect her. [D: Anahí Berneri; A: Sofía Gala, Dante Della Paolera, Dana Basso]
  • Alita: Battle Angel: (2018; Action, Adventure, Romance, Sci-Fi, Thriller) Alita is a creation from an age of despair. Found by the mysterious Dr. Ido while trolling for cyborg parts, Alita becomes a lethal, dangerous being. She cannot remember who she is, or where she came from. But to Dr. Ido, the truth is all too clear. She is the one being who can break the cycle of death and destruction left behind from Tiphares. But to accomplish her true purpose, she must fight and kill. And that is where Alita's true significance comes to bear. She is an angel from heaven. She is an angel of death.::Anthony Harmon [D: Robert Rodriguez; A: Jennifer Connelly, Ed Skrein, Rosa Salazar]
  • Bohemian Rhapsody: (2018; Biography, Drama, Music) Bohemian Rhapsody is a foot-stomping celebration of Queen, their music and their extraordinary lead singer Freddie Mercury, who defied stereotypes and shattered convention to become one of the most beloved entertainers on the planet. The film traces the meteoric rise of the band through their iconic songs and revolutionary sound, their near-implosion as Mercury's lifestyle spirals out of control, and their triumphant reunion on the eve of Live Aid, where Mercury, facing a life-threatening illness, leads the band in one of the greatest performances in the history of rock music. In the process, cementing the legacy of a band that were always more like a family, and who continue to inspire outsiders, dreamers and music lovers to this day.::Twentieth Century Fox [D: Dexter Fletcher, Bryan Singer; A: Rami Malek, Joseph Mazzello, Ben Hardy]
  • Deadpool 2: (2018; Action, Adventure, Comedy, Sci-Fi) After surviving a near fatal bovine attack, a disfigured cafeteria chef (Wade Wilson) struggles to fulfill his dream of becoming Mayberry's hottest bartender while also learning to cope with his lost sense of taste. Searching to regain his spice for life, as well as a flux capacitor, Wade must battle ninjas, the Yakuza, and a pack of sexually aggressive canines, as he journeys around the world to discover the importance of family, friendship, and flavor - finding a new taste for adventure and earning the coveted coffee mug title of World's Best Lover.::Twentieth Century Fox [D: David Leitch; A: Ryan Reynolds, Josh Brolin, Morena Baccarin]
  • Distorted: (2018; Action, Mystery, Thriller) A 32-year-old woman suffering from bipolar disorder comes to suspect the proprietor of the state-of-the-art ''smart apartment'' she and her husband just moved into is using the building's residents as unwitting guinea pigs for a ''synthetic telepathy'' brainwashing plot with dire global ramifications. [D: Rob W. King; A: Christina Ricci, John Cusack, Brendan Fletcher]
  • Everybody Knows: (2018; Drama, Mystery, Thriller) Laura, a Spanish woman living in Buenos Aires, returns to her hometown outside Madrid with her two children to attend her sister's wedding. However, the trip is upset by unexpected events that bring secrets into the open.::screen international [D: Asghar Farhadi; A: Penélope Cruz, Javier Bardem, Bárbara Lennie]
  • Future World: (2018; Sci-Fi) Inside a desert oasis, a queen (Lucy Liu) lays dying as her son Prince (Jeffrey Wahlberg) travels across barren waste lands to find a near-mythical medicine to save her life. After evading violent raiders on motorbikes led by the Warlord (James Franco) and his enforcer (Cliff "Method Man" Smith), Prince meets Ash (Suki Waterhouse), the Warlord's robot sex companion-assassin who's in search of her own soul. As Prince is captured by the Druglord (Milla Jovovich), the Warlord's forces roar in - and Prince fights to save the remnants of humanity. [D: James Franco, Bruce Thierry Cheung; A: James Franco, Suki Waterhouse, Jeffrey Wahlberg]
  • Gringo: (2018; Action, Comedy, Crime) An exhilarating mix of dark comedy, white-knuckle action and dramatic intrigue, Gringo joyrides into Mexico, where mild-mannered businessman Harold Soyinka (David Oyelowo) finds himself at the mercy of his back-stabbing business colleagues back home, local drug lords and a morally conflicted black-ops mercenary. Crossing the line from law-abiding citizen to wanted criminal, Harold battles to survive his increasingly dangerous situation in ways that raise the question: Is he out of his depth - or two steps ahead?::Amazon Studios [D: Nash Edgerton; A: Joel Edgerton, Charlize Theron, David Oyelowo]
  • Hotel Artemis: (2018; Action, Crime, Sci-Fi, Thriller) Set in riot-torn, near-future Los Angeles, 'Hotel Artemis' follows the Nurse, who runs a secret, members-only emergency room for criminals. [D: Drew Pearce; A: Sofia Boutella, Dave Bautista, Sterling K. Brown]
  • The Shape of Water: (2017; Adventure, Drama, Fantasy, Horror, Romance, Thriller) From master storyteller Guillermo del Toro comes THE SHAPE OF WATER, an otherworldly fable set against the backdrop of Cold War era America circa 1962. In the hidden high-security government laboratory where she works, lonely Elisa (Sally Hawkins) is trapped in a life of isolation. Elisa's life is changed forever when she and co-worker Zelda (Octavia Spencer) discover a secret classified experiment. Rounding out the cast are Michael Shannon, Richard Jenkins, Michael Stuhlbarg, and Doug Jones.::Fox Searchlight Pictures [D: Guillermo del Toro; A: Sally Hawkins, Michael Shannon, Richard Jenkins]
  • The Queen of Fear: (2018; Drama) An actress becomes over anxious in the days leading up to the premiere of her one-woman show. [D: Valeria Bertuccelli, Fabiana Tiscornia; A: Valeria Bertuccelli, Gabriel Goity, Darío Grandinetti]
  • Mission: Impossible - Fallout: (2018; Action, Adventure, Thriller) Ethan Hunt and his IMF team, along with some familiar allies, race against time after a mission gone wrong.::Paramount Pictures [D: Christopher McQuarrie; A: Rebecca Ferguson, Vanessa Kirby, Tom Cruise]
  • Puzzle: (2018; Drama) Agnes, taken for granted as a suburban mother, discovers a passion for solving jigsaw puzzles which unexpectedly draws her into a new world - where her life unfolds in ways she could never have imagined.::Anonymous [D: Marc Turtletaub; A: Austin Abrams, Mandela Bellamy, Myrna Cabello]
  • Split: (2016; Horror, Thriller) Though Kevin (James McAvoy) has evidenced 23 personalities to his trusted psychiatrist, Dr. Fletcher (Betty Buckley), there remains one still submerged who is set to materialize and dominate all of the others. Compelled to abduct three teenage girls led by the willful, observant Casey, Kevin reaches a war for survival among all of those contained within him -- as well as everyone around him -- as the walls between his compartments shatter.::alexanderfire-00074 [D: M. Night Shyamalan; A: James McAvoy, Anya Taylor-Joy, Betty Buckley]
  • The Man Who Killed Don Quixote: (2018; Adventure, Comedy, Fantasy) Toby, a cynical advertising director finds himself trapped in the outrageous delusions of an old Spanish shoe-maker who believes himself to be Don Quixote. In the course of their comic and increasingly surreal adventures, Toby is forced to confront the tragic repercussions of a film he made in his idealistic youth - a film that changed the hopes and dreams of a small Spanish village forever. Can Toby make amends and regain his humanity? Can Don Quixote survive his madness and imminent death? Or will love conquer all? [D: Terry Gilliam; A: Adam Driver, Jonathan Pryce, Stellan Skarsgård]
  • Tomb Raider: (2018; Action, Adventure, Drama, Fantasy, Mystery, Thriller) Lara Croft is the fiercely independent daughter of an eccentric adventurer who vanished when she was scarcely a teen. Now a young woman of 21 without any real focus or purpose, Lara navigates the chaotic streets of trendy East London as a bike courier, barely making the rent, and takes college courses, rarely making it to class. Determined to forge her own path, she refuses to take the reins of her father's global empire just as staunchly as she rejects the idea that he's truly gone. Advised to face the facts and move forward after seven years without him, even Lara can't understand what drives her to finally solve the puzzle of his mysterious death. Going explicitly against his final wishes, she leaves everything she knows behind in search of her dad's last-known destination: a fabled tomb on a mythical island that might be somewhere off the coast of Japan. But her mission will not be an easy one; just reaching the island will be extremely treacherous. Suddenly, the stakes couldn't be higher for Lara, who-against the odds and armed with only her sharp mind, blind faith and inherently stubborn spirit-must learn to push herself beyond her limits as she journeys into the unknown. If she survives this perilous adventure, it could be the making of her, earning her the name tomb raider.::Warner Bros. Pictures [D: Roar Uthaug; A: Alicia Vikander, Dominic West, Walton Goggins]
  • Orbiter 9: (2017; Drama, Romance, Sci-Fi) Helena is a young girl who spent all her life in a space pod just after her birth, traveling from Earth to a distant planet where she will reunite with others space colonials, with the voice of the on-board computer as only one company. Arriving to a space station for maintenance works, Helena meets Álex, the repairman, falling in love with him quickly. But Álex, still traumatized by the ghosts of his own past, decides some days later after to meet Helena break all rules and reveal her the truth.::Chockys [D: Hatem Khraiche; A: Clara Lago, Álex González, Andrés Parra]

Finalmente, el conteo de pendientes por fecha:

(Ene-2012)
(Jul-2012)
(Nov-2012)    6
(Feb-2013)    8   2
(Jun-2013)   15  11   2
(Sep-2013)   17  16   8
(Dic-2013)   12  12  12   4
(Abr-2014)    8   8   8   3
(Jul-2014)   10  10  10  10   5   1
(Nov-2014)   24  22  22  22  22   7
(Feb-2015)       13  13  13  13  10
(Jun-2015)           16  16  15  13  11   1
(Dic-2015)               21  19  19  18   6   1
(May-2016)                   26  25  23  21   9
(Sep-2016)                       19  19  18  14   1
(Feb-2017)                           26  25  23  21
(Jun-2017)                               23  23  21
(Dic-2017)                                   19  19
(May-2018)                                       22
Total:      100  94  91  89 100  94  97  94  89  84

Mariano Guerra: Creemos en la Web: Si son datos, hay tabla

Como presentamos muchos datos en una pagina? con tablas!

Partes de una tabla

Tabla de datos

Vamos de menos a mas, la tabla mas simple que podemos tener solo tiene una parte, el cuerpo de la tabla. Es decir, los datos.

Los datos en una tabla son cero o mas filas, cada fila puede tener cero o mas columnas:

Osea que las partes de una tabla por ahora son:

  • Tabla
    • Cuerpo (1)
      • Filas (0 o mas)
        • Columnas (0 o mas)

Si alguna vez usaste una planilla de cálculos, las tablas son una forma de presentar información que presentarías en una planilla de cálculos.

Vamos a ver una tabla de ejemplo:

<table>
  <tr>
    <td>Arenita</td>
    <td>Ardilla</td>
    <td>Marron</td>
  </tr>
  <tr>
    <td>Bob</td>
    <td>Esponja</td>
    <td>Amarillo</td>
  </tr>
  <tr>
    <td>Patricio</td>
    <td>Estrella</td>
    <td>Rosa</td>
  </tr>
</table>

Que se ve algo así:

Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa

Como vemos en el código, el tag table indica que vamos a usar una tabla, si solo vamos a mostrar datos el tag que indica el cuerpo tbody (table body, cuerpo de tabla) es opcional, luego tenemos el tag que indica una fila tr (table row: fila de tabla), dentro del tenemos el tag para una celda de datos td (table cell data: celda de datos de tabla), uno por cada celda.

Cabecera

En la tabla anterior, como sabemos que significa cada columna? para eso necesitamos una cabecera, esto se hace con el tag thead (table head, cabecera de tabla)

  • Tabla
    • Cabecera (0 o 1)
      • Filas (1 o mas)
        • Columnas (1 o mas)
    • Cuerpo (1)
      • Filas (0 o mas)
        • Columnas (0 o mas)
<table>
  <thead>
    <tr>
      <th>Nombre</th>
      <th>Tipo</th>
      <th>Color</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Arenita</td>
      <td>Ardilla</td>
      <td>Marron</td>
    </tr>
    <tr>
      <td>Bob</td>
      <td>Esponja</td>
      <td>Amarillo</td>
    </tr>
    <tr>
      <td>Patricio</td>
      <td>Estrella</td>
      <td>Rosa</td>
    </tr>
  </tbody>
</table>
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa

Como podemos ver, en este caso tenemos que indicar explicitamente el cuerpo de la tabla con el tag tbody (table body, cuerpo de tabla).

Lo hacemos para poder tambien indicar la cabecera con el tag thead (table head, cabecera de tabla).

El cuerpo ya lo vimos antes, la cabecera es muy similar, solo que en lugar de usar el tag td para las columnas usamos el tag th (table cell header, celda de cabecera de tabla)

Pie de Tabla

Algunas tablas que presentan datos suelen tener al final una fila de sumarización que presenta valores resumidos para toda la columna.

Obviamente se puede usar para otras cosas, pero normalmente se usa para eso.

Vamos a ver un ejemplo que no aplica mucho a nuestro caso porque no estamos presentando valores que se puedan sumarizar.

  • Tabla
    • Cabecera (0 o 1)
      • Filas (1 o mas)
        • Columnas (1 o mas)
    • Cuerpo (1)
      • Filas (0 o mas)
        • Columnas (0 o mas)
    • Pie (0 o 1)
      • Filas (1 o mas)
        • Columnas (1 o mas)
<table>
  <thead>
    <tr>
      <th>Nombre</th>
      <th>Tipo</th>
      <th>Color</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Arenita</td>
      <td>Ardilla</td>
      <td>Marron</td>
    </tr>
    <tr>
      <td>Bob</td>
      <td>Esponja</td>
      <td>Amarillo</td>
    </tr>
    <tr>
      <td>Patricio</td>
      <td>Estrella</td>
      <td>Rosa</td>
    </tr>
  </tbody>

  <tfoot>
    <tr>
      <td>Nombre</td>
      <td>Tipo</td>
      <td>Color</td>
    </tr>
  </tfoot>
</table>
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Como podemos ver, el pie de tabla se define con el tag tfoot (table footer, pie de tabla), dentro usamos los mismos tags que en el cuerpo.

Un poco de estilo

Los ejemplos que vimos hasta ahora tienen un aspecto simple pero agradable, eso es porque estaba usando una clase de bootstrap para darle un aspecto aceptable, la clase que estaba usando es la clase table.

<table class="table">

En esta sección vamos a explorar otras clases que podemos aplicarle a una tabla.

Con bordes

<table class="table table-bordered">
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Colores invertidos

<table class="table table-dark">
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Cabecera invertida

<table class="table">
  <thead class="thead-dark">
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Filas "rayadas como una zebra"

Cambiar el color de filas adyacentes es útil para que el usuario pueda seguir las columnas de una fila sin perderse o empezar a leer celdas de las filas cercanas sin darse cuenta.

<table class="table table-striped">
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Énfasis en fila con foco del mouse

Resaltar la fila que tiene el foco del mouse es útil para que el usuario pueda seguir las columnas de una fila sin perderse o empezar a leer celdas de las filas cercanas sin darse cuenta.

<table class="table table-hover">
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Compacta

Una tabla con menos espacios, si es necesario mostrar mas datos.

<table class="table table-sm">
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Resaltando filas

Si necesitamos indicar algo en una fila lo podemos hacer agregando una clase.

<tr class="table-active">
  <td>Arenita</td>
  <td>Ardilla</td>
  <td>Marron</td>
</tr>
<tr class="table-primary">
  <td>Bob</td>
  <td>Esponja</td>
  <td>Amarillo</td>
</tr>
<tr class="table-secondary">
  <td>Patricio</td>
  <td>Estrella</td>
  <td>Rosa</td>
</tr>
<tr class="table-success">
  <td>Arenita</td>
  <td>Ardilla</td>
  <td>Marron</td>
</tr>
<tr class="table-danger">
  <td>Bob</td>
  <td>Esponja</td>
  <td>Amarillo</td>
</tr>
<tr class="table-warning">
  <td>Patricio</td>
  <td>Estrella</td>
  <td>Rosa</td>
</tr>
<tr class="table-info">
  <td>Arenita</td>
  <td>Ardilla</td>
  <td>Marron</td>
</tr>
<tr class="table-light">
  <td>Bob</td>
  <td>Esponja</td>
  <td>Amarillo</td>
</tr>
<tr class="table-dark">
  <td>Patricio</td>
  <td>Estrella</td>
  <td>Rosa</td>
</tr>
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Todo junto!

<table class="table table-bordered table-striped table-sm table-dark table-hover">
  <thead class="thead-light">
    <tr>
      <th>Nombre</th>
      <th>Tipo</th>
      <th>Color</th>
    </tr>
  </thead>

  <tbody>
    <tr class="table-active">
      <td>Arenita</td>
      <td>Ardilla</td>
      <td>Marron</td>
    </tr>
    <tr class="table-primary">
      <td>Bob</td>
      <td>Esponja</td>
      <td>Amarillo</td>
    </tr>
    <tr class="table-secondary">
      <td>Patricio</td>
      <td>Estrella</td>
      <td>Rosa</td>
    </tr>
    <tr class="table-success">
      <td>Arenita</td>
      <td>Ardilla</td>
      <td>Marron</td>
    </tr>
    <tr class="table-danger">
      <td>Bob</td>
      <td>Esponja</td>
      <td>Amarillo</td>
    </tr>
    <tr class="table-warning">
      <td>Patricio</td>
      <td>Estrella</td>
      <td>Rosa</td>
    </tr>
    <tr class="table-info">
      <td>Arenita</td>
      <td>Ardilla</td>
      <td>Marron</td>
    </tr>
    <tr class="table-light">
      <td>Bob</td>
      <td>Esponja</td>
      <td>Amarillo</td>
    </tr>
    <tr class="table-dark">
      <td>Patricio</td>
      <td>Estrella</td>
      <td>Rosa</td>
    </tr>
  </tbody>

  <tfoot>
    <tr>
      <td>Nombre</td>
      <td>Tipo</td>
      <td>Color</td>
    </tr>
  </tfoot>
</table>
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Subtítulo

Es útil indicar que datos se están mostrando en la tabla, para eso hay un tag llamado caption que puede ser usado para tal fin.

<table class="table">
  <caption>Personajes de Bob Esponja</caption>

  <thead>
    <tr>
      <th>Nombre</th>
      <th>Tipo</th>
      <th>Color</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Arenita</td>
      <td>Ardilla</td>
      <td>Marron</td>
    </tr>
    <tr>
      <td>Bob</td>
      <td>Esponja</td>
      <td>Amarillo</td>
    </tr>
    <tr>
      <td>Patricio</td>
      <td>Estrella</td>
      <td>Rosa</td>
    </tr>
  </tbody>

  <tfoot>
    <tr>
      <td>Nombre</td>
      <td>Tipo</td>
      <td>Color</td>
    </tr>
  </tfoot>
</table>
Personajes de Bob Esponja
Nombre Tipo Color
Arenita Ardilla Marron
Bob Esponja Amarillo
Patricio Estrella Rosa
Nombre Tipo Color

Celdas vacías y celdas unidas

En algunos casos podemos querer dejar algunas filas con menos celdas que otras, en otros casos queremos que una celda ocupe mas de una columna.

Usar menos celdas es fácil, simplemente no las escribimos.

<table class="table table-bordered">
  <tbody>
    <tr>
      <td>1.1</td>
    </tr>
    <tr>
      <td>2.1</td>
      <td>2.2</td>
    </tr>
    <tr>
      <td>3.1</td>
      <td>3.2</td>
      <td>3.3</td>
    </tr>
  </tbody>
</table>
1.1
2.1 2.2
3.1 3.2 3.3

Si queremos que una celda ocupe mas de una columna, tenemos que usar el atributo colspan (extensión de columnas) e indicarle cuantas columnas queremos que ocupe, por defecto cada celda tiene un colspan de 1.

<table class="table table-bordered">
  <tbody>
    <tr>
      <td colspan=3>1.1</td>
    </tr>
    <tr>
      <td>2.1</td>
      <td colspan=2>2.2</td>
    </tr>
    <tr>
      <td>3.1</td>
      <td>3.2</td>
      <td>3.3</td>
    </tr>
  </tbody>
</table>
1.1
2.1 2.2
3.1 3.2 3.3

Esto lo podemos usar en la cabecera para crear cabeceras multinivel:

 <table class="table table-bordered">
   <thead class="thead-dark">
     <tr>
       <th colspan=3>Lugar</th>
       <th rowspan=2 style="vertical-align: middle">Población</th>
     </tr>
     <tr>
       <th>Continente</th>
       <th>Pais</th>
       <th>Ciudad</th>
     </tr>
   </thead>

  <tbody>
    <tr>
      <td>America</td>
      <td>México</td>
      <td>Ciudad de México</td>
      <td>8 918 653</td>
    </tr>
    <tr>
      <td>America</td>
      <td>Argentina</td>
      <td>Buenos Aires</td>
      <td>2 890 151</td>
    </tr>
    <tr>
      <td>America</td>
      <td>Brasil</td>
      <td>Brasilia</td>
      <td>2 789 761</td>
    </tr>
  </tbody>
</table>
Lugar Población
Continente Pais Ciudad
America México Ciudad de México 8 918 653
America Argentina Buenos Aires 2 890 151
America Brasil Brasilia 2 789 761

Quizás notaste que use rowspan (extensión de fila) para "unir" las dos celdas de población verticalmente, también use el css vertical-align (alineación vertical) para que el texto este en el medio verticalmente.

Mariano Guerra: Creemos en la Web: Haciendo Lugar

En la sección Creemos en la Web: Lo espacial es invisible a los ojos vimos como indicar que queremos mas espacio entre el borde y otros elementos (margin/margen), en el borde (border) o entre el borde y el contenido interno (padding/relleno).

Cuando yo era joven y el pasto era mas verde, las paginas web se hacían asumiendo una o dos resoluciones de pantalla, ya que los navegadores solo funcionaban en PCs y todas las PCs tenían una resolución casi estándar (800 pixeles de ancho por 600 de alto).

En esas épocas mas simples la unidad que se usaba para indicar espacio/distancia eran los pixeles, una unidad absoluta que se refiere a cada puntito de la pantalla que puede mostrar un color.

Como todas las pantallas tenían cantidades similares de pixeles horizontales y verticales, la cosa funcionaba bastante bien para todos.

No hace falta que les cuente que hoy la web se accede de una cantidad impresionante de dispositivos y resoluciones.

Para poder escribir estilo que se adapte a la resolución de cada dispositivo usamos otras unidades, llamadas relativas, ya que son relativas a algo presente en la pagina, las mas usadas son relativas al ancho del elemento que contiene nuestro tag o al ancho de una letra en el texto.

Pixeles

Esta es la unidad mas común, un pixel es un punto en la pantalla, el cual puede mostrar un color, la cantidad horizontal y vertical de pixeles en una pantalla se llama resolución, por ejemplo, una pantalla de una laptop puede tener 1280 pixeles de ancho por 800 de alto, lo que se escribe abreviado 1280x800.

cuando especificamos el estilo de un tag y le decimos que su borde, margen o relleno es de 15px (15 pixeles), le estamos diciendo que queremos 15 puntos de espacio, pero no sabemos cuantos pixeles tiene la pantalla en total, asi que eso puede ser bastante para la pantalla de un celular básico que puede tener una resolución de 320x240 o muy poco para la pantalla de una computadora de escritorio avanzada que pueden tener 3840x2160 (mas de 10 veces mas resolución!).

Idealmente vamos a usar esta unidad muy poco, yo lo uso solo para especificar el ancho de los bordes y muchas veces no debería :)

em

Esta es la unidad mas usada y la mas recomendada, su nombre según tengo entendido viene de lejos, 1em es el alto en pixeles de la letra M mayúscula, si nombramos la letra M "eme" en ingles es "em".

el alto de que M mayúscula? de la M si estuviera en el tag en el que estamos actualmente, osea que esta unidad es relativa al tamaño de texto del tag en el que nos encontramos, el cual lo puede haber establecido cualquiera de los tags padres, o ninguno, siendo asi el estándar de 16px.

rem

Pero que pasa si no sabemos que estilos se aplicaron a tags padres y queremos estar mas seguros del tamaño que vamos a obtener? para eso existe la unidad rem, que es el alto de la letra M según el tamaño de texto definido en la base del documento (el tag <body>), de no estar definido va a ser también 16px.

Su nombre viene de "root em" (em de la raíz).

Esto nos permite saber que no importa que tamaños de fuente se hayan redefinido hasta nuestro tag, su tamaño va a ser siempre fijo relativo al tamaño base del texto del documento.

Porcentajes

Otra unidad útil, pero usada normalmente cuando estamos definiendo tamaños de la estructura de nuestro documento como ancho de columnas es el porcentaje %.

El porcentaje se refiere al ancho del tag que contiene al tag actual, si decimos que el ancho de nuestro tag es 50%, este ocupara la mitad del tag padre, si decimos que el margen horizontal es de 5%, el padding horizontal es del 2.5%, entonces nos queda 75% para el contenido:

5% margen izquierdo + 2.5% padding izquierdo + 2.5% padding derecho + 5% margen derecho = 15%

Ejemplos que no se entiende nada!

Las unidades de espacio se entienden mas usandolas y a puro prueba y error, la recomendación es usar em y rem siempre que se pueda, porcentajes cuando estamos definiendo posicionamiento de cosas en la pagina y pixeles si tenes una buena razón.

El div azul que contiene a todos los otros divs establece el tamaño de la fuente a 16 pixeles:

<div style="font-size: 16px; width: 90%; padding: 2.5%; margin: 2.5%; border: 1px solid blue;">
    <div style="width: 5em;  background-color: red; color: white; margin: 1em 0;">5em</div>
    <div style="width: 5rem; background-color: red; color: white; margin: 1em 0;">5rem</div>
    <div style="width: 50px; background-color: red; color: white; margin: 1em 0;">50px</div>
    <div style="width: 50%;  background-color: red; color: white;">50%</div>
</div>
5em
5rem
50px
50%

El div azul que contiene a todos los otros divs establece el tamaño de la fuente, notar que los divs interiores tienen el mismo estilo que los de arriba:

<div style="font-size: 32px; width: 90%; padding: 2.5%; margin: 2.5%; border: 1px solid blue;">
    <div style="width: 5em;  background-color: red; color: white; margin: 1em 0;">5em</div>
    <div style="width: 5rem; background-color: red; color: white; margin: 1em 0;">5rem</div>
    <div style="width: 50px; background-color: red; color: white; margin: 1em 0;">50px</div>
    <div style="width: 50%;  background-color: red; color: white;">50%</div>
</div>
5em
5rem
50px
50%

El primer div tiene un ancho de 5em, como el div padre establece el tamaño de la fuente a distintos valores en los dos ejemplos, el ancho resultante es distinto.

El segundo div tiene un ancho de 5rem, como ambos están en el mismo documento raíz, tienen el mismo ancho, aun cuando el texto interior cambia, ya que "hereda" el tamaño del div padre.

El tercero esta en pixeles, así que va a ser igual, el cuarto esta en porcentaje, y ya que ambos divs padres tienen el mismo ancho, su ancho es igual.

Probemos algo un poco distinto:

<div style="font-size: 32px; width: 50%; padding: 2.5%; margin: 2.5%; border: 1px solid blue;">
    <div style="width: 5em;  font-size: 1rem; background-color: red; color: white; margin: 1em 0;">5em</div>
    <div style="width: 5rem; font-size: 1rem; background-color: red; color: white; margin: 1em 0;">5rem</div>
    <div style="width: 50px; font-size: 1rem; background-color: red; color: white; margin: 1em 0;">50px</div>
    <div style="width: 50%;  font-size: 1rem; background-color: red; color: white;">50%</div>
</div>
5em
5rem
50px
50%

El div padre ahora ocupa el 50% del ancho de la pagina, por lo que el ancho del ultimo div hijo debería ser la mitad de los anteriores, para "estandarizar" em y rem, seteo el tamaño de fuente de los divs hijos a 1rem.

Como no se en que pantalla estas viendo esto no te puedo decir mucho sobre que ancho van a tener, lo único que se, es que como la fuente de ambos tiene 1rem de tamaño, el ancho de los dos debería ser el mismo.

Si el tamaño de la fuente del documento resulta ser 10px, entonces el tercer div tendrá el mismo ancho.

Como siempre, no hace falta que se entienda todo ahora, solo saber las unidades mas usadas, las recomendadas y mas o menos como se comportan, el resto es prueba y error.

Facundo Batista: Pasaron los PyDays de Mayo

Dos PyDays teníamos planeados para este mes, el de La Plata y el del NEA.

Fui a ambos, salieron los dos muy bien.

El de La Plata fue el primero que se hacía en dicha ciudad. Organizado por Sofia y un par de secuaces, se realizó en la Facultad De Informática de la UNLP y contó con tres tracks en paralelo, un hall con varios stands, charlas de todo tipo (incluyendo lightning talks) y hasta un cierre con banda de rock.

Incluso tuvimos una charla debate sobre diversidad donde charlamos sobre el problema que tenemos en las comunidades de informática en donde los hombres estamos sobrerrepresentados y varios temitas más. Salió muy bien, y llegamos a la conclusión de que debemos hacer más de estos debates (aunque con un moderador que sepa moderar :p ).

En la charla debate sobre diversidad

El del NEA se hizo en Corrientes, en el Club de Emprendedores. Lo organizaron Sergio y Marian, y también salió bárbaro. Vino mucha más gente de lo que esperábamos, saturamos completamente las instalaciones... pusimos sillas en la parte de atrás de la sala, afuera, y hasta en el patio, y al final de todo eso había gente parada!

El próximo se va a tener que hacer en un lugar más grande! :D

Mucha gente

Acá hay algunas fotos que sacó Marian.

En el segundo semestre vamos por más: ya estamos esperando el PyDay de Luján, fecha a confirmar :). Mientras, para que no decaiga, iremos armando algunos meetups... este miércoles vamos invitados a este.

Mariano Guerra: Creemos en la Web: Colores

Estamos creando una pagina y vemos o nos imaginamos un color que queremos usar, como se lo comunicamos a la computadora?

Las computadoras son buenas manipulando números, los colores, al menos como nosotros los usamos al comunicarnos, no tienen mucho de números.

En la búsqueda por encontrar un compromiso que funcionara tanto para humanos como para computadoras surgieron diferentes "representaciones", formas de describir unívocamente a que color nos referimos.

En esta sección vamos a explorar estas distintas representaciones.

Una herramienta online para elegir colores es Mozilla Color Picker podes usar esta o buscar alguna con la que ya hayas trabajado, intenta que permita ver las representaciones que vamos a explorar en esta sección.

Usando colores

Los siguientes son algunos de los atributos CSS que requieren colores, todos soportan todas las representaciones que vamos a explorar a continuación.

  • color
  • background-color
  • border-color
  • outline-color
  • text-decoration-color
  • text-emphasis-color
  • text-shadow

Un ejemplo que algunos de los atributos listados:

<span style="border: 1px solid; text-decoration: underline; color: red; background-color: lightgrey; border-color: blue; text-decoration-color: green; text-shadow: yellow 0.6em 0.6em; padding: 1em;">Hello Color</span>
Hello Color

Colores con nombres

La mas fácil y la que hemos usado hasta ahora es simplemente dar el nombre del color en ingles cuando necesitamos referirnos a el.

Esta representación es simple para los humanos pero tiene un par de limitaciones:

  • Hay que mantener una lista de nombres a colores
  • No todos los colores tienen nombre
  • Como me acuerdo de tantos nombres?
  • Tampoco queremos una lista de colores eterna
  • Cuando busco un color, como lo busco rápido en la tabla?
  • Cuando digo rojo, que rojo es?

A continuación la lista de colores

black
silver
gray
white
maroon
red
purple
fuchsia
green
lime
olive
yellow
navy
blue
teal
aqua
orange
aliceblue
antiquewhite
aquamarine
azure
beige
bisque
blanchedalmond
blueviolet
brown
burlywood
cadetblue
chartreuse
chocolate
coral
cornflowerblue
cornsilk
crimson
cyan (synonym of aqua)
darkblue
darkcyan
darkgoldenrod
darkgray
darkgreen
darkgrey
darkkhaki
darkmagenta
darkolivegreen
darkorange
darkorchid
darkred
darksalmon
darkseagreen
darkslateblue
darkslategray
darkslategrey
darkturquoise
darkviolet
deeppink
deepskyblue
dimgray
dimgrey
dodgerblue
firebrick
floralwhite
forestgreen
gainsboro
ghostwhite
gold
goldenrod
greenyellow
grey
honeydew
hotpink
indianred
indigo
ivory
khaki
lavender
lavenderblush
lawngreen
lemonchiffon
lightblue
lightcoral
lightcyan
lightgoldenrodyellow
lightgray
lightgreen
lightgrey
lightpink
lightsalmon
lightseagreen
lightskyblue
lightslategray
lightslategrey
lightsteelblue
lightyellow
limegreen
linen
magenta (synonym of fuchsia)
mediumaquamarine
mediumblue
mediumorchid
mediumpurple
mediumseagreen
mediumslateblue
mediumspringgreen
mediumturquoise
mediumvioletred
midnightblue
mintcream
mistyrose
moccasin
navajowhite
oldlace
olivedrab
orangered
orchid
palegoldenrod
palegreen
paleturquoise
palevioletred
papayawhip
peachpuff
peru
pink
plum
powderblue
rosybrown
royalblue
saddlebrown
salmon
sandybrown
seagreen
seashell
sienna
skyblue
slateblue
slategray
slategrey
snow
springgreen
steelblue
tan
thistle
tomato
turquoise
violet
wheat
whitesmoke
yellowgreen
rebeccapurple

RGB: Combinando Rojo, Verde y Azul

Otra forma de especificar colores es describir una mezcla de colores "básicos", en este caso rojo (Red), verde (Green) y azul (Blue).

Como lo describimos?

Necesitamos indicar la cantidad de cada color en la combinación, lo podemos hacer de dos formas:

  • Con números
    • 0: nada de color
    • 255: máximo de color
  • Como porcentaje
    • 0%: nada de color
    • 100%: máximo de color

Como lo escribimos?

La forma mas fácil de escribirlo si sabemos los valores individuales y dado que hay múltiples formas de indicarlo es:

  • Indicar de que forma vamos a describir el color, en nuestro caso rgb
  • Indicar los 3 valores

Veamos algunos ejemplos

R G B Formato Color
0 0 0 rgb(0, 0, 0)
255 255 255 rgb(255, 255, 255)
255 0 0 rgb(255, 0, 0)
0 255 0 rgb(0, 255, 0)
0 0 255 rgb(0, 0, 255)
255 255 0 rgb(255, 255, 0)
255 0 255 rgb(255, 0, 255)
0 255 255 rgb(0, 255, 255)
128 128 128 rgb(128, 128, 128)
128 0 0 rgb(128, 0, 0)
0 128 0 rgb(0, 128, 0)
0 0 128 rgb(0, 0, 128)
80 160 255 rgb(80, 160, 255)
80 255 160 rgb(80, 255, 160)
255 160 80 rgb(255, 160, 80)
160 255 80 rgb(160, 255, 80)
160 80 255 rgb(160, 80, 255)
255 80 160 rgb(255, 80, 160)
0% 0% 0% rgb(0%, 0%, 0%)
100% 100% 100% rgb(100%, 100%, 100%)
100% 0% 0% rgb(100%, 0%, 0%)
0% 100% 0% rgb(0%, 100%, 0%)
0% 0% 100% rgb(0%, 0%, 100%)
100% 100% 0% rgb(100%, 100%, 0%)
100% 0% 100% rgb(100%, 0%, 100%)
0% 0% 0% rgb(0%, 0%, 0%)
50% 50% 50% rgb(50%, 50%, 50%)
50% 0% 0% rgb(50%, 0%, 0%)
0% 50% 0% rgb(0%, 50%, 0%)
0% 0% 50% rgb(0%, 0%, 50%)
50% 50% 0% rgb(50%, 50%, 0%)
50% 0% 50% rgb(50%, 0%, 50%)

Alternativa: Hexadecimal

Este formato suele estar disponible en herramientas que usan o manipulan colores, es compacta pero difícil de interpretar a menos que entiendas la numeración hexadecimal fluidamente.

La mencionamos porque te la vas a encontrar en muchos lugares y hay que saber que es un formato de color valido, que lo podes usar en lugar de cualquiera de los otros y que hay muchas herramientas que la usan.

Nota muy resumida para los curiosos:

En hexadecimal en lugar de contar del 0 al 9 y al quedarnos sin dígitos ponemos un 1 adelante y empezamos de nuevo como lo hacemos en decimal, se cuenta del 0 a la F, porque tiene como base 16 y no 10 como el decimal, contando en hexadecimal seria algo como: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11 ... 1F, 20 ... 2F, 30 ... F0 ... FF, 100 etc.

Lo que cambia es que el 255 de antes se convierte en FF y ponemos los 3 valores todos juntos luego del símbolo #, que indica que estamos usando este formato, el formato debe tener o 3 o 6 caracteres, de ser necesario llenamos los valores restantes con 0.

Algunos ejemplos de la sección anterior convertidos a formato hexadecimal:

R G B Formato Color
00 00 00 #000000
FF FF FF #FFFFFF
FF 00 00 #FF0000
00 FF 00 #00FF00
00 00 FF #0000FF
FF FF 00 #FFFF00
FF 00 FF #FF00FF
00 FF FF #00FFFF
80 80 80 #808080
80 00 00 #800000
00 80 00 #008000
00 00 80 #000080

HSL: Tono, Saturación y "Liviandad/Brillo"

En esta representación tenemos 3 valores, llamados H (Hue), S (Saturation), L (Lightness).

H
Numero de 0 a 360 (angulo en un circulo de colores), indica el tono base que queremos
S
Porcentaje de saturación del color elegido, 0% va a ser un gris, 100% va a ser el color puro.
L
Porcentaje de liviandad/brillo del color elegido, 0% va a ser negro, 100% va a ser blanco, 50% (y 100% de saturación) va a ser el color puro.

Algunos colores "puros":

hsl(0, 100%, 50%)
hsl(30, 100%, 50%)
hsl(60, 100%, 50%)
hsl(90, 100%, 50%)
hsl(120, 100%, 50%)
hsl(150, 100%, 50%)
hsl(180, 100%, 50%)
hsl(210, 100%, 50%)
hsl(240, 100%, 50%)
hsl(270, 100%, 50%)
hsl(300, 100%, 50%)
hsl(330, 100%, 50%)
hsl(360, 100%, 50%)

Cambiando la saturación:

hsl(0, 0%, 50%)
hsl(0, 25%, 50%)
hsl(0, 50%, 50%)
hsl(0, 75%, 50%)
hsl(0, 100%, 50%)

Cambiando el "brillo":

hsl(0, 100%, 0%)
hsl(0, 100%, 25%)
hsl(0, 100%, 50%)
hsl(0, 100%, 75%)
hsl(0, 100%, 100%)

Alpha: Transparencia/Opacidad

Un ultimo componente del color común a todos los que vimos es la transparencia/opacidad, es decir, cuanto del contenido que se encuentra "detrás" del color que estamos mostrando es visible.

La transparencia/opacidad va de 0% (ausencia absoluta de color, como un vidrio) a 100% (color solido, nada se "transluce")

Cuando indicamos la transparencia en rgb y hsl puede ser:

  • Numero entre 0 y 1
  • Porcentaje de 0% a 100%

Ejemplos:

/* transparente */
rgba(255, 0, 153, 0)
rgba(255, 0, 153, 0%)

/* semi translucido */
rgba(255, 0, 153, 0.5)
rgba(255, 0, 153, 50%)

/* opaco */
rgba(255, 0, 153, 1)
rgba(255, 0, 153, 100%)
/* transparente */
hsla(240, 100%, 50%, 0)
hsla(240, 100%, 50%, 0%)

/* semi translucido */
hsla(240, 100%, 50%, 0.5)
hsla(240, 100%, 50%, 50%)

/* opaco */
hsla(240, 100%, 50%, 1)
hsla(240, 100%, 50%, 100%)

En el formato hexadecimal simplemente agregamos dos dígitos mas al final entre 00 (0%) y FF (100%) indicando el nivel de transparencia

/* transparente */
#FFFFFF00

/* semi translucido */
#FFFFFF80

/* opaco */
#FFFFFFFF

Y así llegamos al final, no hace falta que intentes aprender, entender o memorizar esto, solo saber que hay distintas formas de especificar colores, mas o menos cuales son, para el resto esta tu motor de búsqueda amigo.

Martín Gaitán: Miau: cuando el gato dice la verdad

Cuando se cumplieron los primeros 7 meses de su gestión, el presidente Macri dió una entrevista exclusiva a periodistas del canal Telefé. Horas después apareció este video en las redes, cuyo autor o autora desconozco:

Ahí estaba el humor, el fruto más gozoso del ingenio popular, para salvarnos a carcajadas. No para evadirnos de la realidad sino, al contrario, para vencerla, para enfrentar la amargura que algunas certezas traen (ya sabíamos a esa altura, con devaluación a precios y tarifazos en curso, que las advertencias no habían sido una "campaña del miedo"). Pero era aún más: era un ejemplo de ese humor que enuncia verdades difíciles de escuchar de otra manera.

Simplemente me pareció genial. Me acordé, por supuesto, de la entrevista a Homero en el capítulo de la Venus de jalea y también de un cortometraje español que ví hace mucho titulado "Lo que tú quieras oir", cuyo argumento se basa exáctamente en la creación de un mash-up de audio como alivio de una situación dramática.

Cada discurso o entrevista de Macri me parecía (me parece) un puesta en escena cínica, plagada de mentiras, floja de fonética y con pésimo acting. Necesitaba más de estos videos que le hagan decir la verdad.

El maravilloso compositor Jorge Fandermole escribió

Canto, canto,

tan débil soy que cantar es mi mano alzada y fuerte.

Canto, canto,

no sé más qué hacer en esta tierra incendiada

sino cantar.

Parafraseando (bastante lejos de esa belleza) yo podría decir:

print("programo, programo, programar es mi mano alzada y fuerte...")

Asi que ante la falta de talento natural para la edición audiovisual (entre todo el resto de las cosas), programé. Y así fue como hice un programita en Python que hace las ediciones por mí: miau.

Sólo hay que darle la desgrabación del discurso original completo y el guión del discurso pretendido (basado en fragmentos textuales del original, en el orden que sea) y miau se encarga de encontrar, recortar y concatenar para armar un clip de video o un audio remixado.

Por ejemplo este en el que Macri reconoce las verdaderas razones que nos llevaran de vuelta a deberle al FMI.

o este audio donde reconoce que niega los problemas

O este otro en el acepta que están haciendo fantochadas y van a salir "para arriba" en cualquier momento:

Agarrá la pala (o copiá y pegala)

Si bien los excelsos discursos presidenciales suelen ser breves, ¿de verdad te fumás tener que desgrabar toda esa sarta de duranbarbaridades, Martincito?

Pues no, al menos para el caso específico de este felino doméstico. Gracias a que casarosada.gob.ar se toma el trabajo de conservar cada palabra de la retórica sublime, de estadismo profundo y condensado que será aplaudido por generaciones, de esas piezas de discurso político que interpelan hasta al más indiferente... Bueno, quiero decir, gracias a que guardan el txt de las 30 frases en distinto orden que le escriben, no hace falta desgrabar nada.

Alcanza con ir acá, copiar un discurso y guardarlo en un txt, y luego allá para bajarse el video que corresponda (por ejemplo, usando el genial youtube-dl), y ya tenemos todo el material de entrada necesario para mofarnos de estos fugadores un buen rato. Si a esos contenidos los guardamos, supongamos, como macri_gato.txt y macri_gato.mp4, y a nuestro remix lo guardamos como remix.txt, podemos hacer un supercut en mp3 así:

$ miau macri_gato.mp4 macri_gato.txt -r remix.txt -o macri_gato_remixado.mp3

y casi lo mismo si queremos hacer un video:

$ miau macri_gato.mp4 macri_gato.txt -r remix.txt -o macri_gato_remixado.mp4

Consejo

te conviene siempre laburar primero generando audios y cuando estes conforme haces el video, ya que es mucho más rápido el recorte y concatenado.

Como la detección de fragmentos no es infalible, hay que meterle laburo de prueba y error y a veces hay que ajustar un poquito los tiempos detectados automáticamente (sobre todo cuando se recortan palabras sueltas o frases muy breves).

Eso se puede hacer de dos maneras:

  • Reusar el json intermedio que se produce con --dump, editarlo a gusto y pasarlo a una nueva ejecución de miau en reemplazo del txt de remix a -r. Este paso lo que hace justamente es saltearse la alineación automática y usar lo que le damos explícitamente.

  • Ponerle una metadata de ajuste al propio txt. La sintáxis que definí es un poco minimalista y se basa en ponerle signos + y - al final y/o al principio de cada linea, para estrechar o ensanchar el recorte. Cada símbolo equivale, por default, a 0.05s. Por ejemplo, si en el remix hay una línea que dice "el único camino posible" y nos damos cuenta que la detecta un instante tarde y la interrumpe antes de terminar, podemos corregirla poniendo un offset negativo al principio y uno positivo al final:

    --el único camino posible+++``
    

    Miau filtra la línea con una función que hace esto:

    >>> fine_tuning('--el único camino posible+++'):
    {'el único camino posible': {'start_offset': -0.1, 'end_offset': 0.15}}
    

En github fui dejando algunos ejemplos con los pasos y las fuentes con los que los hice.

Vale resaltar que esta herramienta es software libre, lo que quiere decir que no necesariamente tenés que usarla para burlarte de gobiernos de derecha y podés hacer con ella lo que te plazca. ¡Hacele decir a la tía Berta eso que nunca dijo (o al menos no de esa textual manera) en Whatsapp!

Deconstruyendo el relato, con Python

A este tipo de videos se le llaman "supercuts" y hay distintas maneras de hacerlos. De hecho, sin saberlo entonces, hace un tiempo hice uno sobre Sergio Massa, basado en fragmentos de los subtitulos automáticos de youtube. También hay una herramienta en python que permite hacer un "grep" en el video.

Yo quería algo un poquito más ambicioso, algo que permita la generación de cualquier edición posible y que sea más o menos fácil para cualquiera con ganas de hacerla.

Descubrí que existía software que se ocupa de la parte difícil: reconocer frases en un audio y generar las marcas de tiempo de su ubicación. Es algo que se llama forced aligment y hay una biblioteca en Python, hecha por un academico italiano, que anda al pelo: aeneas. Anda tan bien que hasta acierta la mayoría de las veces con la dicción de Mauricio Macri, ¡imaginensé!. De yapa, soporta ("entiende") múltiples idiomas.

Si te dan un "buscador de audio" que te dice el inicio y final de una frase en un discurso, el resto es más o menos fácil. Sólo hay que saber recortar por la línea punteada, hacer una pila con los pedacitos y pegarlos unos con otros. Para eso moviepy es mucho más que suficiente.

Sólo había una sutil complicación. aeneas requiere la desgrabación completa correspondiente al discurso a fragmentar, y en su forma de uso más general, asume que cada fragmento a encontrar es una linea del texto de entrada.

Por ejemplo, supongamos, que este es el "verso" original:

Buenos días: ustedes saben que tengo un compromiso de decirles la verdad siempre;
también que me metí en política y me postulé para la Presidencia para trabajar todos los días.

Si de allí quisiéramos pedirle a aeneas que recorte la frase "tengo un compromiso" y me postulé para la Presidencia, habría que reformatear el texto completo separando en lineas de la siguiente manera:

Buenos días: ustedes saben que
tengo un compromiso
de decirles la verdad siempre; también que me metí en política y
me postulé para la Presidencia
para trabajar todos los días.

Es decir, forzar que cada fragmento objetivo se encuentre textualmente en una fila independiente. El problema es que cabe la posiblidad de que queramos fragmentos que se solapan entre sí. Por ejemplo, si además de los anteriores quisiéramos "me metí en política y me postulé", no tendríamos manera de cumplir con la regla de las filas independientes ya que "me postulé" debería estar repetido en dos renglones.

Por ese motivo miau hace tantas versiones de fragmentado del texto original como encuentre necesarias para salvar estos solapamientos. Esas son las iteraciones que se corresponden con sendas llamadas a aeneas.

Vermuth con software libre y ¡good show!

Aunque es divertidísimo (es decir, es totalmente redituable), mantener software de humor político tiene sus costos, sobre todo cuando tenés más de un laburo, una familia, algun@s amig@s y varios libros a los que tenés que dedicarle tiempo.

El tema es que miau anda masomenos. O como el culo, seamos sinceros. Y, saben, yo no puedo ni quiero pedirle un stand-by al Fondo Monetario, porque sé como termina esa ayudita. Por eso te pido a vos, programador/a, expert o wannabe, que me des una mano. Por ahora no son mucho más de 300 líneas de código en un solo módulo que no hacen nada demasiado raro, así que la zambullida para poder colaborar es accesible.

¿Y cómo? En este orden: usándolo, encontrando errores (que vamos anotando en el issue tracker), desculando por qué suceden y por último arreglándolos. También es indispensable tener pruebas unitarias, así no rompemos tanto nuevo cuando vamos arreglando lo viejo. Y hay funcionalidades que me gustaría completar, como la de permitir múltiples fuentes de entrada para hacer ediciones más complejas y ampliar la base de frases.

A futuro sería genial que tenga otras "atractividades" como una linda interfaz gráfica, que sea fácil instalarlo en cualquier sistema operativo (y particularmente en Windows) y, por qué no, que se convierta en el core de una app web o la API para un app mobile que permita usarlo directamente desde la nube.

Espero sus tickets y pull requests.

¡A maullar esos remixes!

Facundo Batista: PyCamp 2018

Pasó una nueva edición del mejor evento del año, el PyCamp!

Como siempre, lleno de Python, pero también de mil cosas más.

A nivel Python, estuve laburando en fades un poco, pero más que nada difundiéndolo y haciendo que todos, todos, todos, estén al tanto de las bondades del sistemita... un poco denso, estuve, sí :p. También llevé como proyecto a linkode pero acá el que estuvo laburando (en la migración del mismo a Python 3) fue Matías, un capo.

También estuve en largas charlas sobre cual va a ser el futuro de la lista de correo de PyAr (estuvimos analizando opciones), y el diseño del sitio web de gestión para la Asociación Civil Python Argentina. Y después yendo y viniendo por ahí, ayudando a gente en cosas puntuales que necesitaban, charlando, aprendiendo, disfrutando.

La típica grupal

Fuera de lo que es Python o programación en sí, podemos separar las actividades en dos grupos: juegos de mesa y resto.

El primer juego de mesa al que jugué, valga la cacofonía, fue el Belfort, al cual ya jugué varias veces y me encanta. Gané por lejos. Otro repetido fue el Galaxy Trucker, pero en este si juegan Sofia o Fisa no tenés chance. Otro en el que fui vapuleado fue (nuevo para mí) el Age of War. Y también jugué al Timeline (de inventos), gané el primero, el segundo quedé como cuarto.

Actividades sociales por fuera de los juegos de mesa también hubieron un montón. Aprendí a hacer malabares rebotando pelotitas contra el piso (sólo, con dos y tres pelotitas, y grupal, de a 3, 4 o 5 personas, haciendo combinaciones superlocas, armando y desarmando coreografías, fue muy divertido). Aprendí arquería con arcos de verdad (gracias Joaco por las clases). Jugué al basquet (y me raspé una rodilla y rompí una zapatilla). Armé un campeonato de ping-pong, pero perdí en la segunda ronda, 18-21 en el tercer partido, contra el que finalmente ganó el torneo. Hicimos música a cuatro manos en un piano. Montonazazazo de actividades.

Nos agarraste trabajandoHaciendo música

Obviamente, como en todo PyCamp, también hicimos una reunión de PyAr. Charlamos sobre los próximos eventos, algunos anuncios operativos de esos días, y algunos detalles más, pero lo principal fue el balance del PyCamp: qué estuvo bueno, qué estuvo fantástico, en qué cosas debemos mejorar. Nos llevamos un par de ideas para el PyCamp del año que viene, tanto en la preparatoria de las semanas anteriores, como mejoras a hacerle al bot del PyCamp.

Como nota de color, una tarde fuimos a buscar a unos chicos que llegaban a la terminal de Baradero, y al volver nos quedamos en el barro. Estuve 25 minutos tratando de sacar el auto de donde se había empantanado (en dos lugares distintos, imposibles), y al final salí victorioso. Pero me tembló hasta el culo por un par de horas....

Los que fueron magos en algún punto del eventoAlecu y el ventilagón, que fue uno de los proyectos

También, pero más importante, quiero destacar que brillamos en nuestras métricas de diversidad (gracias PSF por las becas para esto): fuimos un 25% de mujeres, y 50% de gente que era su primer PyCamp. Un éxito.

Pero no todo es brillar, especialmente cuando se corta la luz en todo el barrio! Fueron un par de horas, cuando anochecía, pero no nos amedrentamos y seguimos pycampeando casi como si nada hubiera pasado...

Se nos cortó la luzHicimos basquet, malabares, pingpong, espadas... y arquería

Para cerrar, les dejo las fotos mías (más algunas que saqué del grupo de Telegram), las de Yami (fotógrafa oficial), y les prometo el video presentación de todo lo que hicimos (cuando José Luis lo procese, digamos todos "gracias José Luis").

Mariano Guerra: Riak Core Tutorial Part 2: Starting

This is part of a series, see the previous one at Riak Core Tutorial Part 1: Setup

Creating our Project

Now that we have our tools and our template installed we can start by asking rebar3 to create a new project we will call tanodb using the riak_core template we just installed:

rebar3 new rebar3_riak_core name=tanodb

If it fails saying it can't find rebar3 check that it's in your $PATH environment variable and that you have Erlang activated.

The output should be something like this:

===> Writing tanodb/apps/tanodb/src/tanodb.app.src
===> Writing tanodb/apps/tanodb/src/tanodb.erl
===> Writing tanodb/apps/tanodb/src/tanodb_app.erl
===> Writing tanodb/apps/tanodb/src/tanodb_sup.erl
===> Writing tanodb/apps/tanodb/src/tanodb_console.erl
===> Writing tanodb/apps/tanodb/src/tanodb_vnode.erl
===> Writing tanodb/rebar.config
===> Writing tanodb/.editorconfig
===> Writing tanodb/.gitignore
===> Writing tanodb/README.rst
===> Writing tanodb/Makefile
===> Writing tanodb/config/admin_bin
===> Writing tanodb/priv/01-tanodb.schema
===> Writing tanodb/config/advanced.config
===> Writing tanodb/config/vars.config
===> Writing tanodb/config/vars_dev1.config
===> Writing tanodb/config/vars_dev2.config
===> Writing tanodb/config/vars_dev3.config

Note

The content of this chapter is in the 01-template branch.

https://gitlab.com/marianoguerra/tanodb/tree/01-template

Building and Running

Before explaining what the files mean so you get an idea what just happened let's run it!

cd tanodb
make
make console

make runs rebar3 commands to build a release of our project, for that it uses a tool called relx.

The initial build may take a while since it has to fetch all the dependencies and build them.

After the release is built (you can check the result by inspecting the folder _build/default/rel/tanodb/) we can run it.

When we run make console we get some noisy output that should end with something like this:

Eshell V9.3  (abort with ^G)
(tanodb@127.0.0.1)1>

This is the Erlang shell, something like a REPL connected to our system, we now can test our system by calling tanodb:ping() on it.

(tanodb@127.0.0.1)1> tanodb:ping().
{pong,1347321821914426127719021955160323408745312813056}

The response is the atom pong and a huge number that we will explain later, but to make it short, it's the id of the process that replied to us.

Exploring the Template Files

The template created a lot of files and if you are like me, you don't like things that make magic and don't explain what's going on, that's why we will get a brief overview of the files created here.

First this files are created:

apps/tanodb/src/tanodb.app.src
apps/tanodb/src/tanodb.erl
apps/tanodb/src/tanodb_app.erl
apps/tanodb/src/tanodb_sup.erl
apps/tanodb/src/tanodb_console.erl
apps/tanodb/src/tanodb_vnode.erl

Those are the meat of this project, the source code we start with, if you know a little of erlang you will recognice many of them, let's explain them briefly, if you think you need more information I recommend you this awesome book which you can read online: Learn You Some Erlang for great good!

tanodb.app.src
This file is "The Application Resource File", you can read it, it's quite self descriptive. You can read more about it in the Building OTP Applications Section of Learn You Some Erlang or in the man page for app in the Erlang documentation.
tanodb.erl
This file is the main API of our application, here we expose all the things you can ask our application to do, for now it can only handle the ping() command but we will add some more in the future.
tanodb_app.erl
This file implements the application behavior it's a set of callbacks that the Erlang runtime calls to start and stop our application.
tanodb_sup.erl
This file implements the supervisor behavior it's a set of callbacks that the Erlang runtime calls to build the supervisor hierarchy.
tanodb_console.erl
This file is specific to riak_core, it's a set of callbacks that will be called by the tanodb-admin command.
tanodb_vnode.erl
This file is specific to riak_core, it implements the riak_code_vnode behavior, which is a set of callbacks that riak_core will call to accomplish different tasks, it's the main file we will edit to add new features.

Those were the source code files, but the template also created other files, let's review them

rebar.config
This is the file that rebar3 reads to get information about our project like dependencies and build configuration, you can read more about it on the rebar3 documentation
.editorconfig
This file describes the coding style for this project, if your text editor understands editorconfig files then it will change it's setting for this project to the ones described in this file, read more about editor config on the editorconfig website
.gitignore
A file to tell git which files to ignore from the repository.
README.rst
The README of the project
Makefile
A make file with some targets that will make it easier to achieve some complex tasks without copying and pasting too much.
config/admin_bin
A template for the tanodb-admin command.
priv/01-tanodb.schema
The cuttlefish schema file that describes what configuration our application supports, it starts with some example configuration fields that we will use as the application grows.
config/advanced.config
This file is where we configure some advanced things of our application that don't go on our tanodb.config file, here we configure riak_core and our logging library
config/vars.config
This file contains variables used by relx to build a release, you can read more about it in the rebar3 release documentation

The following files are like vars.config but with slight differences to allow running more than one node on the same machine:

config/vars_dev1.config
config/vars_dev2.config
config/vars_dev3.config

Normally when you have a cluster for your application one operating system instance runs one instance of your application and you have many operating system instances, but to test the clustering features of riak_core we will build 3 releases of our application using offsets for ports and changing the application name to avoid collisions.

Those are all the files, follow the links to know more about them.

Playing with Clustering

Before starting to add features, let's first play with clustering so we understand all those config files above work.

Build 3 releases that can run on the same machine:

make devrel

This will build 3 releases of the application using different parameters (the dev1, dev2 and dev3 files we saw earlier) and will place them under:

_build/dev1
_build/dev2
_build/dev3

This is achived by using the profiles feature from rebar3.

Now open 3 consoles and run the following commands one on each console:

make dev1-console
make dev2-console
make dev3-console

This will start the 3 nodes but they won't know about each other, for them to know about each other we need to "join" them, that is to tell one of them about the other two, this is achieved using the tanodb-admin command, here is how you should run it manually (don't run them):

_build/dev2/rel/tanodb/bin/tanodb-admin cluster join tanodb1@127.0.0.1
_build/dev3/rel/tanodb/bin/tanodb-admin cluster join tanodb1@127.0.0.1

We tell dev2 and dev3 to join tanodb1 (dev1), to make this easier and less error prone run the following command:

make devrel-join

Now let's check the status of the cluster:

make devrel-status

You can read the Makefile to get an idea of what those commands do, in this case devrel-status does the following:

_build/dev1/rel/tanodb/bin/tanodb-admin member-status

You should see something like this:

================================= Membership ===============
Status     Ring    Pending    Node
------------------------------------------------------------
joining     0.0%      --      'tanodb2@127.0.0.1'
joining     0.0%      --      'tanodb3@127.0.0.1'
valid     100.0%      --      'tanodb1@127.0.0.1'
------------------------------------------------------------
Valid:1 / Leaving:0 / Exiting:0 / Joining:2 / Down:0

It should say that 3 nodes are joining, now check the cluster plan:

make devrel-cluster-plan

The output should be something like this:

=============================== Staged Changes ==============
Action         Details(s)
-------------------------------------------------------------
join           'tanodb2@127.0.0.1'
join           'tanodb3@127.0.0.1'
-------------------------------------------------------------


NOTE: Applying these changes will result in 1 cluster transition

#############################################################
                         After cluster transition 1/1
#############################################################

================================= Membership ================
Status     Ring    Pending    Node
-------------------------------------------------------------
valid     100.0%     34.4%    'tanodb1@127.0.0.1'
valid       0.0%     32.8%    'tanodb2@127.0.0.1'
valid       0.0%     32.8%    'tanodb3@127.0.0.1'
-------------------------------------------------------------
Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

WARNING: Not all replicas will be on distinct nodes

Transfers resulting from cluster changes: 42
  21 transfers from 'tanodb1@127.0.0.1' to 'tanodb3@127.0.0.1'
  21 transfers from 'tanodb1@127.0.0.1' to 'tanodb2@127.0.0.1'

Now we can commit the plan:

make devrel-cluster-commit

Which should say something like:

Cluster changes committed

Now riak_core started an internal process to join the nodes to the cluster, this involve some complex processes that we will explore in the following chapters.

You should see on the consoles where the nodes are running that some logging is happening describing the process.

Check the status of the cluster again:

make devrel-status

You can see the vnodes transfering, this means the content of some virtual nodes on one tanodb node are being transferred to another tanodb node:

================================= Membership =============
Status     Ring    Pending    Node
----------------------------------------------------------
valid      75.0%     34.4%    'tanodb1@127.0.0.1'
valid       9.4%     32.8%    'tanodb2@127.0.0.1'
valid       7.8%     32.8%    'tanodb3@127.0.0.1'
----------------------------------------------------------
Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

At some point you should see something like this, which means that the nodes are joined and balanced:

================================= Membership ==============
Status     Ring    Pending    Node
-----------------------------------------------------------
valid      34.4%      --      'tanodb1@127.0.0.1'
valid      32.8%      --      'tanodb2@127.0.0.1'
valid      32.8%      --      'tanodb3@127.0.0.1'
-----------------------------------------------------------
Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

When you are bored you can stop them:

make devrel-stop

Building a Production Release

Even when our application doesn't have the features to merit a production release we are going to learn how to do it here since you can later do it at any step and get a full release of the app:

make prod-release

In that command rebar3 runs the release task using the prod profile, which has some configuration differences with the dev profiles we use so that it builds something we can unpack and run on another operating system without installing anything.

Let's package our release:

cd _build/prod/rel
tar -czf tanodb.tgz tanodb tanodb_config
cd -
mv _build/prod/rel/tanodb.tgz .

You can copy it to a clean OS and run:

tar -xzf tanodb.tgz
./tanodb/bin/tanodb console

And it runs!

Note

You should build the production release on the same operating system version you are intending to run it to avoid version problems, the main source of headaches are C extensions disagreeing on libc versions and similar.

So, even when you could build it on a version that is close and test it it's better to build releases on the same version to avoid problems. More so if you are packaging the Erlang runtime with the release as we are doing here.

Wrapping Up

Now you know how to create a riak_core app from a template, how to build a release and run it, how to build releases for a development cluster, run the nodes, join them and inspect the cluster status and how to build a production release and run it on a fresh server.