Author |
Topic: Card graphics not sticking (Read 200 times) |
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #48 on: May 26th, 2016, 4:37pm » |
|
This probably belongs in the Novice category on the LB board, but since it's already been suggested here to hide the window with "stylebits #main, 0, _WS_VISIBLE, 0, 0" and then "#main "show"" after loading, I have a related question.
If the "hidden" window is loaded at the start of the program, it can be made visible by manually issuing a "show" command when desired. That way the window appears to open immediately, which is highly desirable. QUESTION: How do you hide the window again once opened? The program crashes if issued a "#main "hide"" instruction, and simply closing the window takes me back to where I started. Perhaps relocating the window off-screen will work.
There are several windows (not all involving graphics) that can be toggled open or closed by the user, but I don't have enough experience to know how best to go about it. ANOTHER QUESTION: Is opening and closing the "normal" way of handling multiple windows or should they be loaded at the program's start and made visible or invisible as required? I hope that makes sense, and thanks to everyone for your patience.
Tsh73: Thanks to your help, a lot of unnecessary code has been eliminated.
|
|
Logged
|
|
|
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #49 on: May 28th, 2016, 4:58pm » |
|
Richard: Thanks for your explanations. Not knowing any better, I initially designed the program to open selected windows on demand. I'm now changing that to launch all windows along with the rest of the program – they're just hidden until needed. That eliminates any lag in populating the displays and tremendously simplifies the coding. (I often have a tendency to overcomplicate things! ) So far, it looks like LBB might lend itself to running the program after all, but there're many more changes to make first.
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Card graphics not sticking
« Reply #50 on: May 28th, 2016, 10:58pm » |
|
on May 28th, 2016, 4:58pm, Turtleman wrote:| Not knowing any better, I initially designed the program to open selected windows on demand. |
|
In the great majority of programs, it will make no noticeable difference which way you do it. Creating a window usually happens virtually 'instantaneously'; even in your own program it's not the window creation that takes a significant time but the window initialisation, i.e. filling all those graphicboxes and grid cells with a background color and text.
As I think I said previously, I've only once before encountered a program in which the window creation/initialisation took sufficiently longer in LBB than in LB to be important, so it's very unusual. On that occasion I could improve things somewhat, but not match the performance of LB.
I've suggested ways in which you could improve the performance of your program. To speed up window creation you could replace the horizontal set of column labels and the vertical set of row labels with single graphicboxes rather than many individual ones. To speed up the window initialisation you could concatenate the commands into one long string, as suggested in the Wiki article to which I linked.
But you never responded to either suggestion, which is why I concluded you weren't really motivated to get it working well in LBB. The code below incorporates both mods:
Code: 'Graphic boxes demo - May 23, 2016
nomainwin
start = time$("ms")
GridWidth = 40
GridHeight = 25
GridRows = 20
GridColumns = 10
MaxColors = 5
dim counters(GridColumns, GridRows), colors$(MaxColors-1)
restore [FieldValues]
for row = 1 to GridRows
for column = 1 to GridColumns
read n
counters(column, row) = n
next
next
restore [FieldColors]
for i = 0 to MaxColors-1
read color$
colors$(i) = color$
next
BoxWidth = GridColumns * GridWidth
BoxHeight = GridRows * GridHeight
WindowWidth = BoxWidth + 100
WindowHeight = BoxHeight + 100
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
graphicbox #main.gb2, 50, 10, BoxWidth, GridHeight
y = 15
graphicbox #main.gb1, 5, GridHeight + y, GridWidth, BoxHeight
graphicbox #main.gb, 50, 40, BoxWidth, BoxHeight
stylebits #main, 0, _WS_VISIBLE, 0, 0
open "Grid" for window as #main
#main, "trapclose [quit.main]"
#main.gb "down; font arial 10; size 1; color black"
#main.gb "when leftButtonUp [IncreaseCounter]"
#main.gb "when leftButtonDouble [IncreaseCounter]"
gosub [InitGrid]
gosub [title]
#main "show"
finish = time$("ms")
print finish-start
wait
[quit.main]
Close #main
END
[IncreaseCounter]
row = int( MouseY / GridHeight) + 1
column = int( MouseX / GridWidth) + 1
counters(column, row) = counters(column, row) + 1
if counters(column, row) > (MaxColors - 1) then counters(column, row) = 0
#main.gb "delsegment GridUpdate"
gosub [DrawField]
#main.gb "flush GridUpdate"
wait
[InitGrid]
for row = 1 to GridRows
for column = 1 to GridColumns
gosub [DrawField]
next
next
#main.gb "flush InitGrid"
return
[DrawField]
gb$ = "color black; backcolor "; colors$(counters(column, row)); ";"
gb$ = gb$ + "place "; (column-1)*GridWidth; " "; (row-1)*GridHeight; ";"
gb$ = gb$ + "boxfilled "; column*GridWidth; " "; row*GridHeight; ";"
gb$ = gb$ + "place "; (column-.6)*GridWidth; " "; (row-.4)*GridHeight; ";"
if instr(lower$(colors$(counters(column, row))), "dark") > 0 then gb$ = gb$ + "color white;"
gb$ = gb$ + "\"; counters(column, row)
#main.gb gb$
return
[FieldValues]
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
[FieldColors]
data "red" '0
data "darkgreen"'1
data "cyan" '2
data "yellow" '3
data "pink" '4
[title]
#main "font arial 12 bold"
#main "font arial 12 bold"
#main.gb2 "down; color black; backcolor yellow"
for i = 22 to 31
gb2$ = "place ";(i-22) * GridWidth; " 0;"
gb2$ = gb2$ + "boxfilled ";(i-21) * GridWidth; " "; GridHeight-2; ";"
gb2$ = gb2$ + "place ";(i-21.6) * GridWidth; " 17;\";i-21
#main.gb2 gb2$
next
#main.gb2 "flush"
'REM VERTICAL COLUMN LABELS ----------------------------------------------------------------------
#main.gb1 "down; color black; backcolor white"
for i = 1 to 20
gb1$ = "place 0 ";i * GridHeight; ";"
gb1$ = gb1$ + "boxfilled ";GridWidth-2; " "; (i-1) * GridHeight; ";"
gb1$ = gb1$ + "place 14 ";(i-0.4) * GridHeight; ";\"; i
#main.gb1 gb1$
next
#main.gb1 "flush"
return Richard.
|
|
Logged
|
|
|
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #51 on: May 29th, 2016, 11:01am » |
|
Thanks again Richard. You've certainly demonstrated how the amount of code can be greatly reduced and initialization speeded up. The example I posted was just that, an example when I was concerned about the apparent slower speed. My actual application has nearly twice as many graphicboxes and the horizontal and vertical labels have a mix of one to five numbers, letters, and commas.
Thanks to tsh73, the code has been simplified a lot, but your example is much more elegant and efficient. Now, if I can just figure out how to integrate the word$ command to populate the labels with whatever's in the msg$ lines. Meanwhile, I've changed the window to initialize upon loading the program and it now pops up instantly fully populated. Some of the other windows may be modified accordingly. Regardless of LB or LBB, having more efficient code is always desirable; I'm just way too inexperienced to get there in one step.
I'm sorry I didn't respond to your previous post sooner, but even I have to sometimes do other things that take me away from the computer. I am, however, highly motivated to get my program working well in LBB! It's identifying many areas in the code that can be improved, and making executables and changing icons (among other things) are way easier than in LB. If it eventually results in a speed increase won't be known for a while. Back later.
UPDATE: Son-of-gun, adding word$ and msg was a very simple change and it's a zillion times faster and simpler than my initial example. It's embarrassing! Now to modify my "real" program. I wonder if a centering command will work here or if I have to give exceptions for the place command on some lines.
|
| « Last Edit: May 29th, 2016, 11:57am by Turtleman » |
Logged
|
|
|
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #52 on: May 29th, 2016, 12:38pm » |
|
Another PS: Here's the small modification using Word$ and msg to permit characters to be used for the vertical column labels. That was easy. However, centering the labels within the column is so far eluding me. I've "played" with stylebits #main.gb, _ES_CENTER,0,0,0 with no success and guess there might be something to replace the "place 14 ";(i-0.4) * GridHeight instruction, but what?
Code:
'REM VERTICAL COLUMN LABELS ----------------------------------------------------------------------
msg$="10 A,B 3 4 5 6 7 8 C D E,F 14 15 10,10 11 G,G 17 18 19 20"
#main.gb1 "down; color black; backcolor white"
for i = 1 to 20
gb1$ = "place 0 ";i * GridHeight; ";"
gb1$ = gb1$ + "boxfilled ";GridWidth-2; " "; (i-1) * GridHeight; ";"
gb1$ = gb1$ + "font arial bold 10; place 2 ";(i-0.3) * GridHeight; ";\"; word$(msg$,i)
#main.gb1 gb1$
next
#main.gb1 "flush"
return
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Card graphics not sticking
« Reply #53 on: May 29th, 2016, 2:22pm » |
|
on May 29th, 2016, 12:38pm, Turtleman wrote:| I've "played" with stylebits #main.gb, _ES_CENTER,0,0,0 with no success |
|
As the _ES_ tells you, that's an Edit Style bit that is specific to a Texteditor or Textbox; it will have no effect on a Graphicbox.
Quote:| and guess there might be something to replace the "place 14 ";(i-0.4) * GridHeight instruction, but what? |
|
Find the width of the string in pixels, subtract it from the width of the box and halve the resulting value. That tells you at what horizontal coordinate within the box you need to draw the text so it will be centered. Easy, but it will make the code even slower!
Is the requirement to center the text just for the labels, or for the boxes in the main grid? I'm thinking that if it's only the labels maybe you would be better to use TEXTEDITOR controls rather than GRAPHICBOXes because then you could use the _ES_CENTER style bit. LB 4.5.0 and LBB provide control over the foreground and background color of texteditor controls.
Richard.
|
|
Logged
|
|
|
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #54 on: May 29th, 2016, 2:35pm » |
|
I probably shouldn't have mentioned the stylebits centering, as I realized after the fact that it wouldn't work in the graphicbox. Yes, the centering is only for the labels, and only for cosmetic reasons. In my original messy code, the individual place parameters could be adjusted to center labels of 1-5 characters. Obviously, a single graphicsbox is far superior from the standpoints of simplification and speed. Right offhand, I don't have a clue how to change over to substituting texeditor controls, but will definitely put it on the to-do list.
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Card graphics not sticking
« Reply #55 on: May 29th, 2016, 4:02pm » |
|
on May 29th, 2016, 2:35pm, Turtleman wrote:| I don't have a clue how to change over to substituting texeditor controls |
|
Listed below for comparison purposes. It is slower (because we're back to individual controls for each label) and compatibility with LB must be abandoned, but the labels are centered with no extra effort.
Code: 'nomainwin
start = time$("ms")
GridWidth = 40
GridHeight = 25
GridRows = 20
GridColumns = 10
MaxColors = 5
dim counters(GridColumns, GridRows), colors$(MaxColors-1)
restore [FieldValues]
for row = 1 to GridRows
for column = 1 to GridColumns
read n
counters(column, row) = n
next
next
restore [FieldColors]
for i = 0 to MaxColors-1
read color$
colors$(i) = color$
next
BoxWidth = GridColumns * GridWidth
BoxHeight = GridRows * GridHeight
WindowWidth = BoxWidth + 100
WindowHeight = BoxHeight + 100
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
' Column label boxes:
for c = 1 to GridColumns
stylebits #main.te, _ES_CENTER or _ES_READONLY, _
_WS_HSCROLL or _WS_VSCROLL or _ES_MULTILINE, 0, 0
texteditor #main.te, c * GridWidth + 10, 10, GridWidth, GridHeight
maphandle #main.te, "#main.c";c
next
' Row label boxes:
for r = 1 to GridRows
stylebits #main.te, _ES_CENTER or _ES_READONLY, _
_WS_HSCROLL or _WS_VSCROLL or _ES_MULTILINE, 0, 0
texteditor #main.te, 5, r * GridHeight + 15, GridWidth, GridHeight
maphandle #main.te, "#main.r";r
next
graphicbox #main.gb, 50, 40, BoxWidth, BoxHeight
stylebits #main, 0, _WS_VISIBLE, 0, 0
open "Grid" for window as #main
hmain = hwnd(#main)
calldll #user32, "SetMenu", hmain as ulong, 0 as long, r as long
#main, "trapclose [quit.main]"
#main.gb "down; font arial 10; size 1; color black"
#main.gb "when leftButtonUp [IncreaseCounter]"
#main.gb "when leftButtonDouble [IncreaseCounter]"
#main.gb "setfocus"
gosub [InitGrid]
gosub [title]
#main "show"
finish = time$("ms")
print finish-start
wait
[quit.main]
Close #main
END
[IncreaseCounter]
row = int( MouseY / GridHeight) + 1
column = int( MouseX / GridWidth) + 1
counters(column, row) = counters(column, row) + 1
if counters(column, row) > (MaxColors - 1) then counters(column, row) = 0
#main.gb "delsegment GridUpdate"
gosub [DrawField]
#main.gb "flush GridUpdate"
wait
[InitGrid]
for row = 1 to GridRows
for column = 1 to GridColumns
gosub [DrawField]
next
next
#main.gb "flush InitGrid"
return
[DrawField]
gb$ = "color black; backcolor "; colors$(counters(column, row)); ";"
gb$ = gb$ + "place "; (column-1)*GridWidth; " "; (row-1)*GridHeight; ";"
gb$ = gb$ + "boxfilled "; column*GridWidth; " "; row*GridHeight; ";"
gb$ = gb$ + "place "; (column-.6)*GridWidth; " "; (row-.4)*GridHeight; ";"
if instr(lower$(colors$(counters(column, row))), "dark") > 0 then gb$ = gb$ + "color white;"
gb$ = gb$ + "\"; counters(column, row)
#main.gb gb$
return
[FieldValues]
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
data 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
[FieldColors]
data "red" '0
data "darkgreen"'1
data "cyan" '2
data "yellow" '3
data "pink" '4
[title]
#main "font arial 10 bold"
' column labels:
for c = 1 to GridColumns
handle$ = "#main.c";c
#handle$ "!backcolor yellow"
#handle$ str$(c)
next
' row labels:
lbl$ = "one A,B 3 4 5 6 7 8 C D E,F 14 15 10 11 G,H 17 18 19 20"
for r = 1 to GridRows
handle$ = "#main.r";r
#handle$ "!backcolor lightgray"
#handle$ word$(lbl$,r)
next
return I'm sorely tempted to replace those obsolete GOSUBs with CALLs, but have resisted the temptation so far!
Richard.
|
|
Logged
|
|
|
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #56 on: May 29th, 2016, 4:16pm » |
|
WOW - it probably would have taken me weeks or longer to do that if I could at all! I'm involved in something else at the moment and will need to spend some time trying to figure out why the latest code isn't compatible with LB. At this point, I'd still like to maintain compatibility, if for no other reason than to be able to compare performance later on. How big a job is it to modify centering code to be compatible?
Yes, I've heard that gosub's are almost as antiquated and nearly as verboten as goto's, but somehow find them easier to use than calls. I'm not sure I remember why calls are preferred, but gosubs are probably a nasty habit I picked up when I first started. Thanks a bunch!
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Card graphics not sticking
« Reply #57 on: May 29th, 2016, 4:39pm » |
|
on May 29th, 2016, 4:16pm, Turtleman wrote:| How big a job is it to modify centering code to be compatible? |
|
It's doable if you are prepared to lose the colored background to the labels. The problem with the !backcolor command is that only texteditor controls provide it, not textboxes, and in LB the _ES_CENTER stylebit only works with textboxes!
But you're on your own for making the changes; I draw the line at modifying programs to make them compatible with LB! Indeed I'm far more likely to make them incompatible with LB (if only accidentally).
Ideally I'd prefer not even to discuss on this forum how one might maintain compatibility with LB, because it's fundamentally contrary to what LBB is all about.
Quote:| Yes, I've heard that gosub's are almost as antiquated and nearly as verboten as goto's |
|
GOSUBs are worse than GOTOs! Getting rid of GOTOs, whilst worthwhile, can sometimes be tricky and require significant code changes. Replacing GOSUBs with CALLs is substantially trivial and GOSUB has no redeeming features at all.
Richard.
|
|
|
|
Turtleman
New Member
member is offline


Gender: 
Posts: 29
|
 |
Re: Card graphics not sticking
« Reply #58 on: May 29th, 2016, 4:46pm » |
|
Thanks - I understand completely. I'll try to stay more LBB-specific here, while most of my questions are generic programming related, anyway. I'll look into the reasons for using calls in place of gosubs and possibly become a convert.
Ron (Probably no need to remain as anonymous!)
|
|
Logged
|
|
|
|
tsh73
Full Member
member is offline


Gender: 
Posts: 210
|
 |
Re: Card graphics not sticking
« Reply #59 on: May 29th, 2016, 8:12pm » |
|
Quote:| and GOSUB has no redeeming features at all. |
|
It is a quick way to move piece of code away. Moving piece of code in a sub makes one to think of dependant varibles. (and I missed some more then once, making program work wrong) While in GOSUB one had access for all variables (kind of global)
|
| « Last Edit: May 29th, 2016, 8:13pm by tsh73 » |
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Card graphics not sticking
« Reply #60 on: May 29th, 2016, 10:37pm » |
|
on May 29th, 2016, 8:12pm, tsh73 wrote:| It is a quick way to move piece of code away. |
|
I can think of only two reasons why you would ever want to "move a piece of code away". The first is when the same functionality is duplicated in two (or more) places in your program, so it is more efficient to create a 'shared' subroutine that can be called from both places. The second is when a section of code performs some relatively complex self-contained operation, which would make the program harder to read and understand if it is coded 'inline'.
In the first case it is important that the 'shared' subroutine can be called from multiple places without imposing artificial constraints on the calling code. For example it may make no sense for the two or more different places in the program to use the same variable names for the subroutine's inputs and outputs.
In the second case it is important that the calling program can be read and understood in isolation, without the detailed implementation of the subroutine being known. In particular the subroutine must not have unwanted 'side effects' such as modifying the values of variables that the calling code may be using.
Crucially, in both cases only a SUB (or a FUNCTION) meets these requirements. The inputs and outputs need not have the same variable names in the different places from which it is called, and any 'temporary' variables used within the subroutine are independent of those outside.
So my firm opinion is that GOSUB should never ever be used in a program written today. The sole purpose of GOSUB is to make it easier to port a legacy program that was originally written for an ancient version of BASIC that had no other kind of subroutine.
Richard.
|
|
Logged
|
|
|
|
michael
New Member
member is offline


Posts: 28
|
 |
Re: Card graphics not sticking
« Reply #61 on: May 30th, 2016, 11:54pm » |
|
There is of course these commands too that allow you to do draws behind the scenes and show the draws at will.
These are built into LBB but have BBC Basic origin Just passing on what Richard sent me for off screen draws.
!*refresh off !*refresh on !*refresh
refresh off turns off the automatic refresh refresh refreshes the screen and shows the updated draws refresh on returns the automatic refresh to automatic.
We may as well offer this since it is a part of LBB.. (but is not a part of LB. So you wont be able to share such code in LB forums.
|
| « Last Edit: May 31st, 2016, 12:24am by michael » |
Logged
|
I make program generators and some utilities. Its my hobby
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Card graphics not sticking
« Reply #62 on: May 31st, 2016, 08:23am » |
|
on May 30th, 2016, 11:54pm, michael wrote:| There is of course these commands too that allow you to do draws behind the scenes and show the draws at will. |
|
Except that they only work when drawing graphics into the mainwin, so are not generally useful.
The easiest way to achieve 'flicker free' animated graphics in LBB (other than using sprites) is to use the normal JB/LB commands but to put them all - including the initial CLS - into a single string. That makes the best use of LBB's double-buffering:
Code: timer 40, [animate]
wait
[animate]
g$ = "cls;"
g$ += "<graphics commands>;"
g$ += "<more graphics commands>"
#g g$
wait By concatenating all the graphics commands for one 'frame' into a single string (sadly you can't do that if text is included) you avoid the possibility of Windows refreshing the screen when the graphics are only partly drawn, which is what results in flickering.
There may still be some 'tearing' (because the drawing isn't synchronized with the display refresh rate) but with care you can get good results this way.
Richard.
|
|
Logged
|
|
|
|
|