demand_generation.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. """根据节日匹配结果生成需求。"""
  2. from __future__ import annotations
  3. from datetime import date
  4. from typing import Any, Literal
  5. GenerationType = Literal["year_festival", "festival", "year_festival_feature"]
  6. def _append_demand(
  7. items: list[dict[str, Any]],
  8. flat_names: list[str],
  9. seen_names: set[str],
  10. *,
  11. demand_name: str,
  12. generation_type: GenerationType,
  13. festival_name: str,
  14. feature_name: str = "",
  15. event_type: str = "",
  16. ) -> None:
  17. name = demand_name.strip()
  18. if not name:
  19. return
  20. items.append(
  21. {
  22. "demand_name": name,
  23. "generation_type": generation_type,
  24. "festival_name": festival_name,
  25. "feature_name": feature_name,
  26. "event_type": event_type,
  27. }
  28. )
  29. if name not in seen_names:
  30. seen_names.add(name)
  31. flat_names.append(name)
  32. def _matched_festivals_in_order(matches: list[dict[str, Any]]) -> list[str]:
  33. festivals: list[str] = []
  34. seen: set[str] = set()
  35. for item in matches:
  36. festival_name = str(item.get("festival_name") or "").strip()
  37. if not festival_name or festival_name in seen:
  38. continue
  39. seen.add(festival_name)
  40. festivals.append(festival_name)
  41. return festivals
  42. def _event_type_by_festival(matches: list[dict[str, Any]]) -> dict[str, str]:
  43. mapping: dict[str, str] = {}
  44. for item in matches:
  45. festival_name = str(item.get("festival_name") or "").strip()
  46. if not festival_name:
  47. continue
  48. mapping.setdefault(festival_name, str(item.get("event_type") or "").strip())
  49. return mapping
  50. def generate_demands_from_matches(
  51. matches: list[dict[str, Any]],
  52. *,
  53. query_date: date,
  54. ) -> dict[str, Any]:
  55. """根据匹配结果生成三种类型的需求。
  56. 1. year_festival: 当前年份 + 节日事件,如「2026 建党节」
  57. 2. festival: 节日事件本身,如「建党节」
  58. 3. year_festival_feature: 当前年份 + 节日事件 + 特征点,如「2026 劳动节 五一劳动节」
  59. """
  60. if not matches:
  61. return {
  62. "year": query_date.year,
  63. "generated_demands": [],
  64. "generated_demand_names": [],
  65. "generated_demand_count": 0,
  66. "demands_by_type": {
  67. "year_festival": [],
  68. "festival": [],
  69. "year_festival_feature": [],
  70. },
  71. }
  72. year = str(query_date.year)
  73. event_type_by_festival = _event_type_by_festival(matches)
  74. items: list[dict[str, Any]] = []
  75. flat_names: list[str] = []
  76. seen_names: set[str] = set()
  77. for festival_name in _matched_festivals_in_order(matches):
  78. event_type = event_type_by_festival.get(festival_name, "")
  79. _append_demand(
  80. items,
  81. flat_names,
  82. seen_names,
  83. demand_name=f"{year} {festival_name}",
  84. generation_type="year_festival",
  85. festival_name=festival_name,
  86. event_type=event_type,
  87. )
  88. _append_demand(
  89. items,
  90. flat_names,
  91. seen_names,
  92. demand_name=festival_name,
  93. generation_type="festival",
  94. festival_name=festival_name,
  95. event_type=event_type,
  96. )
  97. for item in matches:
  98. festival_name = str(item.get("festival_name") or "").strip()
  99. feature_name = str(item.get("demand_name") or "").strip()
  100. if not festival_name or not feature_name:
  101. continue
  102. _append_demand(
  103. items,
  104. flat_names,
  105. seen_names,
  106. demand_name=f"{year} {festival_name} {feature_name}",
  107. generation_type="year_festival_feature",
  108. festival_name=festival_name,
  109. feature_name=feature_name,
  110. event_type=str(item.get("event_type") or "").strip(),
  111. )
  112. demands_by_type: dict[str, list[str]] = {
  113. "year_festival": [],
  114. "festival": [],
  115. "year_festival_feature": [],
  116. }
  117. for item in items:
  118. generation_type = str(item.get("generation_type") or "")
  119. demand_name = str(item.get("demand_name") or "")
  120. if generation_type in demands_by_type and demand_name:
  121. demands_by_type[generation_type].append(demand_name)
  122. return {
  123. "year": query_date.year,
  124. "generated_demands": items,
  125. "generated_demand_names": flat_names,
  126. "generated_demand_count": len(flat_names),
  127. "demands_by_type": demands_by_type,
  128. }