• flickr
  • instagram
  • lastfm
  • linkedin
  • spotify
  • twitter
  • Goodreads
  • GitHub
  • juanignaciosl.github.io
Wedding Tables Planner

Wedding Tables Planner

Some years ago I worked a lot with many JBoss Open Source products: jBPM, Teiid, JBoss ESB… They’ve got some pretty cool stuff, check it out. One of my all-time favorites is Drools, which begun as a Rete algorithm implementation as a tool for business rules, but it has evolved and branched a lot.

One of the products born under Drools umbrella was OptaPlanner, a planning engine. You can use OptaPlanner to get solutions to planning np-problems like job scheduling or traveller salesman route. This kind of tools are, IMHO, one of the biggest advantages of the JVM over any other platform.

Wedding Tables Planner

I wanted to take a look at OptaPlanner but I didn’t view a suitable problem, so I decided to get married =D (just kidding, don’t want to get divorced even before of the wedding!). As every poor married person knows one of the most sensitive moments while you plan that day is the arrangement of the guests at the restaurant. Tables have capacity boundaries and not every guest is interchangeable: many of them are just known, some love each other and some even hateThis looks like a planning problem!

You can check out the Wedding Tables Planner at GitHub. It’s not rocket science, certainly. Since it’s a straightforward application of OptaPlanner it’s really simple. There’s a XML config file where you set some information about your model, and give OptaPlanner some hints about the way it should look for a suitable solution. In my case I set a HARD_SOFT score, which is the number it uses to compare solutions. It’s composed of a hard and a soft score (as you, smart reader, already supposed ;-) ). The hard score is the primary number to minimize. In my case it’s the following formula:

final int hardScore = 
  + configuration.hatedRelationsInTheSameTable()
  + configuration.lovedRelationsNotInTheSameTable();

As you can see, I don’t want anybody to eat on his feet (exceed table capacity), begin a fight with the knives (hated relationships in the same table), or miss the loved one(s). OptaPlanner will try to keep hardScore at 0.

OptaPlanner will try to maximize the following soft score formula:

final int softScore = 
    4 * configuration.closeRelationsInTheSameTable()
  + 2 * configuration.knownRelationsInTheSameTable()
  - configuration.neededTables().size();

The most important relation for me is being close, but I also want to keep as many known people together. Since I prefer nobody to be alone, I also try to keep needed tables as low as possible.

That’s pretty much the only thing you need for OptaPlanner to work. It’s launched with the following code

public DiningConfiguration planTables(
    final DiningConfiguration unsolvedDiningConfiguration) {
  final SolverFactory solverFactory = new XmlSolverFactory(
  final Solver solver = solverFactory.buildSolver();

  return solver.getBestSolution();

Offtopic: I’ve used Java 8 lambdas. It’s certainly not as clean as Scala’s, type inference is not impressive at all and  you must keep NullPointerExceptions in mind, but it’s fat better than what we had to do until now:

private Set<Guest> sharingTableGuests(final Guest guest) {
return guests
    .filter(aGuest -> aGuest.getTable() != null)
    .filter(tableGuest -> !guest.equals(tableGuest))
    .filter(otherGuest -> otherGuest.getTable().equals(

 Wedding Tables Planner Web

The core of the solver is great and simple, but you won’t force a bride-to-be to learn Java one month before her wedding, so I developed an AngularJS + Play + Scala web (my current stack of choice). It’s not the most beautiful or usable piece of software you might’ve seen, but it does the job.

I’ve used the brand new Activator template for AngularJS and Play applications. It uses WebJars and Require.js for client-side dependencies (neat!). UI is Bootstrap and Less based (although I always use Sass). AngularJS is great and you should be using it right now ;-).

Guest information components looks like this:

Wedding Tables Planner: guests

In order to be a little more confortable, the app allows you to create groups, which get translated into «known» relationships (you don’t want your implementation details to get leaked to your users!). There’s one special group, «All users», which is always active, but clicking other groups switch auto-insertion of guests on and off.

You can detail guest relationship by dragging one on top of another (native AngularJS drag and drop provided by angular-dragdrop):

Guests relationship

When you’ve entered your guests, you just have to tell the app the amount and sizes of the tables you have, and press the «Arrange guests» button.

Final steps

The core is 100% Java, but the controller is Scala (40 lines). Scala supports Java, but it doesn’t feel too confortable. You have to do some ugly collections transformation code from time to time:

val sourceProblem = new DiningConfiguration(HashSet(tables.toArray: _*), HashSet(guestByName.values.toArray: _*))

Maybe I’ll deploy it somewhere so you can try it without cloning repo, stay tuned!

[UPDATE 27/05/2014: you can try it online at http://weddingtablesplanner-juanignaciosl.rhcloud.com/ . Thank you, OpenShift!]

PD: some of you are testing the app (thank you!), it’d be nice if you tell me about bugs or unexpected behavior at GitHub project issues.

8 Comentarios

  1. Geoffrey De Smet · mayo 27, 2014

    Try deploying it on OpenShift (free java webapp cloud provisioning), so people can just try it out.
    The free account should cover it’s needs untill it becomes a global success :)

  2. Gustavo Yasue · mayo 28, 2014

    Muy bueno Juan Ignacio!!, excelente ejemplo y simple.

  3. erics · mayo 29, 2014

    Are you going to post or point to an OpenShift setup that can be repeated by anyone wanting to use your nice project?

    Need things like this: https://github.com/eschabell/openshift-bpm-process-designer

    Note this is just a JBoss AS gear that then I deploy a java WAR into, but for me who does not play in your ‘stack’ it would be fun to push your example project far and wide (evangelize) if you can make it repeatable. ;)

¿Me dejas una respuesta?

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.