Feat : line wrap
This commit is contained in:
@@ -7,6 +7,7 @@ class Translation(TypedDict):
|
||||
card_type: dict[str, str]
|
||||
effects: dict[str, str]
|
||||
numbers: dict[str, str]
|
||||
per: dict[str, str]
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -34,6 +35,7 @@ class Effect(TypedDict):
|
||||
effect: str
|
||||
amount: int
|
||||
effect_type: str | EffectType | None
|
||||
per: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -12,11 +12,19 @@
|
||||
"draw_n":"Piochez %a cartes.",
|
||||
"stun":"Assomez le champion ciblé.",
|
||||
"stack_next_card_bought":"Mettez la prochaine carte dont vous faites l'acquisition\nau dessus de votre pioche.",
|
||||
"sacrifice":"Vous pouvez sacrifier une carte de votre main ou de votre défausse.",
|
||||
"restack_discarded_champion":"Mettez un champion de votre défausse au dessus de votre pioche.",
|
||||
"make_discard":"L'adversaire ciblé se défausse d'une carte",
|
||||
"sacrifice":"Vous pouvez sacrifier une carte de votre main\nou de votre défausse.",
|
||||
"restack_discarded_champion":"Mettez un champion de votre défausse\nau dessus de votre pioche.",
|
||||
"make_discard":"L'adversaire ciblé se défausse d'une carte.",
|
||||
"draw_and_discard":"Vous pouvez piocher une carte.\nSi vous faites ainsi, défaussez vous d'une carte.",
|
||||
"play_next_card_bought":"Mettez dans votre main la prochaine carte dont vous faites l'acquisition."
|
||||
"play_next_card_bought":"Mettez dans votre main la prochaine carte\ndont vous faites l'acquisition."
|
||||
},
|
||||
"per":{
|
||||
"champion":"pour chaque Champion que vous avez en jeu",
|
||||
"cother_hampion":"pour chaque autre Champion que vous avez en jeu",
|
||||
"other_guard":"pour chaque autre Garde que vous avez en jeu",
|
||||
"other_card_of_same_faction":"pour chaque autre x que vous avez en jeu",
|
||||
"champion_of_same_faction":"pour chaque Champion x que vous avez en jeu",
|
||||
"other_knife_played":"pour chaque autre Couteau que vous avez en jeu"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
from typing import List
|
||||
from math import sin, cos, pi
|
||||
import drawsvg as dw
|
||||
import json
|
||||
|
||||
stats_radius = 22
|
||||
|
||||
circle_icon = dw.Circle(cx=0, cy=0, r=stats_radius)
|
||||
with open('src/data/translation_fr.json', encoding="utf-8") as f:
|
||||
translation_fr: dict = json.load(f)
|
||||
|
||||
def is_base_effect(array: dict):
|
||||
return not 'effect_type' in array.keys() or array['effect_type'] == 'champion_action'
|
||||
|
||||
def create_icon(amount: int, fill: str):
|
||||
group = dw.Group()
|
||||
group.append(dw.Use(circle_icon, fill=fill,x=0,y=0))
|
||||
group.append(dw.Text(amount, x=0, y=stats_radius+9, text_anchor="middle", fill="white", font_size=24, font_weight="bold", font_family='Helvetica'))
|
||||
return group
|
||||
|
||||
def create_damage_icon(amount: int):
|
||||
return create_icon(amount, "red")
|
||||
|
||||
def create_heal_icon(amount: int):
|
||||
return create_icon(amount, "green")
|
||||
|
||||
def create_gold_icon(amount: int):
|
||||
return create_icon(amount, "yellow")
|
||||
|
||||
|
||||
def draw_effects_resources_for_row(dwg: Drawing, effects: List, y: int, x_width: int):
|
||||
effects_generator = {
|
||||
"gold": create_gold_icon,
|
||||
"heal": create_heal_icon,
|
||||
"damage": create_damage_icon
|
||||
}
|
||||
effect_icons = list(filter(lambda e: e.get("effect") in effects_generator, effects))
|
||||
effect_icons_groups = [effects_generator[e.get("effect")](dwg, e.get("amount")) for e in effect_icons]
|
||||
|
||||
nb_effects = len(effect_icons_groups)
|
||||
for [i, e] in enumerate(effect_icons_groups):
|
||||
x_effect_pos = x_width/2 + (nb_effects*stats_radius/2) + i*stats_radius
|
||||
e.x = x_effect_pos
|
||||
e.y = y
|
||||
dwg.add(e)
|
||||
|
||||
def draw_effects(dwg: Drawing, card_effects: List[dict], x_width:int, border_width_x: int, row_1_base_y: int,row_2_base_y:int, row_1_to_2_separator_shorten_by: int, row_1_to_2_separator_y: int, effect_text_size: int):
|
||||
# TODO: figure out nb of effects and adjust row_1_x_offset accordingly
|
||||
|
||||
|
||||
|
||||
base_effects = list(filter(is_base_effect, card_effects))
|
||||
other_effects = list(filter(lambda x: not is_base_effect(x), card_effects))
|
||||
# card_effects = card_data['row_1']
|
||||
# row_1_nb_effects = len(card_data['row_1'].keys())
|
||||
|
||||
|
||||
# Draw row 1 stats
|
||||
draw_effects_resources_for_row(dwg, base_effects, row_1_base_y, x_width)
|
||||
# Draw row 1 text
|
||||
for effect in base_effects:
|
||||
|
||||
effect_text_1 = translation_fr["effects"].get(effect.get("effect"))
|
||||
if effect_text_1 is not None:
|
||||
dwg.add(dwg.text(effect_text_1, insert=(x_width/2, row_1_base_y + 57), text_anchor='middle', fill='black', font_size=str(effect_text_size) + 'px', font_family='Helvetica'))
|
||||
|
||||
if other_effects:
|
||||
# Draw row 1 to row 2 separator
|
||||
dwg.add(dwg.line(start=(0 + row_1_to_2_separator_shorten_by, row_1_to_2_separator_y), end=(x_width - row_1_to_2_separator_shorten_by, row_1_to_2_separator_y), stroke='black', stroke_width=1))
|
||||
|
||||
for effect in other_effects:
|
||||
# TODO handle case where there is both faction combo and trash can
|
||||
|
||||
if effect.get('effect_type') == 'faction_combo':
|
||||
row_2_icon_x = border_width_x + 35
|
||||
row_2_icon_y = row_2_base_y - 5
|
||||
dwg.add(dwg.circle(center=(row_2_icon_x + 1, row_2_icon_y + 1), r=15, fill='black'))
|
||||
dwg.add(dwg.circle(center=(row_2_icon_x, row_2_icon_y), r=15, fill='url(#grad2)'))
|
||||
# Draw row 2 stats
|
||||
draw_effects_resources_for_row(dwg, [effect], row_2_base_y - 25, x_width)
|
||||
|
||||
# Draw row 2 effect text
|
||||
effect_text_2 = ""
|
||||
if effect.get('effect') == 'prepare':
|
||||
effect_text_2 = "Mobilisez un champion."
|
||||
dwg.add(dwg.text(effect_text_2, insert=(x_width/2, row_2_base_y), text_anchor='middle', fill='black', font_size=str(effect_text_size) + 'px', font_family='Helvetica'))
|
||||
|
||||
def create_pentagon(center, radius):
|
||||
points = []
|
||||
for i in range(5):
|
||||
x = center[0] + radius * cos(2 * pi * i / 5 + (pi / 2))
|
||||
y = center[1] + radius * sin(2 * pi * i / 5 + (pi / 2))
|
||||
points.append((x, y))
|
||||
return points
|
||||
|
||||
def draw_champion_shield(dwg: Drawing, card_data: dict, x_width: int, y_height: int, border_width_x: int):
|
||||
if not card_data['guard']:
|
||||
pentagon_points = create_pentagon(center=(x_width - border_width_x - 15, y_height - 30), radius=28)
|
||||
dwg.add(dwg.polygon(points=pentagon_points, fill='darkgrey', stroke='#eee', stroke_width=1))
|
||||
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=27, fill='darkgrey'))
|
||||
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=25, fill='lightgrey'))
|
||||
dwg.add(dwg.text(str(card_data['defense']), insert=(x_width - border_width_x - 15, y_height - 20), text_anchor='middle', fill='black', font_size='28px', font_weight="bold", font_family='Helvetica'))
|
||||
else:
|
||||
pentagon_points = create_pentagon(center=(x_width - border_width_x - 15, y_height - 30), radius=28)
|
||||
dwg.add(dwg.polygon(points=pentagon_points, fill='black', stroke='lightgrey', stroke_width=1))
|
||||
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=27, fill='lightgrey'))
|
||||
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=25, fill='#111'))
|
||||
# Draw guard rectangle with text inside, above the shield
|
||||
dwg.add(dwg.rect(insert=(x_width - border_width_x - 40, y_height - 72), size=(49, 17), fill='lightgrey'))
|
||||
dwg.add(dwg.rect(insert=(x_width - border_width_x - 39, y_height - 71), size=(47, 15), fill='#111'))
|
||||
dwg.add(dwg.text('Garde', insert=(x_width - border_width_x - 15, y_height - 59), text_anchor='middle', fill='white', font_size='12px', font_weight="bold", font_family='Helvetica'))
|
||||
dwg.add(dwg.text(str(card_data['defense']), insert=(x_width - border_width_x - 15, y_height - 20), text_anchor='middle', fill='white', font_size='28px', font_weight="bold", font_family='Helvetica'))
|
||||
+48
-35
@@ -148,6 +148,51 @@ resourceIcons = {
|
||||
}
|
||||
|
||||
|
||||
def create_effect_text(effects: list[Effect], height: int, width: int):
|
||||
group = dw.Group()
|
||||
|
||||
effect_text = ""
|
||||
|
||||
for e in effects:
|
||||
if effect_text != "":
|
||||
effect_text += " "
|
||||
per = e.get('per')
|
||||
if per is not None:
|
||||
translation = f"+ x {translation_fr.get("per").get(per)}"
|
||||
elif e.get("amount", 1) > 1:
|
||||
translation = (
|
||||
translation_fr.get("effects")
|
||||
.get(e.get("effect") + "_n", e.get("effect"))
|
||||
.replace(
|
||||
"%a",
|
||||
str(translation_fr.get("numbers").get(str(e.get("amount", "")))),
|
||||
)
|
||||
)
|
||||
else:
|
||||
translation = translation_fr.get("effects").get(
|
||||
e.get("effect"), e.get("effect")
|
||||
)
|
||||
if(len(effect_text)>20):
|
||||
effect_text+="\n"
|
||||
effect_text += translation
|
||||
|
||||
font_size = min(effect_text_size, max((effect_text_size*2)-len(effect_text)*.5,11))
|
||||
group.append(
|
||||
dw.Text(
|
||||
effect_text,
|
||||
x=width / 2,
|
||||
y=(-font_size/2)*effect_text.count("\n"),
|
||||
text_anchor="middle",
|
||||
fill="black",
|
||||
# Attempt to estimate font width
|
||||
font_size=font_size,
|
||||
font_family="Helvetica",
|
||||
)
|
||||
)
|
||||
|
||||
return group
|
||||
|
||||
|
||||
def create_effect_row(effects: list[Effect], type: str, height: int, width: int):
|
||||
group = dw.Group()
|
||||
if type == "faction_combo":
|
||||
@@ -182,11 +227,9 @@ def create_effect_row(effects: list[Effect], type: str, height: int, width: int)
|
||||
)
|
||||
)
|
||||
effect_with_icons = list(
|
||||
filter(lambda x: x.get("effect") in resourceIcons, effects)
|
||||
)
|
||||
effect_with_text = list(
|
||||
filter(lambda x: x.get("effect") not in resourceIcons, effects)
|
||||
filter(lambda x: x.get("effect") in resourceIcons and not x.get("per"), effects)
|
||||
)
|
||||
effect_with_text = list(filter(lambda x: x not in effect_with_icons, effects))
|
||||
|
||||
text_y_pos = height - effect_text_size / 1.5
|
||||
if len(effect_with_icons) == 0:
|
||||
@@ -197,38 +240,8 @@ def create_effect_row(effects: list[Effect], type: str, height: int, width: int)
|
||||
if len(effect_with_text) == 0:
|
||||
icon_y_pos = height / 2
|
||||
|
||||
effect_text = ""
|
||||
|
||||
for e in effect_with_text:
|
||||
if effect_text != "":
|
||||
effect_text += " "
|
||||
|
||||
if e.get("amount", 1) > 1:
|
||||
|
||||
translation = (
|
||||
translation_fr.get("effects")
|
||||
.get(e.get("effect") + "_n", e.get("effect"))
|
||||
.replace(
|
||||
"%a",
|
||||
str(translation_fr.get("numbers").get(str(e.get("amount", "")))),
|
||||
)
|
||||
)
|
||||
else:
|
||||
translation = translation_fr.get("effects").get(
|
||||
e.get("effect"), e.get("effect")
|
||||
)
|
||||
effect_text += translation
|
||||
|
||||
group.append(
|
||||
dw.Text(
|
||||
effect_text,
|
||||
x=width / 2,
|
||||
y=text_y_pos,
|
||||
text_anchor="middle",
|
||||
fill="black",
|
||||
font_size=effect_text_size,
|
||||
font_family="Helvetica",
|
||||
)
|
||||
dw.Use(create_effect_text(effect_with_text, height, width), 0, text_y_pos)
|
||||
)
|
||||
|
||||
icon_radius = min(height / 3, stats_radius)
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
{
|
||||
"cards": [
|
||||
{
|
||||
"id": 1,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Arkus, Imperial Dragon",
|
||||
"cost": 8,
|
||||
"defense": 6,
|
||||
"guard": true,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "draw",
|
||||
"amount": 1,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 5,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 6,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Close Ranks",
|
||||
"cost": 3,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 5
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 2,
|
||||
"times": "per_champion"
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 6,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Command",
|
||||
"cost": 5,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "draw",
|
||||
"amount": 1
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 3
|
||||
},
|
||||
{
|
||||
"effect": "gold",
|
||||
"amount": 2
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Darian , War Mage",
|
||||
"cost": 4,
|
||||
"defense": 5,
|
||||
"guard": false,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 3,
|
||||
"effect_type": "champion_action",
|
||||
"mutex": 1
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 4,
|
||||
"effect_type": "champion_action",
|
||||
"mutex": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Domination",
|
||||
"cost": 7,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 6
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 6
|
||||
},
|
||||
{
|
||||
"effect": "draw",
|
||||
"amount": 1
|
||||
},
|
||||
{
|
||||
"effect": "prepare",
|
||||
"amount": 1,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Cristov, the Just",
|
||||
"cost": 5,
|
||||
"defense": 5,
|
||||
"guard": true,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 2,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 3,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "draw",
|
||||
"amount": 1,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Kraka, High Priest",
|
||||
"cost": 6,
|
||||
"defense": 6,
|
||||
"guard": false,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 2,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "draw",
|
||||
"amount": 1,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 2,
|
||||
"effect_type": "faction_combo",
|
||||
"times": "per_champion"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Man-at-Arms",
|
||||
"cost": 3,
|
||||
"defense": 4,
|
||||
"guard": true,
|
||||
"init_amount": 2,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 2,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 1,
|
||||
"times": "per_other_guard",
|
||||
"effect_type": "champion_action"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Master Weyan",
|
||||
"cost": 4,
|
||||
"defense": 4,
|
||||
"guard": true,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 3,
|
||||
"effect_type": "champion_action"
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 1,
|
||||
"times": "per_other_champion",
|
||||
"effect_type": "champion_action"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Rally the Troops",
|
||||
"cost": 4,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 5
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 5
|
||||
},
|
||||
{
|
||||
"effect": "prepare",
|
||||
"amount": 1,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Recruit",
|
||||
"cost": 2,
|
||||
"init_amount": 3,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "gold",
|
||||
"amount": 2
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 3
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 1,
|
||||
"times": "per_champion"
|
||||
},
|
||||
{
|
||||
"effect": "gold",
|
||||
"amount": 1,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"role": "market",
|
||||
"card_type": "champion",
|
||||
"faction": "yellow",
|
||||
"name": "Tits Priest",
|
||||
"cost": 2,
|
||||
"defense": 3,
|
||||
"guard": false,
|
||||
"init_amount": 2,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "gold",
|
||||
"amount": 1,
|
||||
"effect_type": "champion_action",
|
||||
"mutex": 1
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 1,
|
||||
"effect_type": "champion_action",
|
||||
"mutex": 1,
|
||||
"times": "per_champion"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Taxation",
|
||||
"cost": 1,
|
||||
"init_amount": 3,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "gold",
|
||||
"amount": 2
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 6,
|
||||
"effect_type": "faction_combo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"role": "market",
|
||||
"card_type": "action",
|
||||
"faction": "yellow",
|
||||
"name": "Word of Power",
|
||||
"cost": 6,
|
||||
"init_amount": 1,
|
||||
"effects": [
|
||||
{
|
||||
"effect": "draw",
|
||||
"amount": 2
|
||||
},
|
||||
{
|
||||
"effect": "heal",
|
||||
"amount": 5,
|
||||
"effect_type": "faction_combo"
|
||||
},
|
||||
{
|
||||
"effect": "damage",
|
||||
"amount": 5,
|
||||
"effect_type": "suicide"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user