![]() |
#331 | |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
|
Quote:
|
|
![]() |
![]() |
![]() |
#332 | |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Quote:
A custom icon rule would extract the category of interest, separate out the rating, then choose the appropriate icon. |
|
![]() |
![]() |
Advert | |
|
![]() |
#333 |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
That is a good solution. "from_search" and "for" work together well in this case. Get the list of categories of interest, loop through them searching for books, compute the mean, then construct the result.
|
![]() |
![]() |
![]() |
#334 |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
|
@chaley: The chain variables action already has a column (the value column) that accepts templates as value. I am thinking about adding the new functionality to this action; by adding a third column with a checkbox. When checked, the template will iterate over all books. I will also make right clicking the value cell pop up the template dialog.
I think that way you can, if you choose, skip the set_globals part because the new value will be automatically re-assigned to the named variable (the name column). Any thoughts? Edit: set_global would still be used if a user wants to set more than one variable, as in your previous example, but must be sure to choose a different identifier in the chains variable name column. Last edited by capink; 02-19-2021 at 06:24 AM. |
![]() |
![]() |
![]() |
#335 |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
|
Another thing, does it make sense to persist some variables beyond the lifetime of the current chain? Maybe with additional option, or a certain prefix!
|
![]() |
![]() |
Advert | |
|
![]() |
#336 |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,012
Karma: 500000
Join Date: Jun 2015
Device: Rocketbook, kobo aura h2o, kobo forma, kobo libra color
|
Is there a reason to clear all the variables every time? Why not just leave them there, and if a chain wants to zero out totals before starting, it should be able to set them all at the start of the chain.
Is that too messy? |
![]() |
![]() |
![]() |
#337 | |||
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Quote:
![]() Quote:
Quote:
|
|||
![]() |
![]() |
![]() |
#338 |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Average Rating example
This example action computes the average rating for 3 Genres and their children then stores those ratings in a tags-like custom column in the form 'genre name':average_rating.
Here is the complete chain: It starts by selecting all the books in the library: It then runs a template to compute the average ratings, saving that value in a chain variable (global): The template in the chain variables action is: Code:
program: genres = 'Comics, Mysteries, Science Fiction'; res = ''; for g in genres: ratings = from_search('rating', strcat('#genre:"=.', g, '"')); total = 0; cnt = 0; for r in ratings: if r != "None" then total = add(total, r); cnt = add(cnt, 1) fi rof; if cnt ># 0 then avg = divide(divide(total, 2), cnt) else avg = 0 fi; res = list_union(res, strcat(g, ':', avg), ',') rof; res @capink:I couldn't get the mean() function to work. How do I convert the result of "from_search()" to an "iterable"? Next it saves the computed value to a tags-like column: The template in the Single Field Edit is Code:
program: globals(avg_ratings = ''); Code:
Comics:1.5, Mysteries:2.0, Science Fiction:3.0 |
![]() |
![]() |
![]() |
#339 |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
BTW: there is a bug in the "for" statement. It doesn't strip leading and trailing blanks from list items. The above template uses a fixed version. The bug can be worked around using re() to strip of leading and trailing blanks. Or
Code:
g = list_item(g, 0, ','). |
![]() |
![]() |
![]() |
#340 | |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Quote:
The next question is their lifetime. Do they live for the calibre invocation, while a library is open, while a VL is open, or something else? |
|
![]() |
![]() |
![]() |
#341 | |||
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
|
Quote:
![]() Quote:
This is working for me: Code:
program: genres = 'Comics,Mysteries,Science Fiction'; res = ''; for g in genres: ratings = from_search('rating', strcat('#genre:"=.', g, '"')); avg = mean(ratings); res = list_union(res, strcat(g, ':', avg), ',') rof; res Code:
program:
genres = 'Comics,Mysteries,Science Fiction';
res = '';
for g in genres:
ratings = from_search('rating', strcat('#genre:"=.', g, '"'));
ratings = re_non_numerical(ratings, 0);
avg = mean(ratings);
res = list_union(res, strcat(g, ':', avg), ',')
rof;
res
Quote:
Edit1: No need to create a template function for that. If a user wants to persist data, he can create an empty book record and use the single field edit to persist data to it. Edit2: from_search() and from_selection() always return an iterable (comma separated values). Last edited by capink; 02-19-2021 at 10:31 AM. |
|||
![]() |
![]() |
![]() |
#342 | |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Note that in both cases you must divide the result of mean() by 2, either at the call or later in the list_union. For historical reasons calibre keeps ratings as numbers between 0 and 10. One star == 2, two stars == 4, etc.
The following template does that divide. I also changed the search to include only rated books so that the template can avoid writing xxx:0 if no books with that category are rated. Code:
program: genres = 'Comics, Mysteries, Science Fiction'; res = ''; for g in genres: ratings = from_search('rating', strcat('rating:true and #genre:"=.', g, '"')); if ratings then avg = divide(mean(ratings), 2); res = list_union(res, strcat(g, ':', avg), ',') fi rof; res Quote:
BTW: this is fun, all of figuring out the details of how action chains works, the "logic problem" of how to chain the steps, and constructing templates that compute what is needed. I also am finding some template functions that I might add. One is[list_]count_matching(l, sep, pattern) that returns how many items in l match the pattern. |
|
![]() |
![]() |
![]() |
#343 |
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
The fix to the for statement is now in master source.
|
![]() |
![]() |
![]() |
#344 | |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
|
Quote:
I think as chaley pointed out, it is better not to persist variables because you are going to run into scope problems. However, the user has the option to persist some variables before exiting the chain. This can be done by creating and empty book and calling it something like 'persistent storage'. You can persist whatever data you want into this book, by using the selection modifier to select it, then the single field edit template option to persist. |
|
![]() |
![]() |
![]() |
#345 | |||
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
|
Quote:
![]() Quote:
Quote:
![]() Good. I will wait a couple of days and go ahead with the changes. |
|||
![]() |
![]() |
![]() |
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
[Editor Plugin] Editor Chains | capink | Plugins | 106 | 06-17-2025 05:36 PM |
Action Chains Resources | capink | Plugins | 77 | 06-16-2025 12:45 PM |
[GUI Plugin] Noosfere_util, a companion plugin to noosfere DB | lrpirlet | Plugins | 2 | 08-18-2022 03:15 PM |
[GUI Plugin] Save Virtual Libraries To Column (GUI) | chaley | Plugins | 14 | 04-04-2021 05:25 AM |