feat: improve city selection for weather arts generation

- Introduce `get_recent_cities` to filter out cities that have been recently generated weather arts.
- Update `select_cities` method to exclude recent cities from the selection process, ensuring diversity in the generated arts.
- Modify the `select_countries` method to maintain its functionality while integrating recent city filtering.

This update enhances the system's ability to select active cities efficiently, reducing redundancy and improving the variety of generated weather arts by avoiding recent candidates.
This commit is contained in:
songtianlun 2025-02-17 12:58:16 +08:00
parent f1815afc41
commit 104597e3ba

View File

@ -15,7 +15,8 @@ class BatchGenerateWeatherArtsWorker
remaining_slots = [ remaining_slots, PER_RUN_GENERATION_LIMIT ].min
countries_to_process = select_countries
cities_to_process = select_cities(countries_to_process, remaining_slots)&.shuffle
recent_cities = get_recent_cities
cities_to_process = select_cities(recent_cities, countries_to_process, remaining_slots)&.shuffle
print_cities_list(cities_to_process, start_time)
skipped_cities = []
@ -39,6 +40,16 @@ class BatchGenerateWeatherArtsWorker
private
def get_recent_cities
cutoff_time = Time.current - GENERATION_INTERVAL
City.joins("LEFT JOIN (
SELECT city_id, MAX(created_at) as last_generation_time
FROM weather_arts
GROUP BY city_id
) latest_arts ON cities.id = latest_arts.city_id")
.where("latest_arts.last_generation_time < ?", cutoff_time)
end
def calculate_remaining_slots
today_generations = WeatherArt
.where("DATE(created_at) = ?", Date.today)
@ -50,9 +61,6 @@ class BatchGenerateWeatherArtsWorker
end
def select_countries
cutoff_time = Time.current - GENERATION_INTERVAL
Country.all.select do |country|
timezone_info = country.timezones.present? ? JSON.parse(country.timezones).first : { "zoneName" => "UTC" }
local_time = Time.current.in_time_zone(ActiveSupport::TimeZone[timezone_info["zoneName"]])
@ -60,10 +68,12 @@ class BatchGenerateWeatherArtsWorker
end
end
def select_cities(countries, limit)
def select_cities(recent_city, countries, limit)
cutoff_time = Time.current - GENERATION_INTERVAL
Rails.logger.debug "Select Cities with limit: #{limit}, in #{countries.size} countries."
# 第一阶段:筛选 active 城市
active_cities = City.where(active: true, country_id: countries.map(&:id)).limit(limit).to_a
# 第一阶段:筛选 active 城市, 排除最近生成过的城市
active_cities = City.where.not(id: recent_city.pluck(:id))
.where(active: true, country_id: countries.map(&:id)).limit(limit).to_a
selected = active_cities.first(limit)
remaining = limit - selected.size
Rails.logger.debug "Step1: Selected #{selected.size} cities with active city."
@ -79,17 +89,17 @@ class BatchGenerateWeatherArtsWorker
Rails.logger.debug "Step2: Selected #{remaining_every_country_count} cities in every country"
select_countries.each do |country|
c = City.where.not(id: select_countries.pluck(:id))
.where(country_id: country.id)
.order(Arel.sql("RANDOM()"))
.first(remaining_every_country_count)
c = City.where.not(id: recent_city.pluck(:id))
.where.not(id: select_countries.pluck(:id))
.where(country_id: country.id)
.order(Arel.sql("RANDOM()"))
.first(remaining_every_country_count)
if c.any? # 检查是否有有效的城市
Rails.logger.debug "== Selected city [#{c.first.name}] in country: [#{country.name}]"
selected << c
else
Rails.logger.debug "== No valid cities found in country: [#{country.name}]"
end
selected << c
end
Rails.logger.debug "Finished selected #{selected.size} cities."
selected