Building a mulit-dynamic HTML-Table with Wicket - wicket

I have a very strange dynamic table that represents a daily shopping cart. The table lists a variable amount of options for each day. Each day can have 0 or even n options. The user, can add any of this n options to his selections. So the options part and also the selections part can grow dynamically.
+-------+-------+-------+-------+-------+-------+-------+-------+---
| THE | OPTIONS | SELECTIONS ...
| DAY +-------+-------+-------+-------+-------+-------+-------+---
| | OPT 1 | OPT 2 | OPT3 | OPT n | 1.SEL | 2.SEL | 3.SEL | ...
+=======+=======+=======+=======+=======+=======+=======+=======+===
| day 1 | opt 1 | opt 2 | | | opt 2 | opt 1 | opt 1 | ...
+-------+-------+-------+-------+-------+-------+-------+-------+---
| day 2 | opt 1 | opt 2 | opt 3 | opt n | opt n | | | ...
+-------+-------+-------+-------+-------+-------+-------+-------+---
| day 3 | opt 1 | opt 2 | | | opt 1 | | | ...
+-------+-------+-------+-------+-------+-------+-------+-------+---
| day 4 | | | | | | | | ...
+-------+-------+-------+-------+-------+-------+-------+-------+---
| day 5 | opt 1 | opt 2 | | | opt 2 | | | ...
+-------+-------+-------+-------+-------+-------+-------+-------+---
| day 6 | opt 1 | ...
+-------+-------+---
| day 7 | ...
+-------+---
| ...
+---
Now I want to write code, that can generate a dynamic table, that considers the variable amount of days, options and selections. The tricky part is to dynamically add empty cells to the options columns as well as to the selection columns so that all cells have the right alignment to their corresponding table part.
I always found some examples, but all suffer from calculation the right amount of option-cells to align the user selections.
Do you have any suggestions how to build such a table? Or do you have any further considerations?

First you should calculate the maximum number of existing options and selections, let them be N and M.
Then after rendering the options of a day, determine the number of blank cells (N - current number of options) And add the same number of empty <td> of alternatively only one <td> with the attribute hspan set to the number of blank cells.
And do the same for selections.

Related

Get the max value for each column in a table

I have a table for player stats like so:
player_id | game_id | rec | rec_yds | td | pas_att | pas_yds | ...
--------------------------------------------------------
1 | 3 | 1 | 5 | 0 | 3 | 20 |
2 | 3 | 0 | 8 | 1 | 7 | 20 |
3 | 3 | 3 | 9 | 0 | 0 | 0 |
4 | 3 | 5 | 15 | 0 | 0 | 0 |
I want to return the max values for every column in the table except player_id and game_id.
I know I can return the max of one single column by doing something like so:
SELECT MAX(rec) FROM stats
However, this table has almost 30 columns, so I would just be repeating the query below, for all 30 stats, just replacing the name of the stat.
SELECT MAX(rec) as rec FROM stats
This would get tedious real quick, and wont scale.
Is there any way to kind of loop over columns, get every column in the table and return the max value like so:
player_id | game_id | rec | rec_yds | td | pas_att | pas_yds | ...
--------------------------------------------------------
4 | 3 | 5 | 15 | 1 | 7 | 20 |
You can get the maximum of multiple columns in a single query:
SELECT
MAX(rec) AS rec_max,
MAX(rec_yds) AS rec_yds_max,
MAX(td) AS td_max,
MAX(pas_att) AS pas_att_max,
MAX(pas_yds) AS pas_yds_max
FROM stats
However, there is no way to dynamically get an arbitrary number of columns. You could dynamically build the query by loading all column names of the table, then apply conditions such as "except player_id and game_id", but that cannot be done within the query itself.

Dynamically grow user selection when they have selected "all"

I have users with multiple email preferences and I want to grow their preference selection when new preference options are added if they have selected 'all' as their preference.
I can do this through triggers for each of the preference options table. On INSERT I can also UPDATE the user preference array and append the new options. I am worried about performance when the user list begins to grow since each preference option may be updated and each user can have multiple preferences.
USER_1
PREFERENCE_1
OPTION_1 -> ALL
OPTION_2 -> [1, 2, 3]
OPTION_3 -> [1, 2]
PREFERENCE_2
OPTION_1 -> ALL
OPTION_2 -> ALL
OPTION_3 -> ALL
How should I design the schema to accommodate dynamic column arrays? Or perhaps I shouldn't be using arrays at all?
Additional question:
Is it possible to achieve the All but x selection? A user may want all of the options but not some of the options. The selection should still grow dynamically.
It looks like your question isn't getting much love around here.
You have a couple of options. The best option is to build out the relational tables to store this, but you will need to use a trigger or another indicator column to denote that a user is up for every option.
A second option that I have used a number of times is a bitstring. This is essentially a bitmask. The only regret I have about using this is having to explain how it works to developers fresh out of some shake-and-bake correspondence course who fancy themselves "full-stack."
create table preference (
bitmask bit(30) not null primary key, -- Adjust size to some overkill number
pref_name text
);
insert into preference
select ((2^n)::bigint)::bit(30) as bitmask,
'Option '||(n+1)::text as pref_name
from generate_series(0, 10, 1) as gs(n);
create table prefs_user (
id int primary key,
user_name text,
user_prefs bit(30)
);
insert into prefs_user values
(1, 'me', ~(0::bit(30))),
(2, 'you', 22::bit(30)),
(3, 'him', ~(8::bit(30))); -- all except Option 4
To join to see which options are enabled for a prefs_user:
select *
from prefs_user u
join preference p
on (u.user_prefs & p.bitmask)::bigint > 0
order by u.id, p.bitmask;
id | user_name | user_prefs | bitmask | pref_name
----+-----------+--------------------------------+--------------------------------+-----------
1 | me | 111111111111111111111111111111 | 000000000000000000000000000001 | Option 1
1 | me | 111111111111111111111111111111 | 000000000000000000000000000010 | Option 2
1 | me | 111111111111111111111111111111 | 000000000000000000000000000100 | Option 3
1 | me | 111111111111111111111111111111 | 000000000000000000000000001000 | Option 4
1 | me | 111111111111111111111111111111 | 000000000000000000000000010000 | Option 5
1 | me | 111111111111111111111111111111 | 000000000000000000000000100000 | Option 6
1 | me | 111111111111111111111111111111 | 000000000000000000000001000000 | Option 7
1 | me | 111111111111111111111111111111 | 000000000000000000000010000000 | Option 8
1 | me | 111111111111111111111111111111 | 000000000000000000000100000000 | Option 9
1 | me | 111111111111111111111111111111 | 000000000000000000001000000000 | Option 10
1 | me | 111111111111111111111111111111 | 000000000000000000010000000000 | Option 11
2 | you | 000000000000000000000000010110 | 000000000000000000000000000010 | Option 2
2 | you | 000000000000000000000000010110 | 000000000000000000000000000100 | Option 3
2 | you | 000000000000000000000000010110 | 000000000000000000000000010000 | Option 5
3 | him | 111111111111111111111111110111 | 000000000000000000000000000001 | Option 1
3 | him | 111111111111111111111111110111 | 000000000000000000000000000010 | Option 2
3 | him | 111111111111111111111111110111 | 000000000000000000000000000100 | Option 3
3 | him | 111111111111111111111111110111 | 000000000000000000000000010000 | Option 5
3 | him | 111111111111111111111111110111 | 000000000000000000000000100000 | Option 6
3 | him | 111111111111111111111111110111 | 000000000000000000000001000000 | Option 7
3 | him | 111111111111111111111111110111 | 000000000000000000000010000000 | Option 8
3 | him | 111111111111111111111111110111 | 000000000000000000000100000000 | Option 9
3 | him | 111111111111111111111111110111 | 000000000000000000001000000000 | Option 10
3 | him | 111111111111111111111111110111 | 000000000000000000010000000000 | Option 11
User me selected all options, so any options you add up to a count of 30 will always be selected.
User you selected only three options. Adding options will not affect the user's selection.
User him selected every option except option 4. New options will be selected for this user.
The bit string maps easily to an array from a checkbox group with name properties set to log-base-2 of the bitmask:
select log(2, bitmask::bigint)::int, pref_name from preference;
log | pref_name
-----+-----------
0 | Option 1
1 | Option 2
2 | Option 3
3 | Option 4
4 | Option 5
5 | Option 6
6 | Option 7
7 | Option 8
8 | Option 9
9 | Option 10
10 | Option 11
(11 rows)
When the post comes in, you can create the bitmap value through a simple loop or list comprehension on the host language side.

Crystal Reports - Dynamic Grouping depending on Summary field

Trying to group dynamically depending on the field I sum using Summary. Example: table looks like
Person | Date 1 | Category 1 | Date 2 | Category 2 |
John | 1/1/2010 | minor | 1/1/2015 | major |
Paul | 1/1/2010 | minor | 1/1/2015 | minor |
I want to group dynamically by [major; minor] using sum of entries, like:
| 1/1/2010 | 1/1/2015 |
major | 0 | 1 |
minor | 2 | 1 |
This is a simple example but there could be dynamic categories from the input dataset, not just 2 hardcoded values.
Not sure if this is possible in Crystal Reports.
Thanks!

Tableau: DATEDIFF( 'days', MIN([Start Date]), [End Date])

Cheers!
I'm trying to get a chart working that shows me the count of work orders that are completed each day after work on a unit (serial number) starts. I'd like to be able to "shadow" multiple serial numbers on top of each other, normalized to a start date of '0'.
Currently I have columns in my data set:
Work order number (0..999), repeats for each serial number
Serial number (0..999)
Work order start date (Datetime)
Work order end date (Datetime)
Say for instance that a new serial number starts each day, contains 5 work orders, and requires 5 days to complete (there are 5 units in WIP at any given time).
The data might look like (dates shown as ints):
| Work order number | Serial number | Work order start date | Work order end date |
| ----------------- | ------------- | --------------------- | ------------------- |
| 1 | 1 | 1 | 2 |
| 2 | 1 | 1 | 3 |
| 3 | 1 | 2 | 4 |
| 4 | 1 | 3 | 5 |
| 5 | 1 | 4 | 5 |
| 1 | 2 | 2 | 3 |
| 2 | 2 | 2 | 4 |
| 3 | 2 | 3 | 5 |
| 4 | 2 | 4 | 6 |
| 5 | 2 | 5 | 6 |
I'm assuming I'll need a calculated column that would perhaps go something like:
[Work order end days since start] =
[Work order end date] - MIN(
IF(*serial number matches current*, [Work order start date], NULL)
)
I (clearly) have no idea how to actually create such a calculated field in Tableau.
The values in the column (same order as the data above) should be:
| Work order end days since start |
| ------------------------------- |
| 1 |
| 2 |
| 3 |
| 4 |
| 4 |
| 1 |
| 2 |
| 3 |
| 4 |
| 4 |
Any guidance or help? Happy to clarify anything as well. Many thanks! Cheers!
You will have better results with this kind of data if you reshape it to have a single date column and add a type column indicating whether the current row describes the start or completion of a workorder.
| Work order number | Serial number | date | type |
Think of each row representing a state change, not a work order.
Open work orders on a particular date would be those that have a start record prior to that date, but don't have a completion record prior to that date. If you define a calculated field as +1 if type = New and -1 if type = Completion, then you can use a running total of that field to view the number of open work orders over time.

Numbering the rows in reverse order in an Emacs Org Mode table

I'd like to do something like this:
How to achieve a row index column in Emacs Org Mode using a Calc column rule
but I'd like the rows to be numbered in reverse order. I suspect this should be very easy, and should have something to do with #>, but e.g. $1=#>-## doesn't work.
You can try this example
| row | data |
|-----+------|
| 8 | |
| 7 | |
|-----+------|
| 6 | |
| 5 | |
| 4 | |
| 3 | 5123 |
| 2 | |
| 1 | 4234 |
#+TBLFM: $1='(- (length org-table-dlines) ##)