Getting max from a string list in jinja2 - jinja2

I would like to get a max value from a list. I have a homeassistant configuration that I would like to work, but for some reason list is considered as string value, and I get ] character as max value:
{% set value = ['nema','niska','nema'] %}
{% set list = value | replace("nema", 0 ) | replace("niska", 1 | int) | replace("visoka", 2) | replace("vrlovisoka", 3) %}
{{ list | max }}
If I use {{ list | map('int') | max }} like other posts suggest, I just get an error ValueError: Template error: int got invalid input '[' when rendering template
How can I make this work?

Related

How to convert JSON timestamp to time using Jinja?

I have this simple JSON:
{
"ts": "2022-07-17T09:24:21.840227"
}
and I would like to know what date it is using Jinja.
I tried these two variations:
{{ ts | iso8601_to_time | datetimeformat('%a, %B %d %Y, %H:%M:%S') }}
{{ ts | timestamp_to_time | datetimeformat('%a, %B %d %Y, %H:%M:%S') }}
but both of them are throwing actual time.
I would expect something like this:
Sun, July 17 2022, 09:24:17
How can I achieve this format?
Ok, I figured it out in a meanwhile:
{% set myDate = ts | split('.') %}
{% set myDateFinal = myDate[0]+'Z' %}
{{ myDateFinal | strtotime("yyyy-MM-dd'T'HH:mm:ssXXX") | datetimeformat('%a, %B %d %Y, %H:%M:%S') }}
Basically:
Split by "." sign (makes array of what is left[0] and right[1] from dot)
[2022-07-17T09:24:21, 840227]
Look at the first (left) part and add "Z" sign
2022-07-17T09:24:21Z
Do some magic
Done!

what does # symbol do in this [#][] ansible code?

I would like to know what # symbol does in this line of code and [#][] do? This is being used in Ansible. Thank you.
json_query("response.result.job | [#][]")
The whole code:
- name: task1
<removed for simplicity>
cmd: 'show jobs all'
register: all_jobs
until: |
all_jobs is not failed
and (all_jobs.stdout | from_json | json_query("response.result.job|[#][]") | default([], true) | length > 0)
and (all_jobs.stdout | from_json | json_query("response.result.job|[#][]")
| json_query("[?status != 'FIN']") | length == 0)
retries: 60
delay: 30
For those who are curious, I think I found the answer. It is all about jmespath. # is the current node. [] will flat a list. [][] will flat nested lists. [#][] will flat second level list. To understand this please go to this link below. There are examples there.
https://jmespath.org/tutorial.html

Convert accent characters to normal characters in Liquid

For instance name = Florian Müllner, want name to be Florian MUllner
How to covert name with accented characters in Liquid?
Read the replace doc, but was not able to figure out. How to use?
This is my very very dirty solution and far from complete (but works for my needs) with no plugins in Jekyll:
{% assign text = 'Müller Pérez' %}
{% include normalize_text.html %}
and the included file works as a function:
{% assign text = text | replace: 'á', 'a' | replace: 'é', 'e' | replace: 'í', 'i' | replace: 'ó', 'o' | replace: 'ú', 'u' %}
{% assign text = text | replace: 'à', 'a' | replace: 'è, 'e' | replace: 'ì', 'i' | replace: 'ò', 'o' | replace: 'ù', 'u' %}
{% assign text = text | replace: 'ä', 'a' | replace: 'ë', 'e' | replace: 'ï', 'i' | replace: 'ö', 'o' | replace: 'ü', 'u' %}
{% assign text = text | replace: 'â', 'a' | replace: 'ê, 'e' | replace: 'î', 'i' | replace: 'ô', 'o' | replace: 'û', 'u' %}
You can use replace like this.
{% assign text = 'Florian Müllner' | replace: "ü", "U" %}

How can I add a random number method in liquid that can called multiple times?

How can I add a random number in my liquid template files?
Is there something similar to PHP's rand()?
I have seen this used before, but if the variable is called in other places it displays the same number and is not randomized, even if multiple variables are created.
{% assign min = 65 %}
{% assign max = 80 %}
{% assign diff = max | minus: min %}
{% assign randomNumber = "now" | date: "%N" | modulo: diff | plus: min %}
This is how I am trying to accomplish it now:
<div class="contentDoubleWideWrap">
<div class="contentDoubleWideWrap">
{% assign min = 50 %}
{% assign max = 1000000 %}
{% assign diff = max | minus: min %}
{% assign randomNumber = site.time | date: "%s" | modulo: diff | plus: min %}
<div id="div-gpt-ad-1553024073723-{{ randomNumber }}" data-ad="div-gpt-ad-1553024073723-0" class="tmsads adContentDouble"></div>
</div>
<div class="contentDoubleWideWrap">
{% assign min2 = 50 %}
{% assign max2 = 1000000 %}
{% assign diff2 = max2 | minus: min2 %}
{% assign randomNumber2 = site.time | date: "%s" | modulo: diff2 | plus: min2 %}
<div id="div-gpt-ad-1553024121524-{{ randomNumber2 }}" data-ad="div-gpt-ad-1553024121524-0" class="tmsads adContentDouble"></div>
</div>
</div>
What you could do, it to define a prng, for example a linear congruential random number generator.
This works the following way:
you need a random seed (this can be date: "%N"),
you need the parameters of the rng: m, a, c
you need to specify the index into the generated pseudorandom series.
A good set of parameters:
m=2^31
a=1103515245
c=12345
This is used by GCC rand, see here for the link:
https://en.wikipedia.org/wiki/Linear_congruential_generator
the random number is created by (in pseudo code):
let x=seed
loop index times:
x=(a*x+c)%m
In this setting the random number you get from the generator can be further conditioned by the max, min, module parameters like you already did this for the date.
The only difference would be to use x instead of assign randomNumber = site.time | date: "%s"
You have almost everything in your code to do this. If you only need a few random numbers I would most probably simply unroll the loop in the pseudocode. Does that work for you?
Let me show how to implement the example you gave above:
<div class="contentDoubleWideWrap">
<div class="contentDoubleWideWrap">
{% assign min = 50 %}
{% assign max = 1000000 %}
{% assign diff = max | minus: min %}
{% assign seed = site.time | date: "%N" %}
{% assign randomNumber1 = seed | modulo: diff | plus: min %}
<div id="div-gpt-ad-1553024073723-{{ randomNumber1 }}" data-ad="div-gpt-ad-1553024073723-0" class="tmsads adContentDouble"></div>
</div>
<div class="contentDoubleWideWrap">
{% assign m = 2147483648 %}
{% assign a = 1103515245 %}
{% assign c = 12345 %}
{% assign min2 = 50 %}
{% assign max2 = 1000000 %}
{% assign diff2 = max2 | minus: min2 %}
{% assign randomNumber2 = seed | times: a | plus: c | modulo: m | modulo: diff2 | plus: min2 %}
<div id="div-gpt-ad-1553024121524-{{ randomNumber2 }}" data-ad="div-gpt-ad-1553024121524-0" class="tmsads adContentDouble"></div>
</div>
</div>
In this case x0 is seed and x1 the next state of the rng, you get randomNumber2 from that by modulo diff |plus: min2. To generate randomNumber3, you would repeate the a c and m filters one more time, like:
times: a | plus: c | modulo: m |times: a | plus: c | modulo: m
This can work if you only have a few random numbers to generate.
If you need more random numbers, you can use a loop instead to do the same thing.
The problem is that basically a static site is generated. What you could do is to move the random number generation to the client side, by using javascript. Does that work for you?
I bet it is possible via plugins, e.g. https://github.com/codecalm/jekyll-random
random_number(index, min=0, max=100, round=0)
Returns a number between min and max based on index. By default it returns a number between 0 and 100.
{% for i in (1..100) %}
{{ i }} - {{ forloop.index | random_number: 0, 10 }}
{% endfor %}
The code above returns random numbers like:
1 - 6
2 - 1
3 - 6
4 - 8
5 - 4
6 - 7
7 - 1
...

Computing a Weighted Average with Liquid Template Filters

I'm using Jekyll with its Liquid Templates hosted on Github Pages and I'd like to compute a weighted average, but I don't see a way to deal with order of operations using Liquid math filters.
For example I'd like to compute something like:
{{ (page.x | times:.4) | plus:(page.y | times:.6) }}
--> (x * .4) + (y * .6)
But it seems the parenthesis are ignored an I'm effectively getting:
{{ page.x | times:.4 | plus:page.y | times:.6 }}
--> (((x * .4) + y) * .6)
Liquid filters are applied one at a time in the order they appear, using the former value. You cannot change precedence with parenthesis (you can only do this with if conditionals).
Here you have to split you operation like this :
{% assign a = x | times:.4 %}
{% assign b = y | times:.6 %}
{% assign c = a | plus: b %}