496 lines
19 KiB
GDScript
496 lines
19 KiB
GDScript
extends Control
|
|
|
|
# ============================================================================
|
|
# CafeCompanionPanel.gd - 咖啡店陪伴机器人面板
|
|
# ============================================================================
|
|
# 点击咖啡店陪伴机器人后,先展示付费时长选择;购买成功后才进入聊天。
|
|
# ============================================================================
|
|
|
|
@onready var chatFrame: PanelContainer = %CafeCompanionFrame
|
|
@onready var titleLabel: Label = %TitleLabel
|
|
@onready var subtitleLabel: Label = %SubtitleLabel
|
|
@onready var productList: VBoxContainer = %ProductList
|
|
@onready var purchaseButton: Button = %PurchaseButton
|
|
@onready var statusLabel: Label = %StatusLabel
|
|
@onready var chatHistory: ScrollContainer = %ChatHistory
|
|
@onready var messageList: VBoxContainer = %MessageList
|
|
@onready var chatInput: LineEdit = %ChatInput
|
|
@onready var sendButton: Button = %SendButton
|
|
@onready var closeButton: Button = %CloseButton
|
|
|
|
var _currentSessionId: String = ""
|
|
var _currentTarget: Dictionary = {}
|
|
var _products: Array = []
|
|
var _selectedMinutes: int = 0
|
|
var _waitingForReply: bool = false
|
|
var _resignTarget: Dictionary = {}
|
|
var _resignDialog: Control
|
|
var _resignLabel: Label
|
|
var _resignConfirmButton: Button
|
|
var _resignCancelButton: Button
|
|
|
|
func _ready() -> void:
|
|
chatFrame.visible = false
|
|
purchaseButton.pressed.connect(_on_purchase_pressed)
|
|
sendButton.pressed.connect(_on_send_pressed)
|
|
closeButton.pressed.connect(_on_close_pressed)
|
|
chatInput.text_submitted.connect(_on_input_submitted)
|
|
_build_resign_dialog()
|
|
_connect_events()
|
|
_set_chat_enabled(false)
|
|
|
|
func _exit_tree() -> void:
|
|
var eventSystem := get_node_or_null("/root/EventSystem")
|
|
if eventSystem != null:
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_SELECTED, _on_cafe_companion_selected, self)
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_SELF_SELECTED, _on_cafe_companion_self_selected, self)
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_PRODUCTS_READY, _on_products_ready, self)
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_CHAT_TIME_PURCHASED, _on_chat_time_purchased, self)
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_MESSAGE_RECEIVED, _on_message_received, self)
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_EMPLOYMENT_RESIGNED, _on_employment_resigned, self)
|
|
eventSystem.call("disconnect_event", EventNames.CAFE_COMPANION_ERROR_OCCURRED, _on_companion_error, self)
|
|
|
|
func _connect_events() -> void:
|
|
var eventSystem := get_node_or_null("/root/EventSystem")
|
|
if eventSystem == null:
|
|
push_warning("CafeCompanionPanel: EventSystem autoload is not available.")
|
|
return
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_SELECTED, _on_cafe_companion_selected, self)
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_SELF_SELECTED, _on_cafe_companion_self_selected, self)
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_PRODUCTS_READY, _on_products_ready, self)
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_CHAT_TIME_PURCHASED, _on_chat_time_purchased, self)
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_MESSAGE_RECEIVED, _on_message_received, self)
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_EMPLOYMENT_RESIGNED, _on_employment_resigned, self)
|
|
eventSystem.call("connect_event", EventNames.CAFE_COMPANION_ERROR_OCCURRED, _on_companion_error, self)
|
|
|
|
func _on_cafe_companion_selected(data: Dictionary) -> void:
|
|
_currentTarget = data.duplicate(true)
|
|
_currentSessionId = ""
|
|
_waitingForReply = false
|
|
_selectedMinutes = 0
|
|
_clear_messages()
|
|
|
|
titleLabel.text = _format_target_title(data)
|
|
subtitleLabel.text = _format_target_subtitle(data)
|
|
statusLabel.text = "请选择陪聊时长"
|
|
purchaseButton.text = "购买聊天时间"
|
|
purchaseButton.disabled = true
|
|
chatFrame.visible = true
|
|
_set_chat_enabled(false)
|
|
|
|
var manager := _get_cafe_companion_manager()
|
|
if manager == null or not manager.has_method("get_chat_time_products"):
|
|
_set_error("CafeCompanionManager 未加载")
|
|
return
|
|
manager.call("get_chat_time_products")
|
|
|
|
func _on_cafe_companion_self_selected(data: Dictionary) -> void:
|
|
_resignTarget = data.duplicate(true)
|
|
_resignLabel.text = _format_resign_message(data)
|
|
_resignDialog.visible = true
|
|
_resignDialog.modulate.a = 0.0
|
|
var tween := create_tween()
|
|
tween.tween_property(_resignDialog, "modulate:a", 1.0, 0.12)
|
|
|
|
func _on_employment_resigned(data: Dictionary) -> void:
|
|
_hide_resign_dialog()
|
|
_set_error(_format_resign_result(data))
|
|
chatFrame.visible = false
|
|
|
|
func _on_products_ready(data: Dictionary) -> void:
|
|
if not chatFrame.visible:
|
|
return
|
|
var productsVariant: Variant = data.get("products", [])
|
|
_products = productsVariant if productsVariant is Array else []
|
|
_render_products()
|
|
if _products.is_empty():
|
|
statusLabel.text = "暂时没有可购买的陪聊时长"
|
|
else:
|
|
statusLabel.text = "点击时长后购买,购买成功才会进入聊天"
|
|
|
|
func _on_chat_time_purchased(data: Dictionary) -> void:
|
|
var sessionData: Dictionary = data
|
|
var sessionVariant: Variant = data.get("session", {})
|
|
if sessionVariant is Dictionary:
|
|
sessionData = sessionVariant
|
|
|
|
var servicePointId := str(sessionData.get("service_point_id", ""))
|
|
if not _currentTarget.is_empty() and servicePointId != str(_currentTarget.get("service_point_id", "")):
|
|
return
|
|
|
|
_currentSessionId = str(sessionData.get("session_id", ""))
|
|
_waitingForReply = false
|
|
_set_chat_enabled(true)
|
|
statusLabel.text = _format_purchase_status(data, sessionData)
|
|
|
|
var companionVariant: Variant = sessionData.get("companion", {})
|
|
if companionVariant is Dictionary:
|
|
var companion: Dictionary = companionVariant
|
|
titleLabel.text = str(companion.get("persona_name", titleLabel.text)).strip_edges()
|
|
|
|
_clear_messages()
|
|
var messagesVariant: Variant = sessionData.get("messages", [])
|
|
if messagesVariant is Array and not messagesVariant.is_empty():
|
|
for messageVariant in messagesVariant:
|
|
if messageVariant is Dictionary:
|
|
var message: Dictionary = messageVariant
|
|
_add_message(str(message.get("role", "assistant")), str(message.get("content", "")))
|
|
else:
|
|
var welcomeMessage := str(sessionData.get("welcome_message", "")).strip_edges()
|
|
if not welcomeMessage.is_empty():
|
|
_add_message("assistant", welcomeMessage)
|
|
|
|
chatInput.grab_focus()
|
|
|
|
func _on_message_received(data: Dictionary) -> void:
|
|
if str(data.get("session_id", "")) != _currentSessionId:
|
|
return
|
|
_waitingForReply = false
|
|
_set_chat_enabled(true)
|
|
statusLabel.text = _format_remaining_status(data)
|
|
|
|
var messageVariant: Variant = data.get("assistant_message", {})
|
|
if messageVariant is Dictionary:
|
|
var message: Dictionary = messageVariant
|
|
_add_message("assistant", str(message.get("content", "")))
|
|
|
|
func _on_companion_error(data: Dictionary) -> void:
|
|
if not chatFrame.visible and not (_resignDialog != null and _resignDialog.visible):
|
|
return
|
|
if _resignDialog != null and _resignDialog.visible and is_instance_valid(_resignLabel):
|
|
_resignLabel.text = str(data.get("message", "咖啡店陪聊暂时不可用"))
|
|
_resignConfirmButton.disabled = false
|
|
return
|
|
_set_error(str(data.get("message", "咖啡店陪聊暂时不可用")))
|
|
|
|
func _render_products() -> void:
|
|
for child in productList.get_children():
|
|
child.queue_free()
|
|
|
|
for productVariant in _products:
|
|
if not (productVariant is Dictionary):
|
|
continue
|
|
var product: Dictionary = productVariant
|
|
var minutes := int(product.get("minutes", 0))
|
|
if minutes <= 0:
|
|
continue
|
|
var button := Button.new()
|
|
button.toggle_mode = true
|
|
button.focus_mode = Control.FOCUS_NONE
|
|
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
button.text = _format_product_label(product)
|
|
button.pressed.connect(func() -> void:
|
|
_select_product(minutes)
|
|
)
|
|
productList.add_child(button)
|
|
|
|
func _select_product(minutes: int) -> void:
|
|
_selectedMinutes = minutes
|
|
for child in productList.get_children():
|
|
var button := child as Button
|
|
if button != null:
|
|
button.button_pressed = button.text.begins_with("%d分钟" % minutes)
|
|
purchaseButton.disabled = false
|
|
purchaseButton.text = "购买 %d 分钟" % minutes
|
|
|
|
func _on_purchase_pressed() -> void:
|
|
if _selectedMinutes <= 0:
|
|
statusLabel.text = "请先选择陪聊时长"
|
|
return
|
|
var manager := _get_cafe_companion_manager()
|
|
if manager == null or not manager.has_method("purchase_chat_time"):
|
|
_set_error("CafeCompanionManager 未加载")
|
|
return
|
|
purchaseButton.disabled = true
|
|
statusLabel.text = "正在购买陪聊时长..."
|
|
manager.call("purchase_chat_time", _currentTarget, _selectedMinutes)
|
|
|
|
func _on_send_pressed() -> void:
|
|
_send_current_message()
|
|
|
|
func _on_input_submitted(_text: String) -> void:
|
|
_send_current_message()
|
|
|
|
func _send_current_message() -> void:
|
|
if _waitingForReply:
|
|
return
|
|
var content := chatInput.text.strip_edges()
|
|
if content.is_empty():
|
|
return
|
|
if _currentSessionId.is_empty():
|
|
_set_error("请先购买陪聊时长")
|
|
return
|
|
|
|
chatInput.clear()
|
|
_add_message("user", content)
|
|
_waitingForReply = true
|
|
_set_chat_enabled(false)
|
|
statusLabel.text = "对方正在回复..."
|
|
|
|
var manager := _get_cafe_companion_manager()
|
|
if manager == null or not manager.has_method("send_chat_message"):
|
|
_set_error("CafeCompanionManager 未加载")
|
|
return
|
|
manager.call("send_chat_message", _currentSessionId, content)
|
|
|
|
func _on_close_pressed() -> void:
|
|
chatFrame.visible = false
|
|
_waitingForReply = false
|
|
chatInput.release_focus()
|
|
|
|
func _confirm_resign() -> void:
|
|
var servicePointId := str(_resignTarget.get("service_point_id", "")).strip_edges()
|
|
if servicePointId.is_empty():
|
|
_set_error("离职目标不存在")
|
|
return
|
|
var manager := _get_cafe_companion_manager()
|
|
if manager == null or not manager.has_method("resign_employment"):
|
|
_set_error("CafeCompanionManager 未加载")
|
|
return
|
|
_resignConfirmButton.disabled = true
|
|
_resignLabel.text = "正在办理离职..."
|
|
manager.call("resign_employment", servicePointId)
|
|
|
|
func _hide_resign_dialog() -> void:
|
|
if is_instance_valid(_resignDialog):
|
|
_resignDialog.visible = false
|
|
if is_instance_valid(_resignConfirmButton):
|
|
_resignConfirmButton.disabled = false
|
|
|
|
func _set_error(message: String) -> void:
|
|
_waitingForReply = false
|
|
_set_chat_enabled(not _currentSessionId.is_empty())
|
|
purchaseButton.disabled = _selectedMinutes <= 0
|
|
statusLabel.text = message
|
|
|
|
func _set_chat_enabled(enabled: bool) -> void:
|
|
chatInput.editable = enabled
|
|
sendButton.disabled = not enabled
|
|
|
|
func _clear_messages() -> void:
|
|
for child in messageList.get_children():
|
|
child.queue_free()
|
|
|
|
func _add_message(role: String, content: String) -> void:
|
|
var normalizedContent := content.strip_edges()
|
|
if normalizedContent.is_empty():
|
|
return
|
|
|
|
var row := HBoxContainer.new()
|
|
row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
row.alignment = BoxContainer.ALIGNMENT_END if role == "user" else BoxContainer.ALIGNMENT_BEGIN
|
|
|
|
var bubble := PanelContainer.new()
|
|
bubble.custom_minimum_size = Vector2(120, 0)
|
|
bubble.size_flags_horizontal = 0
|
|
bubble.add_theme_stylebox_override("panel", _make_bubble_style(role))
|
|
|
|
var margin := MarginContainer.new()
|
|
margin.add_theme_constant_override("margin_left", 14)
|
|
margin.add_theme_constant_override("margin_top", 8)
|
|
margin.add_theme_constant_override("margin_right", 14)
|
|
margin.add_theme_constant_override("margin_bottom", 8)
|
|
|
|
var label := Label.new()
|
|
label.text = normalizedContent
|
|
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
label.custom_minimum_size = Vector2(300, 0)
|
|
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
label.add_theme_color_override("font_color", Color(0.16, 0.20, 0.25, 1))
|
|
label.add_theme_font_size_override("font_size", 16)
|
|
|
|
margin.add_child(label)
|
|
bubble.add_child(margin)
|
|
row.add_child(bubble)
|
|
messageList.add_child(row)
|
|
call_deferred("_scroll_to_bottom")
|
|
|
|
func _make_bubble_style(role: String) -> StyleBoxFlat:
|
|
var style := StyleBoxFlat.new()
|
|
style.bg_color = Color(0.80, 0.92, 0.98, 1) if role == "user" else Color(1, 1, 1, 0.96)
|
|
style.border_color = Color(0.55, 0.72, 0.82, 0.35)
|
|
style.set_border_width_all(1)
|
|
style.set_corner_radius_all(10)
|
|
return style
|
|
|
|
func _scroll_to_bottom() -> void:
|
|
if is_instance_valid(chatHistory):
|
|
chatHistory.scroll_vertical = int(chatHistory.get_v_scroll_bar().max_value)
|
|
|
|
func _get_cafe_companion_manager() -> Node:
|
|
return get_node_or_null("/root/CafeCompanionManager")
|
|
|
|
func _build_resign_dialog() -> void:
|
|
_resignDialog = Control.new()
|
|
_resignDialog.name = "CafeEmploymentResignDialog"
|
|
_resignDialog.set_anchors_preset(Control.PRESET_CENTER)
|
|
_resignDialog.custom_minimum_size = Vector2(460, 240)
|
|
_resignDialog.offset_left = -230
|
|
_resignDialog.offset_top = -120
|
|
_resignDialog.offset_right = 230
|
|
_resignDialog.offset_bottom = 120
|
|
_resignDialog.visible = false
|
|
_resignDialog.mouse_filter = Control.MOUSE_FILTER_STOP
|
|
add_child(_resignDialog)
|
|
|
|
var bg := PanelContainer.new()
|
|
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
|
|
bg.add_theme_stylebox_override("panel", _make_dialog_style())
|
|
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
_resignDialog.add_child(bg)
|
|
|
|
var margin := MarginContainer.new()
|
|
margin.set_anchors_preset(Control.PRESET_FULL_RECT)
|
|
margin.add_theme_constant_override("margin_left", 28)
|
|
margin.add_theme_constant_override("margin_top", 28)
|
|
margin.add_theme_constant_override("margin_right", 28)
|
|
margin.add_theme_constant_override("margin_bottom", 24)
|
|
_resignDialog.add_child(margin)
|
|
|
|
var box := VBoxContainer.new()
|
|
box.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
box.add_theme_constant_override("separation", 18)
|
|
margin.add_child(box)
|
|
|
|
_resignLabel = Label.new()
|
|
_resignLabel.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
_resignLabel.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
_resignLabel.add_theme_font_size_override("font_size", 18)
|
|
_resignLabel.add_theme_color_override("font_color", Color(0.16, 0.22, 0.28, 1))
|
|
box.add_child(_resignLabel)
|
|
|
|
var row := HBoxContainer.new()
|
|
row.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
row.add_theme_constant_override("separation", 12)
|
|
box.add_child(row)
|
|
|
|
_resignCancelButton = _make_dialog_button("继续打工", false)
|
|
_resignCancelButton.pressed.connect(_hide_resign_dialog)
|
|
row.add_child(_resignCancelButton)
|
|
|
|
_resignConfirmButton = _make_dialog_button("确认离职", true)
|
|
_resignConfirmButton.pressed.connect(_confirm_resign)
|
|
row.add_child(_resignConfirmButton)
|
|
|
|
func _make_dialog_button(textValue: String, primary: bool) -> Button:
|
|
var button := Button.new()
|
|
button.text = textValue
|
|
button.custom_minimum_size = Vector2(128, 42)
|
|
button.focus_mode = Control.FOCUS_NONE
|
|
button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
|
button.add_theme_font_size_override("font_size", 16)
|
|
button.add_theme_color_override("font_color", Color.WHITE if primary else Color(0.16, 0.22, 0.28, 1))
|
|
if not primary:
|
|
button.add_theme_color_override("font_hover_color", Color(0.258824, 0.627451, 0.913725))
|
|
button.add_theme_color_override("font_pressed_color", Color(0.060, 0.270, 0.540, 1.0))
|
|
button.add_theme_color_override("font_disabled_color", Color(0.520, 0.600, 0.680, 0.55))
|
|
button.add_theme_stylebox_override("normal", _make_dialog_button_style(primary, false))
|
|
button.add_theme_stylebox_override("hover", _make_dialog_button_style(primary, true))
|
|
button.add_theme_stylebox_override("pressed", _make_dialog_button_style(primary, false))
|
|
button.add_theme_stylebox_override("focus", StyleBoxEmpty.new())
|
|
return button
|
|
|
|
func _make_dialog_style() -> StyleBoxFlat:
|
|
var style := StyleBoxFlat.new()
|
|
style.bg_color = Color(0.982, 0.995, 1.0, 0.98)
|
|
style.border_color = Color(0.46, 0.62, 0.70, 0.28)
|
|
style.set_border_width_all(1)
|
|
style.set_corner_radius_all(16)
|
|
style.shadow_color = Color(0.06, 0.09, 0.12, 0.22)
|
|
style.shadow_size = 12
|
|
style.shadow_offset = Vector2(0, 5)
|
|
return style
|
|
|
|
func _make_dialog_button_style(primary: bool, hover: bool) -> StyleBoxFlat:
|
|
var style := StyleBoxFlat.new()
|
|
if primary:
|
|
style.bg_color = Color(0.78, 0.26, 0.22, 1.0) if not hover else Color(0.88, 0.32, 0.26, 1.0)
|
|
else:
|
|
style.bg_color = Color(0.90, 0.96, 0.98, 1.0) if not hover else Color(0.84, 0.93, 0.97, 1.0)
|
|
style.set_corner_radius_all(10)
|
|
return style
|
|
|
|
func _format_resign_message(data: Dictionary) -> String:
|
|
var personaName := str(data.get("persona_name", "陪伴机器人")).strip_edges()
|
|
var endsAt := str(data.get("employment_ends_at", "")).strip_edges()
|
|
var message := "确认结束「%s」的咖啡店打工?" % personaName
|
|
if not endsAt.is_empty():
|
|
message += "\n原定结束时间:%s" % endsAt
|
|
message += "\n提前离职会按剩余工时扣回部分已获得收益。"
|
|
return message
|
|
|
|
func _format_resign_result(data: Dictionary) -> String:
|
|
var penaltyVariant: Variant = data.get("penalty", {})
|
|
if penaltyVariant is Dictionary:
|
|
var penalty: Dictionary = penaltyVariant
|
|
var amount := int(penalty.get("amount", 0))
|
|
if amount > 0:
|
|
return "已离职,扣回 %d 鲸币收益" % amount
|
|
return "已结束咖啡店雇佣"
|
|
|
|
func _format_target_title(data: Dictionary) -> String:
|
|
var personaName := str(data.get("persona_name", "陪伴机器人")).strip_edges()
|
|
return personaName if not personaName.is_empty() else "陪伴机器人"
|
|
|
|
func _format_target_subtitle(data: Dictionary) -> String:
|
|
var servicePointLabel := _format_service_point_label(str(data.get("service_point_id", "")))
|
|
return "鲸鱼咖啡馆 · %s" % servicePointLabel if not servicePointLabel.is_empty() else "鲸鱼咖啡馆"
|
|
|
|
func _format_service_point_label(servicePointId: String) -> String:
|
|
if servicePointId.begins_with("ServiceIdlePoint"):
|
|
var pointNumber := _parse_point_number(servicePointId)
|
|
if pointNumber > 0:
|
|
return "%s号陪伴位" % _format_chinese_number(pointNumber)
|
|
return ""
|
|
|
|
func _format_product_label(product: Dictionary) -> String:
|
|
var minutes := int(product.get("minutes", 0))
|
|
var price := int(product.get("price", 0))
|
|
return "%d分钟 · %d鲸币" % [minutes, price]
|
|
|
|
func _format_purchase_status(data: Dictionary, sessionData: Dictionary) -> String:
|
|
var price := 0
|
|
var purchaseVariant: Variant = data.get("purchase", {})
|
|
if purchaseVariant is Dictionary:
|
|
price = int((purchaseVariant as Dictionary).get("price", 0))
|
|
elif data.has("product") and data.get("product") is Dictionary:
|
|
price = int((data.get("product") as Dictionary).get("price", 0))
|
|
var remaining := _format_remaining_status(sessionData)
|
|
if price > 0:
|
|
return "已购买,花费%d鲸币,%s" % [price, remaining]
|
|
return "已购买,%s" % remaining
|
|
|
|
func _format_remaining_status(data: Dictionary) -> String:
|
|
var seconds := int(data.get("remaining_seconds", 0))
|
|
if seconds <= 0:
|
|
var expiresText := str(data.get("expires_at", "")).strip_edges()
|
|
return "陪聊时间已开启" if expiresText.is_empty() else "陪聊结束时间 %s" % expiresText
|
|
var minutes := int(ceil(seconds / 60.0))
|
|
return "剩余约 %d 分钟" % minutes
|
|
|
|
func _parse_point_number(value: String) -> int:
|
|
var digits := ""
|
|
for index in range(value.length()):
|
|
var character := value.substr(index, 1)
|
|
if character >= "0" and character <= "9":
|
|
digits += character
|
|
return int(digits) if not digits.is_empty() else 0
|
|
|
|
func _format_chinese_number(value: int) -> String:
|
|
const CHINESE_DIGITS: Array[String] = [
|
|
"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"
|
|
]
|
|
if value <= 0:
|
|
return str(value)
|
|
if value < 10:
|
|
return CHINESE_DIGITS[value]
|
|
if value == 10:
|
|
return "十"
|
|
if value < 20:
|
|
return "十%s" % CHINESE_DIGITS[value - 10]
|
|
if value < 100:
|
|
var tens := value / 10
|
|
var ones := value % 10
|
|
return "%s十%s" % [CHINESE_DIGITS[tens], CHINESE_DIGITS[ones]] if ones > 0 else "%s十" % CHINESE_DIGITS[tens]
|
|
return str(value)
|