How can I add an input that is selected by a click

Yeah, I’ll admit that one was over the top :sweat_smile:


I’d probably add a dict:

SUIT_COLORS={"spades": "black", "clubs":"green", "diamonds":"blue", "hearts": "red" }

Then instead of

color = "black" if suit in ["spades", "clubs"] else "red"

it would be:

color = SUIT_COLORS[suit]

Thanks you all for all the help,

I’ve only been programing for less than 2 months in hours … and in this time I managed to pull out an app (I invite you to the web www.pokerutils.com … but still need a week of work in there to add users, so dont be hard on me please, but managed to create for poker) and some trading bots … without doing a single course of python, or programming … I know python is easier … but finding very interesting how much a do without knowing a *** … next step is to pull out a poker solver (thats vanguard for 8 years ago, doc papers etc) … give me some time and some answers.

thanks to all, you are really helpfull & sorry for asking too much, but If a baby doesn’t cry …

Is there any way I can select by 1 click, instead of n_clicks?

I whant to have various cards selected, first click, the first card, second click the second one … is this possible?

So you mean that you would like to show more than one card selected? If so, you could take a look at this example.

It shows how to add or remove sereral elements (in this case a card with a figure), but it would be similar.

yes, but need different outputs, to work on the cards (solve ev … numerical stuff) just whant to get different outputs for each card) … I need to have between 2 and 7 cards choosed … how can I make that possible?

hi, does this work for getting different outputs? or are they the same outputs?

What do you mean by “different”?

Please have a read here:

This sounds like what you are looking for

Simple Example with MATCH

Like ALL, MATCH will fire the callback when any of the component’s properties change. However, instead of passing all of the values into the callback, MATCH will pass just a single value into the callback. Instead of updating a single output, it will update the dynamic output that is “matched” with.

So, I turned this into a game:

  • Deal the cards
  • Play them from the active hand (outlined in red)

css

#player2 {
    position: absolute;
    top: 0px;
    display: flex;
    flex-direction: row;
    justify-content: center;
}

#player1 {
    position: absolute;
    left: 0px;
    top: 0px;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    justify-content: center;
}

#player3 {
    position: absolute;
    right: 0px;
    top: 0px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

#player0 {
    position: absolute;
    bottom: 0px;
    display: flex;
    flex-direction: row;
    justify-content: center;
}

#cards-played {
    display: flex;
    align-items: center;
    height: 100vh;
}

#cardActivity {
    position: absolute;
    top: 50%;
    left: 50%;
}

.disabled button.playingCard {
    cursor: not-allowed;
    pointer-events: none;
}

.active {
    border: 2pt solid red;
}

app.py

import random
from dash import Dash, html, Input, Output, ALL, ctx, State, dcc
from dash.exceptions import PreventUpdate
import dash_bootstrap_components as dbc
from dash_iconify import DashIconify

app = Dash(__name__, external_stylesheets=[dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP])

SUITS = ["spades", "clubs", "diamonds", "hearts"]
RANKS = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "jack", "queen", "king", "ace"]
players = ['player1', 'player2', 'player3', 'player0']
values = {'ace':14, 'king':13, 'queen':12, 'jack':11, '10':10,
          '9':9, '8':8, '7':7, '6':6, '5':5, '4':4, '3':3, '2':2,
          'spades':60, 'clubs':20, 'diamonds':30, 'hearts':40}



def create_deck(shuffle=False):
    """Create a  deck of 52 cards"""
    deck = [(s, r) for s in SUITS for r in RANKS]
    if shuffle:
        random.shuffle(deck)
    return deck

def shuffle_deck(deck):
    newDeck = []
    for suit in deck:
        for card in suit:
            newDeck.append(card)
    random.shuffle(newDeck)
    return newDeck

def sort_key(button):
    return values[button.id['index'].split('-')[0]] + values[str(button.id['index'].split('-')[1])]

def make_card(card):
    """format the card as a button"""
    suit, rank = card
    color = "black" if suit in ["spades", "clubs"] else "red"
    card_icon = DashIconify(
        icon=f"game-icons:card-{rank}-{suit}", color=color, height=45
    )
    return dbc.Button(
        [card_icon], color="white", className="playingCard", id={"index": f"{suit}-{rank}"}
    )


def make_deck(deck):
    """make card layout"""
    return [[make_card(c) for c in deck if s in c] for s in SUITS]

app.layout = dbc.Container(
    [
        html.Div([],id='cards-played'),
        dcc.Store(id='countChildren', data=0),
        html.Button('Deal Cards', n_clicks=0, id='cardActivity'),
        html.Div(id="card-selected"),
    ] + [html.Div(id=i) for i in players],
)


@app.callback(
    Output("cards-played", "children"),
    Input('cardActivity', 'n_clicks'),
    Input({"index": ALL}, "n_clicks"),
    State('cards-played','children'),
    prevent_initial_call=True,
)
def selected(n1, _, played):
    selected_card = ctx.triggered_id
    if selected_card:
        if selected_card == 'cardActivity':
            return []
    if ctx.triggered[0]['value']:
        selected_card = ctx.triggered_id.index
        suit, _, rank = selected_card.partition("-")
        color = "black" if suit in ["spades", "clubs"] else "red"
        if len(played) > 3:
            played = []
        return played + [DashIconify(icon=f"game-icons:card-{rank}-{suit}", color=color, height=60)]
    return played

@app.callback(
    [Output(i, 'children') for i in players],
    Input('cardActivity', 'n_clicks'),
    Input({"index": ALL}, "n_clicks"),
    [State(i, 'children') for i in players],
    prevent_initial_call=True,
)
def dealCards(n1, i, *args):
    selected_card = ctx.triggered_id
    if selected_card == 'cardActivity':
        deck = create_deck(True)
        madeDeck = make_deck(deck)
        shuffledDeck = shuffle_deck(madeDeck)
        dealt = [[]for i in players]
        x = 0
        for card in shuffledDeck:
            dealt[x].append(card)
            x += 1
            if x > 3:
                x = 0
        for hand in dealt:
            hand = hand.sort(key=sort_key)
    else:
        dealt = args
        for hand in dealt:
            for card in hand:
                if card['props']['id'] == selected_card:
                    hand.remove(card)
    return dealt

@app.callback(
    [Output(i, 'className') for i in players],
    Output('countChildren', 'data'),
    Input('cardActivity', 'n_clicks'),
    Input("cards-played", "children"),
    State('countChildren', 'data'),
    [State(i, 'className') for i in players],
    prevent_initial_call=True,
)
def setActive(n1, i, data, *args):
    selected_card = ctx.triggered_id
    active = list(args)
    if selected_card:
        countChildren = [data]
        if selected_card == 'cardActivity':
            act = random.randint(0,3)
            active = ['disabled']*len(list(args))
            active[act] = 'active'
            countChildren = [0]
        elif len(ctx.triggered[0]['value']) != data:
            countChildren = [len(ctx.triggered[0]['value'])]
            for i in range(len(active)):
                if active[i] == 'active':
                    active[i] = 'disabled'
                    if i >= len(active)-1:
                        active[0] = 'active'
                    else:
                        active[i+1] = 'active'
                    break
        return active + countChildren



if __name__ == "__main__":
    app.run_server(debug=True)
1 Like