FirstLegoLeague / displaySystem

Set of display tools
https://firstlegoleague.github.io/displaySystem/
4 stars 7 forks source link

Display should pull the team list from the scoring #31

Closed alanggreen closed 7 years ago

alanggreen commented 7 years ago

In our pilot we found that it is necessary to load the team list into the displaySystem as well as into fllscoring. It would be easier for setup if the displaySystem would pull the team list from the scoring

Note: seems like this is available (see Issue 30) but we didn't know how to use it.

rikkertkoppes commented 7 years ago

This is not in scope for diaplay system. Let me explain.

There are a few applications in the FLL github that are designed to be completely generic (display system, castDeck, clock spring to mind). As such we'd rather not have FLL specific functionality in it. These systems are designed to be also usable outside the FLL realm

For display system, it is designed to be able to display just about anything. Any feature requests that are generic enough to accomplish more of that are likely to get implemented.

The idea of display system is to have it work the other way around. Feed data into it. This can be done either manually via the control screen or programatically via mhub.

To show a team list in the display system, the way to do that is to push that data over mhub into the list view. I can see three ways to approach your use case.

1 Adjust scoring to push the correct data over mhub when needed.

This is a less than ideal approach, but would work. Less then ideal because it'd need fflscoring to have knowledge of the internal data structure of display system. Ideally, you'd rather have fllscoring to be able to publish data to basically anywhere

2 Create an adapter to sit in between both systems

This is the LEGO approach. Create standalone systems that can be developed independently, without having to keep in mind each others intricacies with regard to data format. An adapter layer in between would solve the snot-conversion. This is currently the approach in the Netherlands and we use mhub-relay for that (in fact, mhub-relay was designed for that). We have some docs and links to mhub-relay scripts here

If there is anything in that area you'd like to have cleared up, please let us know. The idea is that you could take it and use it with little effort. If that is not the case, I'd like to improve that.

3 Ignore anything I've said and implement new stuff in display system anyway.

This is also a valid approach. The software is open source. You can just break with our ideas if you want and take it and develop a separate fork of the software tailored to your own needs. This is the beauty of open source software. Ideas of the maintainers may not always be the best. So you can just take it on a divergent path and improve it to your own likings.

The only caveat here is that we should take care in communicating the pro's and con's of these divergent versions to our larger user base. A large number if separate versions may not be beneficial to clarity.

alanggreen commented 7 years ago

Ok, I understand your reasoning, and I like it. Seems to me that option 2 is the best option, and I'm going to check your link. I also think that I owe the amazing development group an explanation of what I'm trying to do here. I'll make that will be my next task.

alanggreen commented 7 years ago

Do you have a visual example (ideally a photo) of what the display looks like when piped through mhub-relay - as you do it for the Netherlands competitions?

Jheronymus commented 7 years ago

Not sure if this is what you are looking for... image Last time we used it as-is. The year before that Rikkert made some styling in the FLL theme for that year. You can use the example https://firstlegoleague.github.io/displaySystem/ to test it out.

alanggreen commented 7 years ago

Not really. Wanted to see scores from all 3 rounds - to know if the mhub-proxy knows how to do that.

On Mon, Jun 26, 2017 at 11:21 PM, Jeroen notifications@github.com wrote:

Not sure if this is what you are looking for... [image: image] https://user-images.githubusercontent.com/2046231/27558453-6ff263c0-5abd-11e7-9872-bb342b8528da.png Last time we used it as-is. The year before that Rikkert made some styling the FLL theme for that year. You can use the example https://firstlegoleague.github.io/displaySystem/ to test it out.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FirstLegoLeague/displaySystem/issues/31#issuecomment-311170669, or mute the thread https://github.com/notifications/unsubscribe-auth/AGccjYQR5DSoXuH8BIZVXvg3DM4OsUkhks5sIBLCgaJpZM4OEYaT .

rikkertkoppes commented 7 years ago

This is an area that needs a bit of work.

Current workings

Currently, there is a button and a bit of code in fllscoring that broadcasts the rankings on the message bus. That bit can be found here

Note the comments in the code. The broadcasted message is now very much tailored to what we want(ed) to see on the display, that is, it contains rank, team name and highest score only.

That message, with the 'list:setArray' topic, is broadcasted over an mhub bus and received by display system, where it recognizes the 'setArray' bit and handles the message. This bit of code is here. There are a few more mhub topics that can be sent to the display system list module, documented here

Lastly, something that really needs to be improved is the lack of documentation of the mhub protocols in the mq-protocols repo where we currently only have a bit of spec for (the interoperability of) the clock

Better workings

As can be seen from the comments in the code, this is less than ideal. This way, fllscoring and display system are very tied together. Ideally, we'd want display system to send a message over the bus that contains all information it knows, so all rounds, and everything, without having to know who listens to it. And also without having to know how to format it for a specific recipient

This allows for any system to listen to these messages For example, aside from displaying it on a display, you could publish it to a website, send facebook updates, send sms text messages to the teams, or launch fireworks writing the top team name in the air.

On the side of display system, we'd want the list:setArray topic to receive a generic table, as it is now (it expects an array of arrays for lines and a separate array for the header). If the list module were tailored to receive only messages from fllscoring, it would not be very versatile.

This allows for any system to send messages to a display. Not only displaying team results, but maybe also a schedule (from a scheduling application), or a list of lost-and-found items or a timetable listing future firework deployments.

Relay

This versatility comes with a price, as both systems broadcast and receive in their own language, we need something in between to make the translation. Basically we want an adapter that has plugs for both systems. This allows us to create a predefined set of adapters that you can use to connect any two systems together over mhub. We have some docs here

TODO

There is a lot of work to do in this area, we could really use some help there

alanggreen commented 7 years ago

This is what the current FIRST LEGO League scoring system display looks like image

Let's leave the top third out of the discussion for now, as there is too much space for logos and the like, and not enough space for scores.

The Goal

We want columns for Ranking, Team number, Team Name, Highest Score, Round 1 score, etc

So how to achieve that using the mhub-relay? I'm thinking of something along these lines

fllscoring publishes a score to mhub when the scorekeeper presses the Publish button. The meta-data included with the score would be the team number and the round (and possibly a practice/scoring indication).

The mhub-relay (acting as a transformer/aggregator) subscribes to this topic, and collects the data as it comes in. It might even have an in-memory database for that. The mhub-relay then publishes the aggregated data for the team back to mhub, where it is picked up by flldisplay and handled by a new table module.

Problems

There are a number of things missing here.

  1. We need to pull in the team name from somewhere
  2. How do we keep the list sorted by ranking?
  3. How does the scrolling work? (there will almost always be more teams than rows on the screen)
  4. How do we handle recovery from a crash? If the system restarts during the competition, the scores displayed until the crash must be shown again.
  5. Can we avoid sending the all the information for a team every time it has one new score?

    Disadvantages

    One of the disadvantages of this idea is that the same information (team scores) is kept in more than one place.

The Labview scoring program has a problem where, in certain situations, scores entered are shown on the Display module, but not in the ranking table that the scorekeeper/head referees sees (happens when scores are entered by tablets in a hostile WiFi environment AND the server PC is under-powered).

Other Ideas

rikkertkoppes commented 7 years ago

The way I see it is the following

Fllscoring is responsible to publish a message that includes all info that can possibly be needed (and maybe more). This would include ranking, and team names and the actual sort order.

Mhub can be used for persistence of messages in case of a crash, see https://github.com/poelstra/mhub/blob/master/README.md#node-types

Mhub relay would be responsible to transform the message to something display system can understand. I would vote to keep a repository of useful relay scripts somewhere (with a node red approach, these would be transformation blocks that can be easily inserted in the flow)

Display system is responsible for displaying, paging and scrolling, because it is the only component that can possibly know how large the screen is. The list module already supports paging.

Lastly, I don't see harm in reposting the entire ranking when one score changes. This makes sure the list is always consistent. Mhub relay may filter out team info that is not needed.

Have a look ar what mhub can do for you wrt crash recovery.

Lastly, this is my current view. It may not be correct and change based on your input. Let me know what you think

On Fri, 30 Jun 2017, 23:18 Alan Green, notifications@github.com wrote:

This is what the current FIRST LEGO League scoring system display looks like [image: image] https://user-images.githubusercontent.com/6757517/27753051-b14c3134-5dec-11e7-9872-6aa534f8de23.png

Let's leave the top third out of the discussion for now, as there is too much space for logos and the like, and not enough space for scores. The Goal

We want columns for Ranking, Team number, Team Name, Highest Score, Round 1 score, etc

So how to achieve that using the mhub-relay? I'm thinking of something along these lines

fllscoring publishes a score to mhub when the scorekeeper presses the Publish button. The meta-data included with the score would be the team number and the round (and possibly a practice/scoring indication).

The mhub-relay (acting as a transformer/aggregator) subscribes to this topic, and collects the data as it comes in. It might even have an in-memory database for that. The mhub-relay then publishes the aggregated data for the team back to mhub, where it is picked up by flldisplay and handled by a new table module. Problems

There are a number of things missing here.

  1. We need to pull in the team name from somewhere
  2. How do we keep the list sorted by ranking?
  3. How does the scrolling work? (there will almost always be more teams than rows on the screen)
  4. How do we handle recovery from a crash? If the system restarts during the competition, the scores displayed until the crash must be shown again.
  5. Can we avoid sending the all the information for a team every time it has one new score?

Disadvantages

One of the disadvantages of this idea is that the same information (team scores) is kept in more than one place.

  • fllscoring - currently needs to be there so that the scores can be exported to csv
  • mhub-relay - to be able send a whole row to the displaySystem table module
  • displaySystem - has the whole table in memory.

The Labview scoring program has a problem where, in certain situations, scores entered are shown on the Display module, but not in the ranking table that the scorekeeper/head referees sees (happens when scores are entered by tablets in a hostile WiFi environment AND the server PC is under-powered). Other Ideas

  • Other ideas that come to mind include enhancing the displaySystem table module so that it gets an index (i.e. the team number) and a column (or maybe more than one column). That way the aggregator publishes just the new score with an indication of which round (i.e. column) it belongs to. The additional column would be the "highest score" column - the aggregator would add that information if the highest score changes.
  • If all the data is saved by the aggregator then it could publish it on request (i.e. when the user requires export to csv.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/FirstLegoLeague/displaySystem/issues/31#issuecomment-312375092, or mute the thread https://github.com/notifications/unsubscribe-auth/AASe5VrFmNPz-aTYb1YJmcn1KGlea9Tkks5sJWYjgaJpZM4OEYaT .

poelstra commented 7 years ago

I agree with Rikkert's approach. In fact, this was largely already what we did in the past: fllscoring publishes full list of scores (all rounds, all teams, already ordered by rank, etc).

Then mhub-relay or node-red filters that as needed, e.g. in our case only show highest score per round and omitting teams that didn't play yet.

Posting the full set of data every time is no issue at all, we're talking a few kilobytes at most.

The advantage is that the complex logic of determining rank (e.g. handling teams that were disqualified, shared rank in case of equal scores etc) is all handled in one place (fllscoring app) and can never be out-of-sync.

Mhub has a node type that persists certain topics, and has the additional advantage that anyone subscribing to these topics will immediately get the last message posted to it. This way you don't have to wait for a new round of scores to be published in order to fill a newly connected display.

The disadvantage of this node type is that you need to configure the topics to perdist on the mhub server. I thought about adding a node type that persists messages when e.g. persist: true is given in the headers.

You'll find a comment in the fllscoring app where it publishes the scores today, that that piece of code is a bit of a hack/shortcut, because we already do 'our' style filtering there (I think we didn't have mhub-relay at the time or something).

Rikkert Koppes notifications@github.com schreef op 1 juli 2017 10:59:26 CEST:

The way I see it is the following

Fllscoring is responsible to publish a message that includes all info that can possibly be needed (and maybe more). This would include ranking, and team names and the actual sort order.

Mhub can be used for persistence of messages in case of a crash, see https://github.com/poelstra/mhub/blob/master/README.md#node-types

Mhub relay would be responsible to transform the message to something display system can understand. I would vote to keep a repository of useful relay scripts somewhere (with a node red approach, these would be transformation blocks that can be easily inserted in the flow)

Display system is responsible for displaying, paging and scrolling, because it is the only component that can possibly know how large the screen is. The list module already supports paging.

Lastly, I don't see harm in reposting the entire ranking when one score changes. This makes sure the list is always consistent. Mhub relay may filter out team info that is not needed.

Have a look ar what mhub can do for you wrt crash recovery.

Lastly, this is my current view. It may not be correct and change based on your input. Let me know what you think

On Fri, 30 Jun 2017, 23:18 Alan Green, notifications@github.com wrote:

This is what the current FIRST LEGO League scoring system display looks like [image: image]

https://user-images.githubusercontent.com/6757517/27753051-b14c3134-5dec-11e7-9872-6aa534f8de23.png

Let's leave the top third out of the discussion for now, as there is too much space for logos and the like, and not enough space for scores. The Goal

We want columns for Ranking, Team number, Team Name, Highest Score, Round 1 score, etc

So how to achieve that using the mhub-relay? I'm thinking of something along these lines

fllscoring publishes a score to mhub when the scorekeeper presses the Publish button. The meta-data included with the score would be the team number and the round (and possibly a practice/scoring indication).

The mhub-relay (acting as a transformer/aggregator) subscribes to this topic, and collects the data as it comes in. It might even have an in-memory database for that. The mhub-relay then publishes the aggregated data for the team back to mhub, where it is picked up by flldisplay and handled by a new table module. Problems

There are a number of things missing here.

  1. We need to pull in the team name from somewhere
  2. How do we keep the list sorted by ranking?
  3. How does the scrolling work? (there will almost always be more teams than rows on the screen)
  4. How do we handle recovery from a crash? If the system restarts during the competition, the scores displayed until the crash must be shown again.
  5. Can we avoid sending the all the information for a team every time it has one new score?

Disadvantages

One of the disadvantages of this idea is that the same information (team scores) is kept in more than one place.

  • fllscoring - currently needs to be there so that the scores can be exported to csv
  • mhub-relay - to be able send a whole row to the displaySystem table module
  • displaySystem - has the whole table in memory.

The Labview scoring program has a problem where, in certain situations, scores entered are shown on the Display module, but not in the ranking table that the scorekeeper/head referees sees (happens when scores are entered by tablets in a hostile WiFi environment AND the server PC is under-powered). Other Ideas

  • Other ideas that come to mind include enhancing the displaySystem table module so that it gets an index (i.e. the team number) and a column (or maybe more than one column). That way the aggregator publishes just the new score with an indication of which round (i.e. column) it belongs to. The additional column would be the "highest score" column - the aggregator would add that information if the highest score changes.
  • If all the data is saved by the aggregator then it could publish it on request (i.e. when the user requires export to csv.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub

https://github.com/FirstLegoLeague/displaySystem/issues/31#issuecomment-312375092, or mute the thread

https://github.com/notifications/unsubscribe-auth/AASe5VrFmNPz-aTYb1YJmcn1KGlea9Tkks5sJWYjgaJpZM4OEYaT .

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/FirstLegoLeague/displaySystem/issues/31#issuecomment-312420401

alanggreen commented 7 years ago

Not sure I understand. You say

In fact, this was largely already what we did in the past: fllscoring publishes full list of scores (all rounds, all teams, already ordered by rank, etc).

When we ran the pilot, we saw that only the highest scores are shown, and the team name needs to be entered into the displaySystem control window. Did it get changed at some stage?

poelstra commented 7 years ago

I was referring to this piece of code: https://github.com/FirstLegoLeague/fllscoring/blob/master/src/js/views/ranking.js#L30

As you can see in the comment there, the intention was to make it generic (i.e. publish the full stage object to scores:ranking or or 'scores/ranking/` or whatever), but we took a rather dirty shortcut at the time, to publish a message specifically targetted directly at the displaySystem.

From the code, it's clear that the list only includes the highest score, but it should also include the team name, so it would be really strange you'd have to enter that by hand on displaySystem...

Now, it can be something is wrong on the fllscoring side (and the team name isn't actually published in the message), or displaySystem is somehow not showing it.

A simple way to see what happens, is to use mhub-client -l -o json (optionally with -s <mhub_server_address>). That will show you all messages going across the bus. The -o json makes sure to show the full message, without 'truncating' embedded objects.

poelstra commented 7 years ago

(Note, I edited my previous post to include -o json to the mhub-client commandline...)

When clicking the "Broadcast" button on the "Voorrondes" stage, on this ranking screen: image

I get:

martin@laptop:~/src/fll/fllscoring (master)$ mhub-client -l -o json
{"topic":"list:setArray","data":{"data":[[1,"Jajaja",653],[2,"Dik&lelijk",255],[3,"Fleppie",180]],"header":"Voorrondes"},"headers":{}}

So in my case it does include the team name as expected.

alanggreen commented 7 years ago

HI Martin

I'm not at home now so I can't look at the code, but what I mean was to see the ranking data on the display. Did you mean that it's available in the scoring but that the mhub-relay must be used to see it on display?

Alan

On Mon, Jul 3, 2017 at 5:08 PM, Martin Poelstra notifications@github.com wrote:

(Note, I edited my previous post to include -o json to the mhub-client commandline...)

When clicking the "Broadcast" button on the "Voorrondes" stage, on this ranking screen: [image: image] https://user-images.githubusercontent.com/1025628/27795988-95225d44-6008-11e7-9ccf-22fca70c717d.png

I get:

martin@laptop:~/src/fll/fllscoring (master)$ mhub-client -l -o json {"topic":"list:setArray","data":{"data":[[1,"Jajaja",653],[2,"Dik&lelijk",255],[3,"Fleppie",180]],"header":"Voorrondes"},"headers":{}}

So in my case it does include the team name as expected.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FirstLegoLeague/displaySystem/issues/31#issuecomment-312655145, or mute the thread https://github.com/notifications/unsubscribe-auth/AGccjeqhsgu_qShZKO1p9fACbk9L96kPks5sKPXMgaJpZM4OEYaT .

poelstra commented 7 years ago

This is what fllscoring does for ranking:

So, in an ideal situation, when you click the Broadcast button, fllscoring would send out this full set of data to mhub. And indeed, you would have something like mhub-relay or node-red translate that generic message to something else, e.g. a list that only shows the highest scores (in our case), or a list that includes all scores (in your case). It could even convert it into an HTML page and post it to a website.

Unfortunately, right now, the Broadcast button behaves differently: it basically does what mhub-relay would do for you: i.e. it already filters that nice generic data down to a 'dumb' array of ranks with only highest score (it does include the team name, though), and directly posts it to a topic that is very specific the the displaySystem.

The only advantage of the way it is today, is that we 'only' need fllscoring + mhub + displaySystem to display scores on an external display (i.e. no mhub-relay config required).

The downside is of course that fllscoring is now directly coupled to displaySystem, and you can't do any other things with the rankings.

In fact, it would probably be rather trivial to change the Broadcaster code to broadcast the full ranking data, but it would require more setup (and documentation of that) to then include mhub-relay (or node-red).

Hopefully that's not an issue anymore though, if the docker/vm stuff is up and running...

alanggreen commented 7 years ago

Thanks Martin, you've explained it very clearly now. Idan and I discussed how we should proceed, and (since he's doing most of the programming work) you've saved him quite a bit of effort. Our intention is to go in the direction of the "ideal situation" you describe.

On Mon, Jul 3, 2017 at 7:23 PM, Martin Poelstra notifications@github.com wrote:

This is what fllscoring does for ranking:

  • fllscoring has a list of teams, all entered scores, and the logic to compute a ranking with all its complexities
  • fllscoring keeps that ranking in a 'general' form, per stage (e.g. Qualifying rounds, Semi-Final, Final, etc.)
  • the data per stage includes an ordered list (by rank) of: rank number, team info, highest score and scores for each round that team has played
  • the team info is an object, that contains team number, name, etc.
  • this info is used to display the ranking screen as shown in my earlier comment, but could also be used to post on mhub

So, in an ideal situation, when you click the Broadcast button, fllscoring would send out this full set of data to mhub. And indeed, you would have something like mhub-relay or node-red translate that generic message to something else, e.g. a list that only shows the highest scores (in our case), or a list that includes all scores (in your case). It could even convert it into an HTML page and post it to a website.

Unfortunately, right now, the Broadcast button behaves differently: it basically does what mhub-relay would do for you: i.e. it already filters that nice generic data down to a 'dumb' array of ranks with only highest score (it does include the team name, though), and directly posts it to a topic that is very specific the the displaySystem.

The only advantage of the way it is today, is that we 'only' need fllscoring + mhub + displaySystem to display scores on an external display (i.e. no mhub-relay config required).

The downside is of course that fllscoring is now directly coupled to displaySystem, and you can't do any other things with the rankings.

In fact, it would probably be rather trivial to change the Broadcaster code to broadcast the full ranking data, but it would require more setup (and documentation of that) to then include mhub-relay (or node-red).

Hopefully that's not an issue anymore though, if the docker/vm stuff is up and running...

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FirstLegoLeague/displaySystem/issues/31#issuecomment-312687503, or mute the thread https://github.com/notifications/unsubscribe-auth/AGccjTiZib53lMgvK8veWpQZWf6upGofks5sKRVxgaJpZM4OEYaT .

poelstra commented 7 years ago

Had some time to fiddle with the code a bit.

It appeared to be a little bit more complicated to get a clean output directly from the scoreboard, because:

This leads to a JSON with a lot of duplicate stuff and ugly Angular-injected internal stuff.

So, here's what I did instead (at https://github.com/FirstLegoLeague/fllscoring/blob/master/src/js/views/ranking.js#L30):

            $scope.broadcastRanking = function(stage) {
                ... (left the 'old' code intact for now)

                // Send generic ranking info on bus, but filter it down a bit
                // to not include Angular-injected stuff (yuk), but also omit
                // the full scoresheets and their validation results etc.
                // Having it spelled out exactly also helps to have some kind of
                // 'interface' defined to the outside world.
                var rankingMessage = {
                    stage: {
                        id: stage.id,
                        name: stage.name,
                        rounds: stage.rounds,
                    },
                    ranking: $scope.scoreboard[stage.id].map(function (item) {
                        return {
                            rank: item.rank, // Note: there can be multiple rows with same (shared) rank!
                            team: {
                                number: item.team.number,
                                name: item.team.name,
                            },
                            scores: item.scores,
                            highest: item.highest,
                        };
                    }),
                };
                $message.send('scores:ranking', rankingMessage);
            };

This yields the following example message in mhub-client:

{"topic":"scores:ranking","data":{"stage":{"id":"qualifying","name":"Voorrondes","rounds":3},"ranking":[{"rank":1,"team":{"number":10,"name":"Jajaja"},"scores":[559,653,110],"highest":653},{"rank":2,"team":{"number":1,"name":"Dik&lelijk"},"scores":[255,127,50],"highest":255},{"rank":3,"team":{"number":2,"name":"Fleppie"},"scores":[null,null,180],"highest":180}]},"headers":{}}

Just the data-part of it formatted for convenience:

{
    "stage": {
        "id": "qualifying",
        "name": "Voorrondes",
        "rounds": 3
    },
    "ranking": [
        {
            "rank": 1,
            "team": {
                "number": 10,
                "name": "Jajaja"
            },
            "scores": [
                559,
                653,
                110
            ],
            "highest": 653
        },
        {
            "rank": 2,
            "team": {
                "number": 1,
                "name": "Dik&lelijk"
            },
            "scores": [
                255,
                127,
                50
            ],
            "highest": 255
        },
        {
            "rank": 3,
            "team": {
                "number": 2,
                "name": "Fleppie"
            },
            "scores": [
                null,
                null,
                180
            ],
            "highest": 180
        }
    ]
}
idanstark42 commented 7 years ago

That looks great! Generic and simple. I'm currently working on the Table module in the displaySystem, so can you push it into the repository? Many thanks

rikkertkoppes commented 7 years ago

That would be a great addition to scoring I guess. Could we move the discussion to there?

If this is committed to master, we also need a default relay script and some docs to get the current behaviour back. People should be able to get stuff working easily, so relay scripts to transform the generic scoring data to something the list / new table module can handle would be absolutely needed here.

poelstra commented 7 years ago

Made new issue, closing this one.