3

I'm in the middle of a very long project developing a league site for the National Collegiate Wrestling Association in my spare time (once finished, could be a great showcase for Craft).

Currently, I'm trying to implement a points system, where athletes accumulate points based on the matches they win & how they win them.

Here's a screenshot of an athletes stat page (wip) http://cl.ly/image/3L2A0e2x1q3v

All the results are tied to an event, so the points can be recalculated easily if an event has to be removed for whatever reason, or a coach inputs the wrong kid by accident.

There is quite a bit of logic being done here, but manageable, and can be cached- but teams also accumulate points based on the points of the top 11 athletes in their roster!

This means the points will have to be calculated and displayed on

  • The Team's page (11x the queries)
  • The Index page of all Teams

Currently, the only way I know how to do this, will be some heavy nesting of conditionals in loops- repeating the process of each athlete.

I know doing it this way, all in the templates, is extremely unorthodox. I'm 99.9% this would be much easier to implement with plugins somehow, but unfortunately I don't know PHP nor do I have the time to invest in the trial/error learning process of how to write plugins in the time needed. So I'm kinda up against a wall here and looking for solutions to smooth out this process, regardless of how hacky it may be.

Maybe there's a way to only perform these massive queries in the middle of the night, and the points total only updates once per day, no matter how many results are inputted in the 24-hour period? I don't know. Please help me, very kind Craft community :)


Update: Added requested template logic... Removed extra unnecessary code for readability & sake of space. Team pages & Teams Index page won't require all the information displayed in screenshot (date, opponent, score/time, pt diff)

{% set athlete = craft.users.id( craft.request.lastSegment ).first %}
{% set results = craft.entries.section('results').relatedTo({
    targetElement: athlete,
    field: 'matches',
}) %}
{% set points = 0 %}
{% if results|length %}

  {% for result in results %}
    {% for block in result.matches %}
      {% if (athlete.id == block.winner.first.id) or (athlete.id == block.loser.first.id) %}

          {% if block.winner|length and (athlete.id == block.winner.first.id) %}
            {% if (block.result == "Maj") or (block.result == "Dec") %}
               {% set points = (points + 5) %}
               {% set difference = "+5" %}
              {% else %}
                {% set points = (points + 6.1) %}
                {% set difference = "+6.1" %}
            {% endif %}
          {% endif %}

          {% if block.loser|length and (athlete.id == block.loser.first.id) %}
            {% if athlete.id == block.loser.first.id %}
              Lost by {{ block.result.label }}
                {% set points = points - 1.75 %}
                {% set difference = "-1.75" %}
                {% set negative %}{% endset %}
            {% endif %}
          {% endif %}

      {% endif %}
    {% endfor %}
  {% endfor %}
{% endif %}



{% set tournaments = craft.entries.section('results').relatedTo({
  targetElement: athlete,
  }) %}
{% if tournaments|length %}
  {% for tournament in tournaments %}

    {% if tournament.type.handle == 'minorTournament' %}
      {% for w in 1..3 %}
        {% for p in 1..3 %}
          {% if (tournament['w'~w~'p'~p]|length) and (tournament['w'~w~'p'~p].first.id == athlete.id) %}

            {% switch loop.index %}
              {% case "1" %}
              {% set points = (points + 6) %}
              {% case "2" %}
              {% set points = (points + 4) %}
              {% case "3" %}
              {% set points = (points + 2) %}
            {% endswitch %}

          {% endif %}
        {% endfor %}
      {% endfor %}
    {% endif %}
  {% endfor %}
{% endif %}

Points:>{{points}}
  • Hey Chase, could you please just clarify exactly what logic you are currently doing? Or even just a snippet so we can understand how you are calculating these figures, thanks :) – Alec Ritson Aug 17 '15 at 8:57
  • Hi @AlecRitson. I've updated the question with the necessary code that will needed on the team pages and teams index page. Thanks for taking a look! – Chase Giunta Aug 17 '15 at 21:00
1

Without wanting to go into any PHP or plugin development, your best bet is to set a 24 hour cache on your chunk of processing code. As you suggested, it is probably smart to not have the cache clear itself when an entry is saved. To accomplish this, just set cacheElementQueries to false in your general config file.

| improve this answer | |
1

From the looks of your code, I don't think its actually too bad, I mean there is a lot of logic going on but if its manageable for you, then really thats all that matters.

Twig is also just a template engine for PHP:

Twig compiles templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum.

This means that if you're template logic is from memory then it should be super quick, which it looks like yours is.

The problem would be if you had database queries nested within your {% for %} loops, this is when it gets pretty intensive and would slow your templates down, but as it looks like all your queries take place out of the loops, so you shouldn't be in too much trouble and as Aaron states, you can easily set a cache which will speed things up even more.

In short, if your templates are loading quick enough for you and you feel your code is manageable, then don't worry too much. The thing I try and personally keep to is keep database queries out of loops as much as possible

I hope that helps :)

| improve this answer | |
  • Thanks for the input Alec. I think my concern is the potential to have all this looping easily over 1,000+ times. There's around 1,700 athletes in the league, so on the index page, calculating ALL the points would be a mess, I assume. I'm most likely going to paginate that data though, to only display the top 10 teams- which will still be the most expensive query: the top teams will have the most active athletes tallying the most points (~18x10 times the queries on my single bio template) . So, knowing this whole template might be placed a couple more nested for loops, still think I'm ok? – Chase Giunta Aug 18 '15 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.